1说明 1。1环境:python3。8opnecv4。4。0 1。2gesturerecognition(手势识别),好东西就需要分享。 1。3代码来源:感谢原作者,但是有bug,作者不想给伸手党〔笑哭〕;还是感谢原作者,因为我要公开了,仅供学习。https:blog。csdn。netqq25939803articledetails106414495?utmmediumdistribute。pcrelevant。nonetaskblogBlogCommendFromMachineLearnPai21。channelparamdepth1utmsourcedistribute。pcrelevant。nonetaskblogBlogCommendFromMachineLearnPai21。channelparam 1。4对源代码进行增加,修改,注释,讲解,通俗易懂,小白秒懂。 2效果展示 2。1手掌图为主 2。2手背图为主(放到后面展示) 3代码讲解 3。1原理简述 第一步:加载图片,无论你是用cv2导入一张静态手势图片还是用摄像头导入实时图片都可以。 第二步:肤色检测,基于HSV颜色空间H,S,V范围筛选法HSV中 7H20;28S256;50V256 第三步:进行高斯滤波 第四步:边缘轮廓检测 第五步:求出手势的凹凸点 第六步:利用凹凸点个数判断当前手势,例如:0个凹凸点就是拳头,4个凹点就是布也就是5。 3。2代码:coding:UTF8第1步:导入模块importcv2importnumpyasnpimportmath第2步:获取摄像头实时视频0代表来自摄像头capcv2。VideoCapture(0)增加1利用BackgroundSubtractorMOG2算法消除背景fgbgcv2。createBackgroundSubtractorMOG2()第3步:循环while(cap。isOpened()):ret,framecap。read()读取摄像头每帧图片增加2fgmaskfgbg。apply(frame)framecv2。flip(frame,1)kernelnp。ones((2,2),np。uint8)在视频原图中的框,有点小修改1,300变500roiframe〔100:500,100:500〕选取图片中固定位置作为手势输入修改2,300变500cv2。rectangle(frame,(100,100),(500,500),(0,0,255),0)用红线画出手势识别框基于hsv的肤色检测hsvcv2。cvtColor(roi,cv2。COLORBGR2HSV)lowerskinnp。array(〔0,28,70〕,dtypenp。uint8)upperskinnp。array(〔20,255,255〕,dtypenp。uint8)进行高斯滤波maskcv2。inRange(hsv,lowerskin,upperskin)maskcv2。dilate(mask,kernel,iterations4)maskcv2。GaussianBlur(mask,(5,5),100)找出轮廓contours,hcv2。findContours(mask,cv2。RETRTREE,cv2。CHAINAPPROXSIMPLE)cntmax(contours,keylambdax:cv2。contourArea(x))epsilon0。0005cv2。arcLength(cnt,True)approxcv2。approxPolyDP(cnt,epsilon,True)hullcv2。convexHull(cnt)areahullcv2。contourArea(hull)areacntcv2。contourArea(cnt)arearatio((areahullareacnt)areacnt)100求出凹凸点hullcv2。convexHull(approx,returnPointsFalse)defectscv2。convexityDefects(approx,hull)l0定义凹凸点个数初始值为0增加3:非常重要,然后下面全部缩进ifdefectsisnotNone:重要!整体向内缩进foriinrange(defects。shape〔0〕):源代码报错处s,e,f,d,defects〔i,0〕starttuple(approx〔s〕〔0〕)endtuple(approx〔e〕〔0〕)fartuple(approx〔f〕〔0〕)pt(100,100)amath。sqrt((end〔0〕start〔0〕)2(end〔1〕start〔1〕)2)bmath。sqrt((far〔0〕start〔0〕)2(far〔1〕start〔1〕)2)cmath。sqrt((end〔0〕far〔0〕)2(end〔1〕far〔1〕)2)s(abc)2armath。sqrt(s(sa)(sb)(sc))手指间角度求取anglemath。acos((b2c2a2)(2bc))57ifangle90andd20:l1cv2。circle(roi,far,3,〔255,0,0〕,1)cv2。line(roi,start,end,〔0,255,0〕,2)画出包络线l1fontcv2。FONTHERSHEYSIMPLEX下面的都是条件判断,也就是知道手势后你想实现什么功能就写下面判断里就行了。ifl1:ifareacnt2000:cv2。putText(frame,puthandinthewindow,(0,50),font,2,(0,0,255),3,cv2。LINEAA)else:ifarearatio12:cv2。putText(frame,0,(0,50),font,2,(0,0,255),3,cv2。LINEAA)elifarearatio17。5:cv2。putText(frame,1,(0,50),font,2,(0,0,255),3,cv2。LINEAA)else:cv2。putText(frame,1,(0,50),font,2,(0,0,255),3,cv2。LINEAA)elifl2:cv2。putText(frame,2,(0,50),font,2,(0,0,255),3,cv2。LINEAA)elifl3:ifarearatio27:cv2。putText(frame,3,(0,50),font,2,(0,0,255),3,cv2。LINEAA)else:cv2。putText(frame,3,(0,50),font,2,(0,0,255),3,cv2。LINEAA)elifl4:cv2。putText(frame,4,(0,50),font,2,(0,0,255),3,cv2。LINEAA)elifl5:cv2。putText(frame,5,(0,50),font,2,(0,0,255),3,cv2。LINEAA)窗口展示视频效果cv2。imshow(frame,frame)cv2。imshow(mask,mask)退出设置kcv2。waitKey(25)0xffifk27:键盘Esc键退出break第4步:只能放在循环外,否则就是坑!!销毁全部窗口,无参数cv2。destroyAllWindows()释放摄像头cap。release() 4手背图为主的效果图 完美!!适合收藏。