소리 분류 모델을 이용하여 사용자 인터페이스를 만들어 보았다.
소리 데이터를 넣으면 개, 고양이 중 분류를 하여 화면에 나타내준다.
확률도 같이 나오게 했다.
사용자 인터페이스를 만든 과정을 보자
[1] 필요한 패키지 로드
# 1.필요한 패키지 전부 로드
import tkinter as tk
from tkinter import filedialog
from tkinter import *
from PIL import ImageTk, Image
import numpy as np
from keras.models import load_model
import cv2
import numpy
import glob
import librosa
from pygame import mixer #소리 재생 모듈
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
[2] 소리 업로드 함수 생성
# 2. upload_sound 함수 생성
def upload_sound():
try:
global file_path
global x_test_features
file_path=filedialog.askopenfilename() #윈도우 탐색기 열기
x_test = librosa.load(file_path)[0] # 숫자로 변환
wave_rate = librosa.load(file_path)[1] # 주파수 대역 추출
x_test_features = extract_features( x_test, wave_rate ) # 41개의 학습 데이터 만든 후에
except:
pass # try와 except 사이에 문제가 생겨도 그냥 무시해라
[3] MFCC 함수 생성 (음성에서 feature 뽑아내는 과정)
feature은 소리의 주파수 스펙트럼 데이터 40개 + zero_crossing 1개
# (2) 음성에서 특징을 뽑아내는 함수 생성
# 특징은 소리의 주파수 스펙트럼 데이터 40개 + zero_crossing_rate 1개
# 전처리를 위해 필요한 함수를 불러옵니다.
def extract_features(audio_samples, sample_rate): # 음성의 특징을 추출하는 함수
extracted_features = np.empty((0, 41, )) # (1,41) 은 아니고 그냥 41개의 값을 받을 비어있는 리스트를 할당하겠다는 뜻
if not isinstance(audio_samples, list):# 리스트가 아니라면
audio_samples = [audio_samples] # 리스트화 해라
for sample in audio_samples: # 진폭 데이터 리스트를 하나씩 가져옵니다.
zero_cross_feat = librosa.feature.zero_crossing_rate(sample).mean() # 음성 신호 파형이 중심축(0) 을 통과하는 횟수
mfccs = librosa.feature.mfcc(y=sample, sr=sample_rate, n_mfcc=40) # https://youdaeng-com.tistory.com/5
mfccsscaled = np.mean(mfccs.T,axis=0) # 각 주파수별 평균값을 구합니다. #https://stackoverflow.com/questions/36182697/why-does-librosa-librosa-feature-mfcc-spit-out-a-2d-array
mfccsscaled = np.append(mfccsscaled, zero_cross_feat) # 주파수 40개에 대한 평균값 40개와 zero_cross_feat 값 를 가지고
mfccsscaled = mfccsscaled.reshape(1, 41, ) # 41개의 값을 학습 데이터로 구성합니다. [[293,291,293,...392]]
extracted_features = np.vstack((extracted_features, mfccsscaled)) #[[293,291,293,...392]]
return extracted_features
[4] 음성을 모델에 넣고 개,고양이인지 분류하는 classify 함수 생성
# 4 음성을 모델에 넣고 결과를 출력하는 classify 라는 함수 생성
# 음성 --> 모델 --> 결과(cat 또는 dog)
def classify():
pred = model.predict( x_test_features.reshape( 1, 41, ) ) # 모델에 넣고 예측해라
a = np.argmax(pred) # # 가장 큰 원소의 인덱스 번호 추출 (확률 큰 값 추출해라)
if a == 0:
sign='This sound is a cat sound'
image_path = 'c:\\sound\\cat_image2.png'
else:
sign='This sound is a dog sound'
image_path = 'c:\\sound\\dog_imge3.png'
uploaded = Image.open(image_path) # os에 있는 이미지를 불러옵니다
uploaded.thumbnail(( (top.winfo_width()/2.25), (top.winfo_height()/2.25) )) # 사이즈 조정
img = ImageTk.PhotoImage(uploaded)
sign_image.configure(image=img) # 불러온 사진을 sign_image 라는 변수로 구성
sign_image.image = img # 불러온 사진을 sign_image.imge 에 담기
sign_image.pack() # 불러온 사진을 완전히 지정하고
sign_image.place(relx=0.35, rely=0.2) # 위치 시키기
label.configure(foreground='#011638', text= sign) # sign이 할당된 글씨를 배경에 붙임
label.place(x=115, y=50)
Draw_graph(pred) # 분류 버튼을 누루면 그래프가 그려지도록 여기에 둡니다.
[5] 모델 결과 확률 그래프 그리는 함수
# 6 확률 그래프 그리는 함수
def Draw_graph(pred):
global top
fig=plt.Figure(figsize=(6.5,0.5), facecolor='grey') # 그래프의 크기와 색깔 지정 #e5ddff
plot = FigureCanvasTkAgg( fig, master=top) #tkinter 위에 그래프 올리기
# 확률 숫자 생성
y = [ 'cat %0.3f'%pred[0][0], 'dog %0.3f'%pred[0][1] ] # 소수점이하 3번째까지만 2개의 확률저장
# 그래프 그리기
fig.add_subplot(1,1,1).barh( y , pred[0], color='black') # 그래프 그리기 , 막대 색깔 설정
plot.draw() # 그래프 그리기
plot.get_tk_widget().pack() # 그래프 설정을 저장하기
plot.get_tk_widget().place( x =110, y=400 ) # 그래프 위치 지정하기
[6] 소리 재생하는 함수
# 6. 소리 재생하는 함수
def Play():
if file_path: # file_path 에 음원의 위치와 이름이 들어있다면
mixer.init() # 초기화 작업 수행
mixer.music.load(file_path) #음원을 불러들임
mixer.music.play() # 음원 재생
우선 여기까지 함수들을 모두 생성해보았다.
이제는 GUI 사용자 인터페이스 화면을 구현하는 코드를 생성하겠다.
[7] 사용자 인터페이스 화면 생성
# 7. 사용자 인터페이스 생성 하기
# (1). 사용자 인터페이스 배경 화면 생성
top=tk.Tk() # tkinger (GUI 전문 모듈) 객체화 시키겠다
top.geometry('800x600') # 화면 크기
top.title('cat and dog sound Classification')
top.configure(background='#b32717') # 맨 위 제목 색깔 # 구글: #CDCDCD
# (2).업로드 버튼
upload=Button(top,text="Upload an sound",command=upload_sound,padx=10,pady=5)
upload.configure(background='white',foreground='black',font=('arial',10,'bold')) # 버튼 색깔
upload.pack(side=BOTTOM,pady=50) # 버튼 위치 (TOP, BOTTOM,LEFT, RIGHT)
upload.place(relx=0.2,rely=0.8)
# (3) 분류 버튼
classify_b=Button(top,text="Classfiy an Sound",command=classify,padx=10,pady=5)
classify_b.configure(background='white', foreground='black',font=('arial',10,'bold')) # 버튼 색깔
classify_b.pack(side=BOTTOM,pady=50) # 버튼 위치 (TOP, BOTTOM,LEFT, RIGHT)
classify_b.place(relx=0.6,rely=0.8)
# (4) 소리 재생 버튼
btn_play = Button(top,text ='Play',width = 10,font=('Courier',10),command=Play)
btn_play.place(x=280, y=400) # 버튼 위치 지정
# 소리 멈춤 버튼
btn_stop = Button(top,text ='Stop',width = 10,font=('Courier',10),command=Play)
btn_stop.place(x=400, y=400) # 버튼 위치 지정
# (5) 사진
sign_image=Label(top,background='#b32717')
sign_image.pack(side=BOTTOM,expand=True)
sign_image.place(relx=0.5, rely=0.3)
# (5) 화면 배경에 클래스 사진 출력
label = Label(top, background='#b32717',font=('arial',35,'bold'))
label.pack(side=BOTTOM,expand=True)
#################### 저작권 문구 #####################################
copy = Label(top,font=('Curier',8,'normal'),
text="Copyright 2022. eunsung Corp. All rights reserved. send email to @naver.com for use.",
background='#e5ddff', fg="black") # compound 는 text 자리 지정
copy.configure(background='#b32717',foreground='black',font=('Courier',8,'normal'))
copy.pack(side=BOTTOM, anchor = 's', expand=False)
copy.place(relx=0.1, rely=0.97)
top.mainloop() # 무조건 맨아래 하나
'파이썬' 카테고리의 다른 글
오늘 다시 구글링한 부분 (0) | 2022.12.26 |
---|