• 售前

  • 售后

热门帖子
入门百科

OpenCV+MediaPipe实现手部关键点辨认

[复制链接]
大黄瓜xxxl 显示全部楼层 发表于 2022-1-8 07:37:16 |阅读模式 打印 上一主题 下一主题
目次


  • 可视化辅助函数
  • 单张图片
  • 摄像头检测
  • 改变关键点数据特性

可视化辅助函数

在下面的代码的解释内有大致的操作
根本操作与前面的人脸检测的操作相似,增长了可视化的辅助函数
  1. import matplotlib.pyplot as plt
  2. # 使用ipython的魔法方法,将绘制出的图像直接嵌入在notebook单元格中
  3. import cv2
  4. # 定义可视化图像函数
  5. def look_img(img):
  6.     '''opencv读入图像格式为BGR,matplotlib可视化格式为RGB,因此需将BGR转RGB'''
  7.     img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  8.     plt.imshow(img_RGB)
  9.     plt.show()
  10. #调用摄像头拍照
  11. time.sleep(2) # 运行本代码后两秒拍照
  12. # 获取摄像头,0为电脑默认摄像头,1为外接摄像头
  13. cap = cv2.VideoCapture(0)
  14. # 从摄像头捕获一帧画面
  15. success, image = cap.read()
  16. # 关闭摄像头
  17. cap.release()
  18. # 关闭图像窗口
  19. cv2.destroyAllWindows()
  20. cv2.imwrite('photo.jpg', image)
  21. #调用摄像头拍视频
  22. import cv2
  23. import time
  24. # 定义逐帧处理函数,可不进行任何处理,直接将摄像头捕获的画面写入视频帧
  25. def process_frame(img):
  26.     return img
  27. output_name = 'record_video.mp4'
  28. # 获取摄像头,传入0表示获取系统默认摄像头
  29. cap = cv2.VideoCapture(0)
  30. # 打开cap
  31. cap.open(0)
  32. frame_size = (cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
  33. fourcc = cv2.VideoWriter_fourcc(*'mp4v')
  34. fps = cap.get(cv2.CAP_PROP_FPS)
  35. out = cv2.VideoWriter(output_name, fourcc, fps, (int(frame_size[0]), int(frame_size[1])))
  36. # 无限循环,直到break被触发
  37. while cap.isOpened():
  38.     # 获取画面
  39.     success, frame = cap.read()
  40.     if not success:
  41.         break
  42.     # 对捕获的帧进行图像处理
  43.     frame = process_frame(frame)
  44.     ## 将帧写入视频文件中
  45.     out.write(frame)
  46.     # 展示处理后的三通道图像
  47.     cv2.imshow('press q to break', frame)
  48.     if cv2.waitKey(1) in [ord('q'), 27]:  # 按键盘上的q或esc退出(在英文输入法下)
  49.         break
  50. # 关闭图像窗口
  51. cv2.destroyAllWindows()
  52. out.release()
  53. # 关闭摄像头
  54. cap.release()
  55. print('视频已保存', output_name)
复制代码
单张图片
  1. import cv2 as cv
  2. import mediapipe as mp
  3. import  tqdm
  4. import time
  5. import  matplotlib.pyplot as plt
  6. def look_img(img):
  7.     img_RGB=cv.cvtColor(img,cv.COLOR_BGR2RGB)
  8.     plt.imshow(img_RGB)
  9.     plt.show()
  10. # 手部关键点检测模型
  11. mp_hand=mp.solutions.hands
  12. # 导入模型
  13. hands=mp_hand.Hands(static_image_mode=False,
  14.                     max_num_hands=5,
  15.                     min_detection_confidence=0.3,
  16.                     min_tracking_confidence=0.3
  17.                     )
  18. # 导入绘图函数
  19. mpDraw=mp.solutions.drawing_utils
  20. img=cv.imread('hand2.png')
  21. # look_img(img)
  22. img_RGB=cv.cvtColor(img,cv.COLOR_BGR2RGB)
  23. results=hands.process(img_RGB)
  24. if results.multi_hand_landmarks:
  25.     for hand_idx in range(len(results.multi_hand_landmarks)):
  26.         hand_21=results.multi_hand_landmarks[hand_idx]
  27.         mpDraw.draw_landmarks(img, hand_21, mp_hand.HAND_CONNECTIONS)  # 可视化
  28. look_img(img)
  29. cv.imwrite('hands2.jpg',img)
  30. # 在三维坐标系中可视化索引为0的手
  31. mpDraw.plot_landmarks(results.multi_hand_landmarks[0], mp_
复制代码


摄像头检测
  1. import cv2
  2. # mediapipe人工智能工具包
  3. import mediapipe as mp
  4. # 进度条库
  5. from tqdm import tqdm
  6. # 时间库
  7. import time
  8. # 导入模型
  9. # 导入solution
  10. mp_hands = mp.solutions.hands
  11. # 导入模型
  12. hands = mp_hands.Hands(static_image_mode=False,        # 是静态图片还是连续视频帧
  13.                        max_num_hands=2,                # 最多检测几只手
  14.                        min_detection_confidence=0.7,   # 置信度阈值
  15.                        min_tracking_confidence=0.5)    # 追踪阈值
  16. # 导入绘图函数
  17. mpDraw = mp.solutions.drawing_utils
  18. # 处理单帧函数
  19. # 处理帧函数
  20. def process_frame(img):
  21.     # 水平镜像翻转图像,使图中左右手与真实左右手对应
  22.     # 参数 1:水平翻转,0:竖直翻转,-1:水平和竖直都翻转
  23.     img = cv2.flip(img, 1)
  24.     # BGR转RGB
  25.     img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  26.     # 将RGB图像输入模型,获取预测结果
  27.     results = hands.process(img_RGB)
  28.     if results.multi_hand_landmarks:  # 如果有检测到手
  29.         # 遍历每一只检测出的手
  30.         for hand_idx in range(len(results.multi_hand_landmarks)):
  31.             hand_21 = results.multi_hand_landmarks[hand_idx]  # 获取该手的所有关键点坐标
  32.             mpDraw.draw_landmarks(img, hand_21, mp_hands.HAND_CONNECTIONS)  # 可视化
  33.         # 在三维坐标系中可视化索引为0的手
  34.         # mpDraw.plot_landmarks(results.multi_hand_landmarks[0], mp_hands.HAND_CONNECTIONS)
  35.     return img
  36. # 导入opencv-python
  37. import cv2
  38. import time
  39. # 获取摄像头,传入0表示获取系统默认摄像头
  40. cap = cv2.VideoCapture(1)
  41. # 打开cap
  42. cap.open(0)
  43. # 无限循环,直到break被触发
  44. while cap.isOpened():
  45.     # 获取画面
  46.     success, frame = cap.read()
  47.     if not success:
  48.         print('Error')
  49.         break
  50.     ## !!!处理帧函数
  51.     frame = process_frame(frame)
  52.     # 展示处理后的三通道图像
  53.     cv2.imshow('my_window', frame)
  54.     if cv2.waitKey(1) in [ord('q'), 27]:  # 按键盘上的q或esc退出(在英文输入法下)
  55.         break
  56. # 关闭摄像头
  57. cap.release()
  58. # 关闭图像窗口
  59. cv2.destroyAllWindows()
复制代码
改变关键点数据特性
  1. import cv2
  2. # mediapipe人工智能工具包
  3. import mediapipe as mp
  4. # 进度条库
  5. from tqdm import tqdm
  6. # 时间库
  7. import time
  8. # 导入solution
  9. mp_hands = mp.solutions.hands
  10. # 导入模型
  11. hands = mp_hands.Hands(static_image_mode=False,        # 是静态图片还是连续视频帧
  12.                        max_num_hands=2,                # 最多检测几只手
  13.                        min_detection_confidence=0.7,   # 置信度阈值
  14.                        min_tracking_confidence=0.5)    # 追踪阈值
  15. # 导入绘图函数
  16. mpDraw = mp.solutions.drawing_utils
  17. def process_frame(img):
  18.     # 记录该帧开始处理的时间
  19.     start_time = time.time()
  20.     # 获取图像宽高
  21.     h, w = img.shape[0], img.shape[1]
  22.     # 水平镜像翻转图像,使图中左右手与真实左右手对应
  23.     # 参数 1:水平翻转,0:竖直翻转,-1:水平和竖直都翻转
  24.     img = cv2.flip(img, 1)
  25.     # BGR转RGB
  26.     img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  27.     # 将RGB图像输入模型,获取预测结果
  28.     results = hands.process(img_RGB)
  29.     if results.multi_hand_landmarks:  # 如果有检测到手
  30.         handness_str = ''
  31.         index_finger_tip_str = ''
  32.         for hand_idx in range(len(results.multi_hand_landmarks)):
  33.             # 获取该手的21个关键点坐标
  34.             hand_21 = results.multi_hand_landmarks[hand_idx]
  35.             # 可视化关键点及骨架连线
  36.             mpDraw.draw_landmarks(img, hand_21, mp_hands.HAND_CONNECTIONS)
  37.             # 记录左右手信息
  38.             temp_handness = results.multi_handedness[hand_idx].classification[0].label
  39.             handness_str += '{}:{} '.format(hand_idx, temp_handness)
  40.             # 获取手腕根部深度坐标
  41.             cz0 = hand_21.landmark[0].z
  42.             for i in range(21):  # 遍历该手的21个关键点
  43.                 # 获取3D坐标
  44.                 cx = int(hand_21.landmark[i].x * w)
  45.                 cy = int(hand_21.landmark[i].y * h)
  46.                 cz = hand_21.landmark[i].z
  47.                 depth_z = cz0 - cz
  48.                 # 用圆的半径反映深度大小
  49.                 radius = max(int(6 * (1 + depth_z * 5)), 0)
  50.                 if i == 0:  # 手腕
  51.                     img = cv2.circle(img, (cx, cy), radius, (0, 0, 255), -1)
  52.                 if i == 8:  # 食指指尖
  53.                     img = cv2.circle(img, (cx, cy), radius, (193, 182, 255), -1)
  54.                     # 将相对于手腕的深度距离显示在画面中
  55.                     index_finger_tip_str += '{}:{:.2f} '.format(hand_idx, depth_z)
  56.                 if i in [1, 5, 9, 13, 17]:  # 指根
  57.                     img = cv2.circle(img, (cx, cy), radius, (16, 144, 247), -1)
  58.                 if i in [2, 6, 10, 14, 18]:  # 第一指节
  59.                     img = cv2.circle(img, (cx, cy), radius, (1, 240, 255), -1)
  60.                 if i in [3, 7, 11, 15, 19]:  # 第二指节
  61.                     img = cv2.circle(img, (cx, cy), radius, (140, 47, 240), -1)
  62.                 if i in [4, 12, 16, 20]:  # 指尖(除食指指尖)
  63.                     img = cv2.circle(img, (cx, cy), radius, (223, 155, 60), -1)
  64.         scaler = 1
  65.         img = cv2.putText(img, handness_str, (25 * scaler, 100 * scaler), cv2.FONT_HERSHEY_SIMPLEX, 1.25 * scaler,
  66.                           (255, 0, 255), 2 * scaler)
  67.         img = cv2.putText(img, index_finger_tip_str, (25 * scaler, 150 * scaler), cv2.FONT_HERSHEY_SIMPLEX,
  68.                           1.25 * scaler, (255, 0, 255), 2 * scaler)
  69.         # 记录该帧处理完毕的时间
  70.         end_time = time.time()
  71.         # 计算每秒处理图像帧数FPS
  72.         FPS = 1 / (end_time - start_time)
  73.         # 在图像上写FPS数值,参数依次为:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细
  74.         img = cv2.putText(img, 'FPS  ' + str(int(FPS)), (25 * scaler, 50 * scaler), cv2.FONT_HERSHEY_SIMPLEX,
  75.                           1.25 * scaler, (255, 0, 255), 2 * scaler)
  76.     return img
  77. # 获取摄像头,传入0表示获取系统默认摄像头
  78. cap = cv2.VideoCapture(0)
  79. # 打开cap
  80. cap.open(0)
  81. # 无限循环,直到break被触发
  82. while cap.isOpened():
  83.     # 获取画面
  84.     success, frame = cap.read()
  85.     if not success:
  86.         break
  87.     frame = process_frame(frame)
  88.     # 展示处理后的三通道图像
  89.     cv2.imshow('my_window', frame)
  90.     if cv2.waitKey(1) in [ord('q'), 27]:  # 按键盘上的q或esc退出(在英文输入法下)
  91.         break
  92. # 关闭摄像头
  93. cap.release()
  94. # 关闭图像窗口
  95. cv2.destroyAllWindows()
复制代码

以上就是OpenCV+MediaPipe实现手部关键点识别的详细内容,更多关于OpenCV MediaPipe手部关键点识别的资料请关注脚本之家别的相干文章!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作