# <h1>Hand Posture Recognition with CNN</h1> ###### tags: `深度學習` `Python` `大三` ## 目錄 <ul> <li>目錄</li> <li> 問題 <ul> <li>問題內容</li> </ul> </li> <li> 解決過程 <ul> <li>產生訓練資料以及測試資料</li> <li>建立模型</li> <li>訓練模型</li> <li>繪製loss圖以及accuracy圖</li> <li>顯示訓練後的結果以及圖</li> </ul> </li> </ul> ## 問題 ### 問題內容: 設計模型來辨識三種不同的手勢, 可獲得5張在不同照片下從不同人物處捕獲的數據集 拍攝條件。每個數據集中的樣本存儲在9個單獨的目錄中。 目錄0000〜0002、0003〜0005和0006〜0008包含狀態1、2的樣本和3。 每個目錄有20個樣本。每個樣本都是32x32的灰度圖像像素。 ## 解決過程 在程式碼中,會需要import以下資料: ``` import cv2 import numpy as np import os from keras import layers from keras import models from keras.utils import to_categorical import matplotlib.pyplot as plt ``` ### 產生訓練資料以及測試資料: ``` def enumerate_files(dirs, path='All_gray_1_32_32', n_poses=3,n_samples=20): #從路徑中獲得資料放入filenames,targets中 filenames, targets = [], [] for p in dirs: for n in range(n_poses): for j in range(3): dir_name = path+'/'+p+'/000'+str(n*3+j)+'/' for s in range(n_samples): d = dir_name+'%04d/'%s for f in os.listdir(d): if f.endswith('jpg'): filenames += [d+f] targets.append(n) return filenames, targets def read_images(files): #使用cv2將圖片存成灰階的圖案放入img imgs = [] for f in files: img = cv2.imread(f, cv2.IMREAD_GRAYSCALE) imgs.append(img) return imgs def read_datasets(datasets): #使用enumerate_files和read_images得到train和test資料 files, labels = enumerate_files(datasets) list_of_arrays = read_images(files) return np.array(list_of_arrays),labels #list_of_arrays要使用np.array存成array形式 train_sets = ['Set1', 'Set2', 'Set3'] #set1~set3是訓練資料 test_sets = ['Set4', 'Set5'] #set4~set5是測試資料 trn_array, trn_labels = read_datasets(train_sets) #獲得訓練的array和label tst_array, tst_labels = read_datasets(test_sets) #獲得測試的array和label trn_array = trn_array.reshape(540,32,32,1) #要reshape成四維的(幾張照片,幾乘幾的圖片,每次幾張) trn_array = trn_array.astype('float32')/255.0 #轉換類型成float trn_labels = to_categorical(trn_labels) #將label向量轉為二進制 tst_array = tst_array.reshape(360,32,32,1) #要reshape成四維的(幾張照片,幾乘幾的圖片,每次幾張) tst_array = tst_array.astype('float32')/255.0 #轉換類型成float tst_labels = to_categorical(tst_labels) #將label向量轉為二進制 ``` 透過以上程式碼, 在路徑:'All_gray_1_32_32'中, 可以將測試資料存入trn_array和trn_labels中 以及將訓練資料存入tst_array和tst_labels中 以及將資料都轉變成之後model中能夠使用的型態(包含reshape、astype、to_categorical) ### 建立模型 ``` model = models.Sequential() #建立sequential的model model.add(layers.Conv2D(32, (5, 5), activation='relu', input_shape=(32,32,1),name='layer1')) #建立第一層layer model.add(layers.MaxPooling2D((2, 2))) #將圖片尺寸減半 model.add(layers.Conv2D(64, (3, 3), activation='tanh')) #建立layer model.add(layers.MaxPooling2D((2, 2))) #將圖片尺寸減半 model.add(layers.Conv2D(64, (3, 3), activation='relu')) #建立layer model.add(layers.Conv2D(32, (3, 3), activation='tanh')) #建立layer model.add(layers.Flatten()) #將輸入的向量扁平化 model.add(layers.Dense(128, activation='tanh')) #使用dense多增加一層 model.add(layers.Dense(3, activation='softmax')) #最後建立一層使用softmax model.compile(loss='categorical_crossentropy', optimizer='rmsprop',metrics=['accuracy']) #對model進行compile ``` 藉由以上程式碼,可以將model建立成功,其中使用了兩次relu、三次tanh、一次softmax。 ### 訓練模型 ``` train_history = model.fit(trn_array, trn_labels, epochs=50, batch_size=64) #訓練資料後存入train_history ``` 以上程式碼可以將訓練資料帶入model中開始訓練,並且將訓練的內容存入train_history中 並透過以下程式碼來將測試資料對model進行evaluate,得到測試的結果(accuracy): ``` test_loss, test_acc = model.evaluate(tst_array, tst_labels) #對測試資料進行evaluate print(test_acc) ``` ### 繪製loss圖以及accuracy圖 要繪製圖首先要將train_history中的loss值和accuracy值取出,還有作圖所需要的Epochs值, 透過以下程式碼: ``` train_loss = train_history.history['loss'] #取出訓練過程的loss值 train_accuracy = train_history.history['accuracy'] #取出訓練過程的accuracy值 Epoch_data = [] #建立作圖需要用的Epoch_data for i in range(1,51,1): Epoch_data.append(i) ``` 獲得作圖所需的資料後,就可以藉由下圖開始繪製圖: ``` plt.plot(Epoch_data,train_loss,label='Loss_data',color='blue' ) #做Epoch和loss的圖 plt.xlabel('Epoch_data') #建立X軸標籤 plt.ylabel('Loss_data') #建立Y軸標籤 plt.legend() plt.show() #印出圖 plt.plot(Epoch_data,train_accuracy,label='accuracy_data',color='blue')#做Epoch和accuracy的圖 plt.xlabel('Epoch_data') #建立X軸標籤 plt.ylabel('Accuracy_data') #建立Y軸標籤 plt.legend() plt.show() #印出圖 ``` ### 顯示訓練後的結果以及圖 經過訓練之後的結果如下: ![](https://i.imgur.com/OWBZcVW.png) ![](https://i.imgur.com/5qV87Eb.png) ![](https://i.imgur.com/OpEPM0N.png) 經過測試資料後得到的結果如下: ![](https://i.imgur.com/XDOwtnq.png) 以下是繪製Loss和accuracy的圖: ![](https://i.imgur.com/7CwpcVI.png) ![](https://i.imgur.com/HoJbK26.png)