본문 바로가기

파이썬

tkinter 파이썬으로 GUI 사용자 인터페이스 만들기

내가 구현한 사용자 인터페이스 화면

소리 분류 모델을 이용하여 사용자 인터페이스를 만들어 보았다.

소리 데이터를 넣으면 개, 고양이 중 분류를 하여 화면에 나타내준다.

확률도 같이 나오게 했다.

 

사용자 인터페이스를 만든 과정을 보자

 

[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