MediaPipe Holistic分别利用MediaPipe Pose,MediaPipe Face Mesh和MediaPipe Hands中的姿势,面部和手界标模型来生成总共543个界标(每手33个姿势界标,468个脸部界标和21个手界标)。本文将用MediaPipe Hands来完成AI虚拟鼠标。
引入库
import cv2 import numpy as np import HandTrackingModule as htm import autopy
其中 HandTrackingModule是大神编写的库,用于获取手指的坐标和检查手指是否伸出,调用autopy库实现鼠标点击功能。
HandTrackingModule
Youtube: http://www.youtube.com/c/MurtazasWorkshopRoboticsandAI
Website: https://www.computervision.zone
1. 检测手部得到手指关键点的坐标 success, img = cap.read() img = detector.findHands(img) lmList, bbox = detector.findPosition(img)
2,得到食指和中指的部分坐标 if len(lmList)!= 0:x1, y1 = lmList[8][1:]x2, y2 = lmList[12][1:]#print(x1, y1, x2, y2)
3. 检查哪个手指伸出 fingers = detector.fingersUp()
4. 只有食指伸出时移动鼠标 if fingers[1]==1 and fingers[2] == 0:5. 转换坐标 x3 = np.interp(x1, (frameR, wCam-frameR),(0,wScr)) y3 = np.interp(y1, (frameR, hCam-frameR), (0, hScr))7. 移动鼠标 autopy.mouse.move(wScr-x3, y3) cv2.circle(img, (x1, y1), 15, (255, 0,255),cv2.FILLED) plocX, plocY = clocX, clocY
8. 当食指和中指同时伸出时,鼠标不动 if fingers[1] == 1 and fingers[2] == 1: 9. 中指和食指之间的距离 length, img, lineInfo = detector.findDistance(8, 12, img)10. 当两指间的距离小于限定值时点击 if length < 40: # 当距离小于40个像素点时为左键cv2.circle(img, (lineInfo[4], lineInfo[5]), 15, (0, 255, 0), cv2.FILLED)autopy.mouse.click()
代码展示
import cv2 import numpy as np import HandTrackingModule as htm import time import autopywCam, hCam = 640,480 frameR = 100 smoothening = 5 pTime = 0 plocX, plocY = 0, 0 clocX, clocY = 0, 0 cap = cv2.VideoCapture(0) cap.set(3, wCam) cap.set(4, hCam)detector = htm.handDetector(maxHands=1) wScr, hScr = autopy.screen.size()while True:success, img = cap.read()img = detector.findHands(img)lmList, bbox = detector.findPosition(img)if len(lmList)!= 0:x1, y1 = lmList[8][1:]x2, y2 = lmList[12][1:] finger= detector.fingersUp()print(fingers)cv2.rectangle(img, (frameR, frameR), (wCam - frameR, hCam - frameR), (255, 0, 255), 2)if fingers[1]==1 and fingers[2] == 0:x3 = np.interp(x1, (frameR, wCam-frameR),(0,wScr))y3 = np.interp(y1, (frameR, hCam-frameR), (0, hScr))clocX = plocX +(x3 - plocX) / smootheningclocY = plocY + (y3 - plocY) / smootheningautopy.mouse.move(wScr-x3, y3)cv2.circle(img, (x1, y1), 15, (255, 0,255),cv2.FILLED)plocX, plocY = clocX, clocYif fingers[1] == 1 and fingers[2] == 1: length, img, lineInfo = detector.findDistance(8, 12, img) if length < 40: cv2.circle(img, (lineInfo[4], lineInfo[5]), 15, (0, 255, 0), cv2.FILLED)autopy.mouse.click()cTime = time.time()fps = 1 / (cTime - pTime)pTime = cTimecv2.putText(img, str(int(fps)), (20, 50), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)cv2.imshow("Img", img)if cv2.waitKey(1) == ord('q'): break
调试结果
20220109_182406_哔哩哔哩_bilibili