0


Opencv实战项目:13 手部追踪

0、项目介绍

你可以根据下面进行对应观察。

  1. WRIST = 0
  2. THUMB_CMC = 1
  3. THUMB_MCP = 2
  4. THUMB_IP = 3
  5. THUMB_TIP = 4
  6. INDEX_FINGER_MCP = 5
  7. INDEX_FINGER_PIP = 6
  8. INDEX_FINGER_DIP = 7
  9. INDEX_FINGER_TIP = 8
  10. MIDDLE_FINGER_MCP = 9
  11. MIDDLE_FINGER_PIP = 10
  12. MIDDLE_FINGER_DIP = 11
  13. MIDDLE_FINGER_TIP = 12
  14. RING_FINGER_MCP = 13
  15. RING_FINGER_PIP = 14
  16. RING_FINGER_DIP = 15
  17. RING_FINGER_TIP = 16
  18. PINKY_MCP = 17
  19. PINKY_PIP = 18
  20. PINKY_DIP = 19
  21. PINKY_TIP = 20

这是一个比较基础的项目,我们将在后面对它进行一个拓展,有很多的计算机视觉的游戏都可以根据这个来创立,比如贪吃蛇、水果忍者、虚拟拖拽等

1、效果展示

基础的手指识别展现

可以看到左上角的帧速率还是挺不错的,大致在20左右。

2、项目搭建

没有下这个mediapipe的包的,pip命令下载就好。

pip install mediapipe

上图是你需要搭建的

3、项目的代码

基础的手指识别

  1. import cv2
  2. import mediapipe as mp
  3. import time
  4. cap = cv2.VideoCapture(0)
  5. mpHands = mp.solutions.hands
  6. hands = mpHands.Hands()
  7. mpDraw = mp.solutions.drawing_utils
  8. pTime = 0 #previous time
  9. cTime = 0 #current time
  10. while True:
  11. success, img = cap.read()
  12. imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  13. results = hands.process(imgRGB)
  14. # print(results.multi_hand_landmarks)
  15. if results.multi_hand_landmarks:
  16. for handLms in results.multi_hand_landmarks:
  17. for id, lm in enumerate(handLms.landmark):
  18. print(id, lm)
  19. h, w, c = img.shape
  20. cx, cy = int(lm.x * w), int(lm.y * h)
  21. print(id, cx, cy)
  22. # if id == 8:
  23. cv2.circle(img, (cx, cy), 12, (255, 0, 100), cv2.FILLED)
  24. mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
  25. cTime = time.time()
  26. fps = 1 / (cTime - pTime)
  27. pTime = cTime
  28. cv2.putText(img, str(int(fps)), (12, 70), cv2.FONT_HERSHEY_PLAIN, 3,
  29. (255, 0, 0), 3)
  30. cv2.imshow("Image", img)
  31. k=cv2.waitKey(1)
  32. if k==27:
  33. break

1,我们先来看while循环之外的,mediapipe的solutions函数你可以理解为它是一种形式,它的具体作用并没有给出,下面是打开了Hands的函数,里面被__init__隐藏了,参数的大概意思是静态图像模式为False,不然它的检测速度将会很慢,识别最多的手指数为2,模型的复杂度为1,检测与追踪的置信度为0.5。所以这里最好的就是默认即可。

  1. def __init__(self,
  2. static_image_mode=False,
  3. max_num_hands=2,
  4. model_complexity=1,
  5. min_detection_confidence=0.5,
  6. min_tracking_confidence=0.5):

在这下面是Mediapipe的一些API命令,我们用到了下面的第二个,绘图实用程序。

  1. import mediapipe.python.solutions.drawing_styles
  2. import mediapipe.python.solutions.drawing_utils
  3. import mediapipe.python.solutions.face_detection
  4. import mediapipe.python.solutions.face_mesh
  5. import mediapipe.python.solutions.face_mesh_connections
  6. import mediapipe.python.solutions.hands
  7. import mediapipe.python.solutions.hands_connections
  8. import mediapipe.python.solutions.holistic
  9. import mediapipe.python.solutions.objectron
  10. import mediapipe.python.solutions.pose
  11. import mediapipe.python.solutions.selfie_segmentation

2、再来看看循环之中的,这里有一步BGR—>RGB的步骤,是因为下面hands.py文件中,process方法只处理RGB图像并返回每个检测到的手的手标志和手的惯用度。我们使用multi_hand_landmarks,打印出来后,我们来看看我提取的一小部分。

  1. None
  2. None
  3. None
  4. None
  5. None
  6. landmark {
  7. x: 0.21002258360385895
  8. y: 0.5776774883270264
  9. z: -0.034888774156570435
  10. }
  11. landmark {
  12. x: 0.2889356315135956
  13. y: 0.5564149618148804
  14. z: -0.047251101583242416
  15. }
  16. landmark {
  17. x: 0.3520330786705017
  18. y: 0.5242205262184143
  19. z: -0.05719052627682686
  20. }

这里意思就是没有检测到手,打印出的None,检测到手后,打印出来你就会得到一个数组,很好,这样我们就可以据此来写条件语句,用enumerate函数获得ID以及landmark中的数值。我们来看看控制台中:

  1. 10 x: 0.4111193120479584
  2. y: 0.4475841224193573
  3. z: -0.006161178927868605
  4. 11 x: 0.4441204369068146
  5. y: 0.5238251090049744
  6. z: -0.019978130236268044

