From 6a13bd04d7d4332ba9c7f806611221ad960e915a Mon Sep 17 00:00:00 2001 From: "Eric.Lee2021" <305141918@qq.com> Date: Mon, 8 Mar 2021 02:31:29 +0800 Subject: [PATCH] add handpose_x_gesture_v1 --- README.md | 35 ++++++++++++++++++++--------------- inference.py | 40 +++++++++++++++++++++------------------- samples/Iloveyou.jpg | Bin 0 -> 2930 bytes samples/fist.jpg | Bin 0 -> 2792 bytes samples/five.jpg | Bin 0 -> 3457 bytes samples/four.jpg | Bin 0 -> 3518 bytes samples/gun.jpg | Bin 0 -> 3032 bytes samples/heartSingle.jpg | Bin 0 -> 3606 bytes samples/nine.jpg | Bin 0 -> 2626 bytes samples/ok.jpg | Bin 0 -> 3730 bytes samples/pink.jpg | Bin 0 -> 4686 bytes samples/six.jpg | Bin 0 -> 2955 bytes samples/three.jpg | Bin 0 -> 3817 bytes samples/thumbUp.jpg | Bin 0 -> 3352 bytes samples/yearh.jpg | Bin 0 -> 3458 bytes train.py | 29 ++++++++++++++++++++--------- 16 files changed, 61 insertions(+), 43 deletions(-) create mode 100644 samples/Iloveyou.jpg create mode 100644 samples/fist.jpg create mode 100644 samples/five.jpg create mode 100644 samples/four.jpg create mode 100644 samples/gun.jpg create mode 100644 samples/heartSingle.jpg create mode 100644 samples/nine.jpg create mode 100644 samples/ok.jpg create mode 100644 samples/pink.jpg create mode 100644 samples/six.jpg create mode 100644 samples/three.jpg create mode 100644 samples/thumbUp.jpg create mode 100644 samples/yearh.jpg diff --git a/README.md b/README.md index ee12d8c..2ed7388 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,10 @@ * 通过运行read_datasests.py,可以对数据的标注信息进行解析可视化。 ### 2、静态手势识别数据集 -* 数据集来源大部分样本是网上数据自制。 -* 少部分来源于 kinect_leap_dataset 数据集样本加工制作,其官网地址为:https://lttm.dei.unipd.it/downloads/gesture/ +* 数据集来源3部分,且网上数据占绝大多数,具体: +* 1)来源于网上数据并自制。 +* 2)来源于自己相机采集并自制。 +* 3)来源于 kinect_leap_dataset 数据集并自制,其官网地址为:https://lttm.dei.unipd.it/downloads/gesture/ * 注:数据集如有侵权,请联系删除。 ``` kinect_leap_dataset 数据集来源于以下paper项目组的贡献。 @@ -28,20 +30,23 @@ kinect_leap_dataset 数据集来源于以下paper项目组的贡献。 * 数据下载 该项目数据集命名为:handpose_x_gesture_v1,[数据集下载地址(百度网盘 Password: )]() - + 数据集共 2850 个样本,分为 14 类。 * 手势定义 -| 定义 | 示例 | -|--|--| -| 000-one | ![one](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/one.jpg) | -| 第二章 | ~ | -| 第三章 | ~ | -| 第四章 | ~ | -| 第五章 | ~ | -| 第六章 | ~ | -| 第七章 | ~ | -| 第八章 | ~ | -| 第九章 | ~ | -| 第十章 | ~ | + + ![one](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/one.jpg) :000-one + ![five](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/five.jpg) :001-five + ![fist](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/fist.jpg) :002-fist + ![ok](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/ok.jpg) :003-ok + ![heartSingle](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/heartSingle.jpg) :004-heartSingle + ![yearh](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/yearh.jpg) :005-yearh + ![three](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/three.jpg) :006-three + ![four](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/four.jpg) :007-four + ![six](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/six.jpg) :008-six + ![Iloveyou](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/Iloveyou.jpg) :009-Iloveyou + ![gun](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/gun.jpg) :010-gun + ![thumbUp](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/thumbUp.jpg) :011-thumbUp + ![nine](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/nine.jpg) :012-nine + ![pink](https://codechina.csdn.net/EricLee/classification/-/raw/master/samples/pink.jpg) :013-pink ## 预训练模型 * [预训练模型下载地址(百度网盘 Password: ks87 )](https://pan.baidu.com/s/1tT0wF4N2I9p5JDfCwtM1CQ) diff --git a/inference.py b/inference.py index 8bb2f82..681c1bf 100644 --- a/inference.py +++ b/inference.py @@ -40,21 +40,23 @@ def get_xml_msg(path): if __name__ == "__main__": - parser = argparse.ArgumentParser(description=' Project Classification Test') - parser.add_argument('--test_model', type=str, default = './model_exp/2021-02-09_06-32-32/resnet50_epoch-627.pth', + parser = argparse.ArgumentParser(description=' Project Classification top1 Test') + parser.add_argument('--test_model', type=str, default = './model_exp/2021-03-08_01-16-46/resnet_34-192_epoch-176.pth', help = 'test_model') # 模型路径 - parser.add_argument('--model', type=str, default = 'resnet_50', + parser.add_argument('--model', type=str, default = 'resnet_34', help = 'model : resnet_18,resnet_34,resnet_50,resnet_101,resnet_152') # 模型类型 - parser.add_argument('--num_classes', type=int , default = 120, + parser.add_argument('--num_classes', type=int , default = 14, help = 'num_classes') # 分类类别个数 parser.add_argument('--GPUS', type=str, default = '0', help = 'GPUS') # GPU选择 - parser.add_argument('--test_path', type=str, default = './datasets/test/', + parser.add_argument('--test_path', type=str, default = './handpose_x_gesture_v1/', help = 'test_path') # 测试集路径 - parser.add_argument('--img_size', type=tuple , default = (256,256), + parser.add_argument('--img_size', type=tuple , default = (192,192), help = 'img_size') # 输入模型图片尺寸 parser.add_argument('--fix_res', type=bool , default = False, help = 'fix_resolution') # 输入模型样本图片是否保证图像分辨率的长宽比 + parser.add_argument('--have_label_file', type=bool , default = False, + help = 'have_label_file') # 是否可视化图片 parser.add_argument('--vis', type=bool , default = True, help = 'vis') # 是否可视化图片 @@ -125,20 +127,20 @@ if __name__ == "__main__": img = cv2.imread(ops.test_path +doc+'/'+ file) #--------------- + if ops.have_label_file: + xml_ = ops.test_path +doc+'/'+ file.replace(".jpg",".xml") - xml_ = ops.test_path +doc+'/'+ file.replace(".jpg",".xml") + list_x = get_xml_msg(xml_)# 获取 xml 文件 的 object - list_x = get_xml_msg(xml_)# 获取 xml 文件 的 object - - # 绘制 bbox - for j in range(min(1,len(list_x))): - label_,bbox_ = list_x[j] - x1,y1,x2,y2 = bbox_ - x1 = int(np.clip(x1,0,img.shape[1]-1)) - y1 = int(np.clip(y1,0,img.shape[0]-1)) - x2 = int(np.clip(x2,0,img.shape[1]-1)) - y2 = int(np.clip(y2,0,img.shape[0]-1)) - img = img[y1:y2,x1:x2,:] + # 绘制 bbox + for j in range(min(1,len(list_x))): + label_,bbox_ = list_x[j] + x1,y1,x2,y2 = bbox_ + x1 = int(np.clip(x1,0,img.shape[1]-1)) + y1 = int(np.clip(y1,0,img.shape[0]-1)) + x2 = int(np.clip(x2,0,img.shape[1]-1)) + y2 = int(np.clip(y2,0,img.shape[0]-1)) + img = img[y1:y2,x1:x2,:] # 输入图片预处理 if ops.fix_res: @@ -171,7 +173,7 @@ if __name__ == "__main__": score_ = output[max_index] - print('gt {} -- pre {} --->>> confidence {}'.format(gt_label,max_index,score_)) + print('gt {} - {} -- pre {} --->>> confidence {}'.format(doc,gt_label,max_index,score_)) dict_p[dict_static[max_index]] += 1 if gt_label == max_index: dict_r[doc] += 1 diff --git a/samples/Iloveyou.jpg b/samples/Iloveyou.jpg new file mode 100644 index 0000000000000000000000000000000000000000..72088a31ccf3e85e5124d49f77cd92922cf2679c GIT binary patch literal 2930 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 L)8$h{!N5NN@(*}7 literal 0 HcmV?d00001 diff --git a/samples/fist.jpg b/samples/fist.jpg new file mode 100644 index 0000000000000000000000000000000000000000..47e0e57c5d6326fdff14acb486bd01da5300e1db GIT binary patch literal 2792 zcmbW1dof8v4lZ492A5b`WuUp=?eSAa1!XqN1qVL8(NO+i-^e8#)>9h2V z%;#Czg+;|BrDf&Bm#=HJY^_#g8z ztV`UByJW;H(=I0V@+T)C!7^*Xi#C(@uDpm~d{6|R`>pYXqJIxOUx5-+#z4^29P%iJ zU!JfW#%8m61$;MfBwxKJpV$7qEPWZ{p>%KSCe7%QSGL%dmM{=^Wzo=!5dUW21 zuF76?Sb-ZEpK|!vlR?NSLWPSxGbwbsLkfre&Slx zRMXa;;mV7V2hS@vEp+m7IHd0C1_G-q(Wfu~n@*(1rf$Qy=rW$GiLYEEOW8|3)^Lu; zSqSO@qYt&S$sL3P2Y-n*oylJ<)9@fe2efUjD)!lQ9VAJ( zLR1W=s0=K``oxO)!p5nzIbIy|)FgBaY5O(&yWbQ!>ENZ|?Bfljn}lx|v+35nCTp#} zX-6OG@QZISrOr&TFOLtJy?>K*Ik?`mDXdBj$GcbkhF^H{`_U1HI_=h_^T`_*v-D>m z+mMN7Kly9n6}W-w=o3LOCJw*S*_QINJ-53HI??ge^<_oDnW+^@_#FNClZCWda%7ul zoJ|a!Gt)jokcdYP<@*@Fo3+NhSoBmJss3)r{W)r`wPVRIaoO@KH*upH!%}ffAN_-f zM9zmBk}50Etk+h9`e*Dv*-{HUjqiqUvTsea%pZHMj`{6;3`~jL+C6v*cRT!3R++D% zMP_}EQRg`QEqY?WZMdE!iEbs6K^=jV2t*bOwPwY%5x z3b?7my)=r;RcghtmiCvlTWa?ZhF#_+w$Qq1TPw&IS&TeYj1~ZLdJXeoB|fiyl10%X zyK|;ShOi1l3juYF#g8K2y}J3NetfOdcU=JR4)c?m5cEZWoU|&VcPEgf=w=?Ew)DOF zv;wm^dHre_wX}#hM(a{)f@x;#HPF^!Ow=;hhLR}`DW|T&uVLH!PZ(lrNX_V*#-X$B zXT�dIdmr<@=V;q^zUkcx6qMO3a>LAM-Wlg8aTBPJAlqdz1#3w~9imlw5f2k7+I~ zJ-37_2_xKz(DFTQ+(IwfqJcJ-`<944W$_lo;x`DB*r|ND1ety*CLnN+OXoW)uBW8b zj~gBh42}8S?v>Gt4~=7}F}#$c9wb%rAir z4{`!tHHIJX4}ZSk;nlY3l%VM+@41Ll*W)t^*6$Pf*>WUOjw|(}Y=rl1I>yM!g0s)j zTB_tCuRikB+%<$dK)bXaDAK)%g;#e&;oSdJ-wt}w+U8mD3q zXW!44<)?+Mk~m%~vtxB?h2HB4orp3D8XFa(p^`v8uWa)q)>JXA8lt4Lhze8DaCVX;-nVVqp4o+ zsg$Fl4}Qq1D#FT4zDW<14l!41L|%R%yZ>8Jp^5L1lCwr$DZEy^LK6!cE#E*ZTr<5p zQWW9K5dfn_l%AJSrc0FPx=*ZBr3exDYjoVSyLm!dSl_2w!c5 zOrw@{X~jWyUI7}*Z=I>5lI$^51@kgyyhCG!#$%nCtkrxJ0-_y+;Rn}A^39!0ER!|#0y5+`pAc}DSM^8$cxq-cQgc&Hoo2V$ km`Zsw;n(59t2T5*Aif=2`j+!qd9Zw2zwjLnmM0kdCj)>|H~;_u literal 0 HcmV?d00001 diff --git a/samples/five.jpg b/samples/five.jpg new file mode 100644 index 0000000000000000000000000000000000000000..01c07504a71ec7ac556ed56a64a8e76ff4e321bf GIT binary patch literal 3457 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 Ti&R6y`ODMV0+v2RG=2D=Ri1`F literal 0 HcmV?d00001 diff --git a/samples/four.jpg b/samples/four.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d99de899c849ec747a61db7b58ea98bf55757d69 GIT binary patch literal 3518 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 Y8C_D<(Tx)9go7U-@s{&NL)fGL0+H~qM*si- literal 0 HcmV?d00001 diff --git a/samples/ok.jpg b/samples/ok.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e48fa836798115e0f4c768af5ec4502063f72df GIT binary patch literal 3730 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�}C9xx$aZ`ffptHNk zy32~X`gct>J`9h==e2_7xLKDGCOn**!ZmNyb{|goH6@O?K2y3Vv2c|QTu6h@#7(ef z_B|+UDol&4KmL+`7A+}BEccrTfO@>S)sz99K1Ha(PH)mO;)DaK`A=xs%sa{U36FL& zw3~+}*uc-REQd1G8@jcDPJ3Hv&YT}9e=#j03>Ev9GO!RT_1=w?BJ=K(5us6Iix_SD zW5kOn%?7qswv~$B>;(GihY;96^+KAa1`A%AI*Ij6@))m|6eqNE>+?!4$RG354PEVL zU^sWZGW$!AUtP46^^f`Bv29o!rWToukp6bBY^FrVAR@%k&u_7(>vgjsM(gN+N8Z?j zu!X`X+?pUYwjZKNvowNPz3q)n9`&F1|2m32*EtoKbI^FPHAdJK;j&a*+0Ym}@-ct^ z?B6#7k`(&H26n^YR*q;jwkCqo7-%8lMf50W3u}#d=ne|u?cbM)07pfUn>>}G2 z!$+jCWx77yH9NA!mA;ha)K9omgD-=w0tLDC5Bk|x9hYRm)T7^SN^g}h z?2m+fFhv$l8i)Gp?NdlXbC>lVI49DDHM^uwT~cTI$;Oi){lUd1xBLa-!n__NyjZqa zite6o(Yz*_b*kqP8;BmG2Yj}+iZZhK1Ea}-NaKpnTF$`xsS(3uv7S7iN_c6T%x(YF zzjH4Ox8C2^1$)Dbt_BhAk9m8Z7e+(i$=dRtyCa#G(G$1t zc6*^~P+y0;*9mj1P>5Mh7WJtM%WEf}k_OVp!JG|#Cs|4 z?!CP;&4gt@@S>BtYo$S_?a3_Uk3pOl8!(eb<_wU7M~;43@$c7*YKAO!29jxxh41>P z`eThQa}BwTQSp&O{^;=lFCrnKvIs?cjciOaDm7o+R9fe+xS0r?aFHkTZxTr-Fz3zKE~ z7Y?RnyO5*Q2~j=b7SIs-F-S(ap~=xk(R@Si9nL8f8;)s}#ap@V=CsI-(7v{ZUXjW7 z5F2{f)yQ8wY9o;m?0qKuyP@f;h1J?&Nl!b&vtuL&`6pkC=>qtw5dYJ!({2RiEaYz1 zSIo$S&2ATIR%zEaA@rdt~uGuY{tjUOPDBu-Bcmg{SKl7n!#dM`jaXPHfnhlJG pOll!NxwG0@4y5R)I=Em{47xlp=qqc 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 WfenTg1eJM8DK?<1Bz;h{@qYkWkVnb@ literal 0 HcmV?d00001 diff --git a/samples/thumbUp.jpg b/samples/thumbUp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..340c2f95c68f8bcec66ee58c9766693347149c6a GIT binary patch literal 3352 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 ZnY!`gy@g$tqAufdCqyq;0@(eDzX6UqfIa{K literal 0 HcmV?d00001 diff --git a/train.py b/train.py index 93f4af7..4bb3874 100644 --- a/train.py +++ b/train.py @@ -139,7 +139,7 @@ def trainer(ops,f_log): # print(model_)# 打印模型结构 # Dataset - dataset = LoadImagesAndLabels(path = ops.train_path,img_size=ops.img_size,flag_agu=ops.flag_agu,fix_res = ops.fix_res,val_split = val_split) + dataset = LoadImagesAndLabels(path = ops.train_path,img_size=ops.img_size,flag_agu=ops.flag_agu,fix_res = ops.fix_res,val_split = val_split,have_label_file = ops.have_label_file) print('len train datasets : %s'%(dataset.__len__())) # Dataloader dataloader = DataLoader(dataset, @@ -228,8 +228,9 @@ def trainer(ops,f_log): # 一个 epoch 保存连词最新的 模型 if i%(int(dataset.__len__()/ops.batch_size/2-1)) == 0 and i > 0: torch.save(model_.state_dict(), ops.model_exp + 'latest.pth') - # 每一个 epoch 进行模型保存 - torch.save(model_.state_dict(), ops.model_exp + 'model_epoch-{}.pth'.format(epoch)) + # 每间隔 5 个 epoch 进行模型保存 + if (epoch%5) == 0 and (epoch > 9): + torch.save(model_.state_dict(), ops.model_exp + '{}-{}_epoch-{}.pth'.format(ops.model,ops.img_size[0],epoch)) if len(val_split) > 0 and (epoch%ops.test_interval==0): # test @@ -259,14 +260,23 @@ if __name__ == "__main__": help = 'seed') # 设置随机种子 parser.add_argument('--model_exp', type=str, default = './model_exp', help = 'model_exp') # 模型输出文件夹 - parser.add_argument('--model', type=str, default = 'resnet_50', + parser.add_argument('--model', type=str, default = 'resnet_34', help = 'model : resnet_18,resnet_34,resnet_50,resnet_101,resnet_152') # 模型类型 - parser.add_argument('--num_classes', type=int , default = 120, - help = 'num_classes') # 分类类别个数 + + ''' + 注意以下3个参数与具体分类任务数据集,息息相关 + ''' + #--------------------------------------------------------------------------------- + parser.add_argument('--train_path', type=str, default = './handpose_x_gesture_v1/', + help = 'train_path') # 训练集路径 + parser.add_argument('--num_classes', type=int , default = 14, + help = 'num_classes') # 分类类别个数,gesture 配置为 14 , Stanford Dogs 配置为 120 + parser.add_argument('--have_label_file', type=bool, default = False, + help = 'have_label_file') # 是否有配套的标注文件解析才能生成分类样本,gesture 配置为 False , Stanford Dogs 配置为 True + #--------------------------------------------------------------------------------- + parser.add_argument('--GPUS', type=str, default = '0', help = 'GPUS') # GPU选择 - parser.add_argument('--train_path', type=str, default = './datasets/train/', - help = 'train_path') # 训练集路径 parser.add_argument('--val_factor', type=float, default = 0.0, help = 'val_factor') # 从训练集中分离验证集对应的比例 parser.add_argument('--test_interval', type=int, default = 1, @@ -291,7 +301,7 @@ if __name__ == "__main__": help = 'epochs') # 训练周期 parser.add_argument('--num_workers', type=int, default = 1, help = 'num_workers') # 训练数据生成器线程数 - parser.add_argument('--img_size', type=tuple , default = (256,256), + parser.add_argument('--img_size', type=tuple , default = (192,192), help = 'img_size') # 输入模型图片尺寸 parser.add_argument('--flag_agu', type=bool , default = True, help = 'data_augmentation') # 训练数据生成器是否进行数据扩增 @@ -302,6 +312,7 @@ if __name__ == "__main__": parser.add_argument('--log_flag', type=bool, default = False, help = 'log flag') # 是否保存训练 log + #-------------------------------------------------------------------------- args = parser.parse_args()# 解析添加参数 #-------------------------------------------------------------------------- -- GitLab