深度學(xué)習(xí)與圖像處理實(shí)戰(zhàn)-ResNet 實(shí)現(xiàn)手勢(shì)識(shí)別_第1頁
深度學(xué)習(xí)與圖像處理實(shí)戰(zhàn)-ResNet 實(shí)現(xiàn)手勢(shì)識(shí)別_第2頁
深度學(xué)習(xí)與圖像處理實(shí)戰(zhàn)-ResNet 實(shí)現(xiàn)手勢(shì)識(shí)別_第3頁
深度學(xué)習(xí)與圖像處理實(shí)戰(zhàn)-ResNet 實(shí)現(xiàn)手勢(shì)識(shí)別_第4頁
深度學(xué)習(xí)與圖像處理實(shí)戰(zhàn)-ResNet 實(shí)現(xiàn)手勢(shì)識(shí)別_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

ResNet實(shí)現(xiàn)手勢(shì)識(shí)別深度學(xué)習(xí)與圖像處理實(shí)戰(zhàn)知識(shí)要點(diǎn)7.1ResNet簡介7.2數(shù)據(jù)集介紹及處理7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練7.4模型訓(xùn)練結(jié)果測(cè)試目錄7.1ResNet簡介VGG網(wǎng)絡(luò)達(dá)到19層后再增加層數(shù)就會(huì)導(dǎo)致分類性能下降。而殘差神經(jīng)網(wǎng)絡(luò)(ResidualNeuralNetwork,ResNet)的提出者何愷明等人在2015年提出了殘差學(xué)習(xí)(ResidualLearning)的概念,以簡化以前使用的網(wǎng)絡(luò),使之能夠以更深的網(wǎng)絡(luò)進(jìn)行訓(xùn)練,并進(jìn)一步將它應(yīng)用在了CNN的構(gòu)建當(dāng)中,于是就有了基本的殘差塊(ResidualBlock)。ResNet通過使用多個(gè)帶參數(shù)的層來學(xué)習(xí)輸入與輸出之間的殘差表示(真實(shí)值與預(yù)測(cè)值之間的差),而非像一般CNN(如AlexNet和VGG)那樣使用帶參數(shù)的層來直接嘗試學(xué)習(xí)輸入與輸出之間的映射關(guān)系。ResNet的殘差塊結(jié)構(gòu)7.1ResNet簡介在圖中,可以看到在不使用殘差結(jié)構(gòu)的情況下,18層的神經(jīng)網(wǎng)絡(luò)反而比34層的神經(jīng)網(wǎng)絡(luò)效果好一點(diǎn),而使用殘差結(jié)構(gòu)后,34層神經(jīng)網(wǎng)絡(luò)的錯(cuò)誤率(error)比18層神經(jīng)網(wǎng)絡(luò)的錯(cuò)誤率小得多。網(wǎng)絡(luò)結(jié)構(gòu)對(duì)比圖7.2數(shù)據(jù)集介紹及處理數(shù)據(jù)集文件夾如左圖所示。該數(shù)據(jù)集是由50位志愿者分別使用攝像頭拍攝手勢(shì),并使用膚色提取獲得的圖片構(gòu)成的。本數(shù)據(jù)集共有4個(gè)文件夾,數(shù)據(jù)集文件夾存放著4種手勢(shì)的圖片,分別為拳頭、1、2以及手掌。數(shù)據(jù)集內(nèi)容如右圖所示。圖

數(shù)據(jù)集內(nèi)容圖