这里在x前面就是Id,它这个Id共有21,从0到20,这对应于我们手掌上的信息。而地表信息都是小素,这个是按像素为单位的,那么只要用窗口的大小对应相乘,这样就可以获得我们想要的坐标信息,这里draw_landmarks是循环外绘图实用程序的一个函数,我们用它来链接点,这里用到了一些数学知识,我们可以跳过。由于每个点较小,我们可以通过画圆来方便我们观察。

3、最后,我们将fps,帧速率打印出来,显示图像以及窗口退出的程序。

制作为追踪手指的类

  1. import cv2
  2. import mediapipe as mp
  3. import time
  4. class handDetector():
  5. def __init__(self, mode=False, maxHands=2, complexity=1,detectionCon=0.5, trackCon=0.5):
  6. self.mode = mode
  7. self.maxHands = maxHands
  8. self.complexity=complexity
  9. self.detectionCon = detectionCon
  10. self.trackCon = trackCon
  11. self.mpHands = mp.solutions.hands
  12. self.hands = self.mpHands.Hands(self.mode, self.maxHands,self.complexity,
  13. self.detectionCon, self.trackCon)
  14. self.mpDraw = mp.solutions.drawing_utils
  15. def findHands(self, img, draw=True):
  16. imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  17. self.results = self.hands.process(imgRGB)
  18. # print(results.multi_hand_landmarks)
  19. if self.results.multi_hand_landmarks:
  20. for handLms in self.results.multi_hand_landmarks:
  21. if draw:
  22. self.mpDraw.draw_landmarks(img, handLms,
  23. self.mpHands.HAND_CONNECTIONS)
  24. return img
  25. def findPosition(self, img, handNo=0, draw=True):
  26. lmList = []
  27. if self.results.multi_hand_landmarks:
  28. myHand = self.results.multi_hand_landmarks[handNo]
  29. for id, lm in enumerate(myHand.landmark):
  30. # print(id, lm)
  31. h, w, c = img.shape
  32. cx, cy = int(lm.x * w), int(lm.y * h)
  33. # print(id, cx, cy)
  34. lmList.append([id, cx, cy])
  35. if draw:
  36. cv2.circle(img, (cx, cy), 10, (255, 0, 100), cv2.FILLED)
  37. return lmList
  38. def main():
  39. pTime = 0
  40. cTime = 0
  41. cap = cv2.VideoCapture(0)
  42. detector = handDetector()
  43. while True:
  44. success, img = cap.read()
  45. img = detector.findHands(img)
  46. lmList = detector.findPosition(img)
  47. if len(lmList) != 0:
  48. print(lmList[4])
  49. cTime = time.time()
  50. fps = 1 / (cTime - pTime)
  51. pTime = cTime
  52. cv2.putText(img, str(int(fps)), (12, 70), cv2.FONT_HERSHEY_PLAIN, 3,
  53. (255, 0, 0), 3)
  54. cv2.imshow("Image", img)
  55. k = cv2.waitKey(1)
  56. if k == 27:
  57. break
  58. if __name__ == "__main__":
  59. main()

从最上面的图中,我们可以看到索引4是指大拇指,之后我们可以可以根据这个做很多有趣的项目。

项目的展示(大拇指)

  1. import cv2
  2. import mediapipe as mp
  3. import time
  4. import HandTrackingModule as htm
  5. pTime = 0
  6. cTime = 0
  7. cap = cv2.VideoCapture(0)
  8. detector = htm.handDetector()
  9. while True:
  10. success, img = cap.read()
  11. img = detector.findHands(img, draw=True )
  12. lmList = detector.findPosition(img, draw=False)
  13. if len(lmList) != 0:
  14. print(lmList[4])
  15. cTime = time.time()
  16. fps = 1 / (cTime - pTime)
  17. pTime = cTime
  18. #cv2.putText(img, str(int(fps)), (12, 70), cv2.FONT_HERSHEY_PLAIN, 3,
  19. # (255, 0, 0), 3)
  20. cv2.imshow("Image", img)
  21. k=cv2.waitKey(1)
  22. if k==27:
  23. break

以下是控制台中的信息。

  1. [4, 210, 30]
  2. [4, 211, 30]
  3. [4, 216, 32]
  4. [4, 227, 32]
  5. [4, 228, 32]
  6. [4, 228, 33]
  7. [4, 240, 33]
  8. [4, 239, 35]
  9. [4, 252, 35]
  10. [4, 262, 33]
  11. [4, 259, 32]
  12. [4, 268, 32]
  13. [4, 275, 33]
  14. [4, 276, 34]
  15. [4, 294, 32]
  16. [4, 325, 22]
  17. [4, 325, 22]

可以看到这是我移动大拇指的信息。

4、项目的资源

GitHub:Opencv-project-training/Opencv project training/13 Hand Tracking at main · Auorui/Opencv-project-training · GitHub

如果大家觉得有用可以点击这里,谢谢大家的支持。

5、项目的总结

上周由于事情较多,所以没有更新,而且最近的学校里的功课也要做,所以很抱歉,今天的这个项目我觉得很有用,就比如在这之后的一些项目也会用到,到时候可以做很多有趣的项目。


本文转载自: https://blog.csdn.net/m0_62919535/article/details/127434796
版权归原作者 夏天是冰红茶 所有, 如有侵权,请联系我们删除。

“Opencv实战项目:13 手部追踪”的评论:

还没有评论