这次使用cvzone模块,制作一个虚拟拖拽系统,我们根据索引可以知道食指与中指的索引为8和12,当两指间合并时可以对虚拟方块进行拖拽,张开时解除拖拽,方块停在此处。虽然目前仍然存在一定的bug,即当两个虚拟方块重合较多时,会使其中的一个方块消失,但我们又能利用这一点可以制作计算机视觉方面的游戏,比如贪吃蛇等。
本次项目依赖于视觉方面优秀的第三方库:
pip install cvzone
pip install mediapipe
除此之外,只需要一个.py文件就能完成本次项目。
更新cvzone的方法:
打开pycharm中的设置,找到cvzone:
block.py
import cv2
from cvzone.HandTrackingModule import HandDetector
import cvzone
import numpy as npcap = cv2.VideoCapture(1)
cap.set(3, 1280)
cap.set(4, 720)
detector = HandDetector(detectionCon=0.8)
colorR = (0, 0, 255)cx, cy, w, h = 100, 100, 200, 200class Moveblock():def __init__(self,posCenter,size=(200,200)):self.posCenter=posCenterself.size=sizedef update(self,cursor):cx,cy=self.posCenterw,h=self.sizeif cx - w // 2 < cursor[0] < cx + w // 2 and \cy - h // 2 < cursor[1] < cy + h // 2:self.posCenter = cursor[:2]rectList=[]
for i in range(5):rectList.append(Moveblock((i*250+150,150)))while True:succes,img=cap.read()img = cv2.flip(img,1)lmList ,img = detector.findHands(img)# print(lmList)if lmList:lmList1 = lmList[0]["lmList"]length, info, img = detector.findDistance(lmList1[8][:2],lmList1[12][:2],img,draw=False)print(length)if length<60:# lmList1 = lmList[0]["lmList"]cursor = lmList1[8]# print(cursor)for rect in rectList:rect.update(cursor)#实体框# for rect in rectList:# cx, cy = rect.posCenter# w, h = rect.size# cv2.rectangle(img,(cx-w//2,cy-h//2),(cx+w//2,cy+h//2),colorR,cv2.FILLED)## cvzone.cornerRect(img,(cx-w//2,cy-h//2, w, h),20,rt=0)#半透明imgNew=np.zeros_like(img,np.uint8)for rect in rectList:cx, cy = rect.posCenterw, h = rect.sizecv2.rectangle(imgNew,(cx-w//2,cy-h//2),(cx+w//2,cy+h//2),colorR,cv2.FILLED)cvzone.cornerRect(imgNew,(cx-w//2,cy-h//2, w, h),20,rt=0)out = img.copy()alpha=0.3mask=imgNew.astype(bool)out[mask]=cv2.addWeighted(img,alpha,imgNew,1-alpha,0)[mask]cv2.imshow("Image", out)k=cv2.waitKey(1)if k==27:break
本次依旧还是我来讲解,本次项目实现的思路吧。
def findDistance(self, p1, p2, img=None,draw=True):"""Find the distance between two landmarks based on theirindex numbers.:param p1: Point1:param p2: Point2:param img: Image to draw on.:param draw: Flag to draw the output on the image.:return: Distance between the pointsImage with output drawnLine information"""x1, y1 = p1x2, y2 = p2cx, cy = (x1 + x2) // 2, (y1 + y2) // 2length = math.hypot(x2 - x1, y2 - y1)info = (x1, y1, x2, y2, cx, cy)if img is not None:if draw:cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)return length, info, imgelse:return length, info
GitHub:Opencv-project-training/Opencv project training/16 Virtual drag block at main · Auorui/Opencv-project-training · GitHub
本次的项目还是有点小缺点,当两个方块重合太多时,会让另外的虚拟方块消失,目前还没有解决,但利用这个bug,也还是可以做一些其他项目,比如碰到另外的物体,被触的物体消失,这个想法我觉得运用还是挺多的。