數(shù)據(jù)集文件夾7.2數(shù)據(jù)集介紹及處理importcv2fromPILimportImageimportosfromtensorflow.keras.preprocessing.image\importImageDataGenerator,array_to_img,img_to_array,load_imgimportnumpyasnpfromkeras.utilsimportnp_utilsimportrandomDATASET_PATH=r'D:\下載\skin\skin'DATA_PATH='image_file'01OPTION本章中使用了tf.keras中自帶的數(shù)據(jù)增強(qiáng)。首先,新建一個(gè)getimg.py文件,寫入如下代碼。#數(shù)據(jù)增強(qiáng)defgetimage():ifnotos.path.exists(DATA_PATH):os.mkdir(DATA_PATH)image_file_paths=[os.path.join(DATASET_PATH,path)forpathinos.listdir(DATASET_PATH)]image_paths=[]forimage_file_pathinimage_file_paths:image_paths.append([os.path.join(image_file_path,path)forpathinos.listdir(image_file_path)])datagen=ImageDataGenerator(rotation_range=30,width_shift_range=0.1,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,fill_mode='nearest')7.2數(shù)據(jù)集介紹及處理forimage_pathinimage_paths:foriinimage_path:print(i)dir_num=i.split('\\')[-2]img=load_img(i)x=img_to_array(img)x=x.reshape((1,)+x.shape)i=0forbatchindatagen.flow(x,batch_size=1,save_to_dir=DATA_PATH,save_prefix='%s'%dir_num,save_format='jpg'):i+=1ifi>7:break程序運(yùn)行結(jié)果如圖所示。當(dāng)前目錄中新增了一個(gè)image_file文件夾,里面存儲(chǔ)的是進(jìn)行數(shù)據(jù)增強(qiáng)之后的圖片??梢钥吹?,每種手勢(shì)的圖片量都增加了,而且手勢(shì)的角度、方向也都發(fā)生了改變。程序運(yùn)行結(jié)果(1)7.2數(shù)據(jù)集介紹及處理ImageDataGenerator函數(shù)的參數(shù)及其說明參數(shù)說明rotation_range指定旋轉(zhuǎn)角度范圍,只需輸入一個(gè)整數(shù)即可,但并不是固定以這個(gè)角度進(jìn)行旋轉(zhuǎn),而是在[0,指定角度]的范圍內(nèi)進(jìn)行隨機(jī)角度旋轉(zhuǎn)width_shift_range和height_shift_range分別是水平位置平移和垂直位置平移,其參數(shù)可以是[0,1]的浮點(diǎn)數(shù),也可以大于1,其最大平移距離為圖片長或?qū)挼某叽绯藚?shù)。同樣,平移距離并不固定為最大平移距離,而是在[0,最大平移距離]的區(qū)間內(nèi)shear_range錯(cuò)切交換的角度zoom_range隨機(jī)縮放范圍,以使圖片在尺寸的長或?qū)挿较蜻M(jìn)行放大或縮小horizontal_flip隨機(jī)對(duì)圖片執(zhí)行水平翻轉(zhuǎn)操作。意味著不一定對(duì)所有圖片都執(zhí)行水平翻轉(zhuǎn),每次生成均是選取隨機(jī)圖片進(jìn)行水平翻轉(zhuǎn)fill_mode輸入邊界以外的點(diǎn),根據(jù)給定的模式填充,默認(rèn)為“nearest”7.2數(shù)據(jù)集介紹及處理02OPTION接著加載image_file文件夾中的圖片,對(duì)其進(jìn)行二值化、歸一化,以及標(biāo)簽獨(dú)熱編碼的處理,在最后返回結(jié)果的時(shí)候,還需要打亂數(shù)據(jù)集。該過程代碼如下。#加載數(shù)據(jù)集defloaddata():ifos.listdir(DATA_PATH)==[]:#判斷是否已經(jīng)進(jìn)行數(shù)據(jù)增強(qiáng)getimage()images_paths=[os.path.join(DATA_PATH,path)forpathinos.listdir(DATA_PATH)]print(images_paths)images=[]labels=[]forimages_pathinimages_paths:image=cv2.imread(images_path)#圖像預(yù)處理blur=cv2.GaussianBlur(image,(3,3),1)gray=cv2.cvtColor(blur,cv2.COLOR_BGR2GRAY)ret,binary=cv2.threshold(gray,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)7.2數(shù)據(jù)集介紹及處理images.append(binary)labels.append(images_path.split('\\')[-1].split('_')[0])images=np.array(images)/255.0labels=np_utils.to_categorical(labels)#獨(dú)熱編碼#打亂數(shù)據(jù)集index=[iforiinrange(len(images))]random.shuffle(index)images=images[index]labels=labels[index]print(images[0],labels[0])returnimages,labels這樣就可以得到完整的圖片數(shù)據(jù)和標(biāo)簽了。接下來搭建神經(jīng)網(wǎng)絡(luò),并進(jìn)行訓(xùn)練。7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練圖中l(wèi)ayername代表層名,outputsize代表輸出層的大小,conv代表卷積層,stride代表卷積的步長,averagepool代表平均池化層,1000-dfc代表長度為1000的全連接層,Softmax代表使用Softmax激活函數(shù),F(xiàn)LOPs代表計(jì)算量。圖中分別是ResNet18、ResNet34、ResNet50、ResNet101以及ResNet152的結(jié)構(gòu),它們的輸入都是一樣的,而且都經(jīng)過了卷積核為7×7,步長為2的卷積操作以及最大池化操作,并在輸出層使用了平均池化代替Flatten層。ResNet結(jié)構(gòu)7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練ResNet頭部區(qū)域結(jié)構(gòu)ResNet的結(jié)構(gòu)中,讀者可以一邊理解圖片一邊寫代碼,以加深理解。首先是頭部區(qū)域,結(jié)構(gòu)如圖所示??梢钥匆姡谧畲蟪鼗瘜又?,分出了2條支路,一條支路照常進(jìn)行卷積操作,一條支路不做什么操作,只在輸出部分與另一條支路結(jié)合。這就是前面提到的殘差結(jié)構(gòu)。7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練defResNet34(inpt):defconv(x,filters,kernel,stride,padding='same'):x=Conv2D(filters,kernel_size=kernel,strides=stride,padding=padding)(x)x=BatchNormalization()(x)x=Activation('relu')(x)returnx本節(jié)以ResNet34為例,首先定義一個(gè)函數(shù)ResNet34,然后將ResNet中重復(fù)的部分提取出來封裝成一個(gè)conv函數(shù),內(nèi)容主要是卷積、批量標(biāo)準(zhǔn)化、激活函數(shù)。這是一個(gè)較為主流的組合,Python代碼如下。ResNet中重復(fù)的部分7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練#殘差結(jié)構(gòu)defres_block(inpt,filters,kernel,stride=1,shortcut=False):x=conv(inpt,filters,kernel,stride)x=conv(x,filters,kernel,stride=1)ifshortcut:y=conv(inpt,filters,kernel,stride)x=add([x,y])else:x=add([x,inpt])returnx在殘差結(jié)構(gòu)中可以使用add函數(shù)來連接來自2個(gè)不同層的輸出。注意,連接的2個(gè)層的形狀必須是一致的。但是由于在殘差塊中會(huì)進(jìn)行步長為2的卷積(長、寬減半)操作,因此在另一條支路中也要進(jìn)行同樣的操作以保證形狀一致,如圖所示。ResNet中的殘差連接7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練

自此,一個(gè)基本的殘差結(jié)構(gòu)就搭建完成了。接著可以根據(jù)ResNet結(jié)構(gòu)圖的規(guī)律進(jìn)行ResNet-34的搭建,具體代碼如下。#224×224x=Conv2D(64,kernel_size=7,strides=2,activation='mish',padding='same')(inpt)#112×112x=MaxPool2D()(x)#56×56x=res_block(x,64,3)x=res_block(x,64,3)x=res_block(x,64,3)x=res_block(x,128,3,stride=2,shortcut=True)#28×28x=res_block(x,128,3)x=res_block(x,128,3)x=res_block(x,128,3)x=res_block(x,256,3,stride=2,shortcut=True)#14×14x=res_block(x,256,3)x=res_block(x,256,3)x=res_block(x,256,3)x=res_block(x,256,3)x=res_block(x,256,3)x=res_block(x,512,3,stride=2,shortcut=True)#7×7x=res_block(x,512,3)x=res_block(x,512,3)x=GlobalAveragePooling2D()(x)x=Dense(1000,activation='softmax')(x)returnk.models.Model(inpt,x)7.3主干網(wǎng)絡(luò)搭建與訓(xùn)練

接下來開始訓(xùn)練,最后一層為1000個(gè)類別的輸出,我們用不到這么多,按下面代碼進(jìn)行修改。x=GlobalAveragePooling2D()(x)x=Dropout(0.25)(x)x=Dense(4,activation='softmax')(x)returnk.models.Model(inpt,x)fromsklearn.model_selectionimporttrain_test_splitimages,labels=getimg.loaddata()images=images.reshape(-1,224,224,1)#分割測(cè)試集x_train,x_test,y_train,y_test=train_test_split(images,labels,test_size=0.25)#激活函數(shù)為Adam,學(xué)習(xí)率為0.0003adam=Adam(lr=0.0003)pile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy'])#開始訓(xùn)練model.fit(x_train,y_train,batch_size=16,epochs=30,verbose=1,validation_data=(x_test,y_test),callbacks=[TensorBoard(log_dir='./tmp/log')])score,accuracy=model.evaluate(x_test,y_test,batch_size=16)print('score:',score,'accuracy:',accuracy)model.save('Gesture1_0.h5')

接著就可以開始訓(xùn)練了,代碼如下。7.4模型訓(xùn)練結(jié)果測(cè)試首先定義一個(gè)video.py文件,然后寫入如下代碼。01OPTION使用RGB進(jìn)行膚色提取importcv2importnumpyasnpfromtensorflow.keras.modelsimportload_model#使用RGB進(jìn)行膚色提取defskin_color(img):rows,cols,channels=img.shapeimgSkin=img.copy()#獲得每個(gè)通道中R、G、B的值,并判斷是否處于閾值內(nèi)forrinrange(rows):forcinrange(cols):#分別獲取各個(gè)通道的值B=img.item(r,c,0)G=img.item(r,c,1)R=img.item(r,c,2)skin=0#當(dāng)通道的值在某個(gè)區(qū)間時(shí)像素取1if(abs(R-G)>15)and(R>G)and(R>B):if(R>95)and(G>40)and(B>20)and\(max(R,G,B)-min(R,G,B)>15):skin=1elif(R>220)and(G>210)and(B>170):skin=17.4模型訓(xùn)練結(jié)果測(cè)試代碼如下。02OPTION加載訓(xùn)練好的模型#設(shè)置圖片像素值(二值化)if0==skin:imgSkin.itemset((r,c,0),0)imgSkin.itemset((r,c,1),0)imgSkin.itemset((r,c,2),0)else:imgSkin.itemset((r,c,0),255)imgSkin.itemset((r,c,1),255)imgSkin.itemset((r,c,2),255)returnimgSkinmodel=load_model('Gesture1_0.h5')cam=cv2.VideoCapture(0)hand_label=['0','1','2','5']如膚色提取、高斯模糊、二值化、尋找最大連通區(qū)域等,代碼如下。03OPTION打開攝像頭,進(jìn)行數(shù)據(jù)的實(shí)時(shí)處理whilecam:_,img=cam.read()img=cv2.resize(img,(224,224))#二值化cr=skin_color(img)#高斯濾波,cr是待濾波的源圖像數(shù)據(jù)#(5,5)是指窗口大小,0是指根據(jù)窗口大小來計(jì)算高斯函數(shù)標(biāo)準(zhǔn)差cr1=cv2.GaussianBlur(cr,(5,5),0)#對(duì)cr通道分量進(jìn)行高斯濾波cr1=cv2.cvtColor(cr1,cv2.COLOR_BGR2GRAY)#根據(jù)最大類間方差法(OTSU算法)求圖像閾值,對(duì)圖像進(jìn)行二值化_,skin1=cv2.threshold(cr1,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)con=cv2.findContours(skin1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)7.4模型訓(xùn)練結(jié)果測(cè)試rect=[]#尋找最大連通區(qū)域fori,contourinenumerate(con):#print(i,contour)x,y,w,h=cv2.boundingRect(con[i])rect.append(w*h)#畫出最大連通區(qū)域的矩形框iflen(rect)!=0:x,y,w,h=cv2.boundingRect(con[rect.index(max(rect))])w=h=int((w+h)/2)cv2.rectangle(img,(x-10,y

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論