使用MediaPipe进行图像手部地标检测的方法

概述

在本文中,我们将以深度库即 Mediapipe为基础库,以及其他计算机视觉预处理的CV2库来制作手部地标检测模型。市场上有很多关于这种问题的用例,例如商业相关的虚拟现实、游戏部分的实时体验。e70305c1c2f1c7e96fdc010a3ce4e4de.png

行业用例
  1. 智能家居:这是计算机视觉的现代用例之一,人们使用智能家居来过上更舒适的生活,这就是为什么它不再是一个小众领域,它也正在蔓延到普通家庭。
  2. 智能电视:我们经常看到这种用例,你可以用手势来改变音量、改变频道等等。
  3. 游戏:对于真正的体验,这项技术越来越多地融入互动游戏。

让我们建立我们的手部检测模型

导入库

在这里,我们将导入整个管道中需要的所有库

import cv2import numpy as npimport mediapipe as mpimport matplotlib.pyplot as plt

使用 Mediapipe 初始化手的地标检测模型

第一步是使用有效参数初始化模型,无论我们采用哪种检测技术,它可以是Mediapipe 或Yolo,初始化模型很重要,遵循相同的原则,我们将遵循所有给定的步骤:

# First step is to initialize the Hands class an store it in a variablemp_hands = mp.solutions.hands # Now second step is to set the hands function which will hold the landmarks pointshands = mp_hands.Hands(static_image_mode=True, max_num_hands=2, min_detection_confidence=0.3) # Last step is to set up the drawing function of hands landmarks on the imagemp_drawing = mp.solutions.drawing_utils

代码分解:

  1. 首先,使用mp.solutions.hands初始化变量 mp_hands。
  2. 然后使用相同的变量通过mp.solutions.hands.Hands()为hands设置函数。

到目前为止,我们了解了手模型初始化的结构,现在让我们深入研究函数中使用的参数hands

  • static_image_mode: 该参数将布尔值作为其有效值,即它可以是True或False。当处理视频流时,默认条件是 False ,这意味着它会降低处理延迟,即它会继续专注于特定的手并定位相同的手,直到它追踪的手消失,当我们必须检测实时流或视频中的手时,这可能是有益的,根据我们的要求,我们必须检测图像上的地标,因此我们将值设置为True。
  • max_num_hands:此参数将指示模型将在一个实例中检测到的最大手数。默认情况下,该值为 2,这也是有意义的,尽管我们可以更改它,但我们希望至少检测到一双手。
  • min_detection_confidence:它提供了置信水平的阈值。最小检测置信度的理想范围是 [0.0,1.0],默认情况下,它保持为 0.5,这意味着如果置信度低于 50%,则在输出图像中根本不会检测到手。

最后,我们将使用mp.solutions.drawing_utils,它将负责在输出图像上绘制所有手的地标,这些地标由我们的 Hands 函数检测到。

读取图像

在这里,我们将首先使用cv2.imread()读取要在其上执行手部检测的图像,并使用matplotlib库来显示该特定输入图像。

# Reading the sample image on which we will perform the detectionsample_img = cv2.imread('media/sample.jpg') # Here we are specifing the size of the figure i.e. 10 -height; 10- width.plt.figure(figsize = [10, 10]) # Here we will display the sample image as the output.plt.title("Sample Image");plt.axis('off');plt.imshow(sample_img[:,:,::-1]);plt.show()

输出:b9ccd672254b0ea9775d26550736acf2.png

执行手部地标检测

因此,现在我们已经初始化了我们的手部检测模型,下一步将是处理输入图像上的手部地标检测,并使用上述初始化模型在该图像上绘制所有 21 个地标,我们将通过以下步骤。f939f4cbd80b1afbb6672466548623ff.png

results = hands.process(cv2.cvtColor(sample_img, cv2.COLOR_BGR2RGB)) if results.multi_hand_landmarks:       for hand_no, hand_landmarks in enumerate(results.multi_hand_landmarks):        print(f'HAND NUMBER: {hand_no+1}')        print('-----------------------')                for i in range(2):            print(f'{mp_hands.HandLandmark(i).name}:')            print(f'{hand_landmarks.landmark[mp_hands.HandLandmark(i).value]}')

输出:a76f9c5dcb1b326ca5dfadc1cac4f544.png

代码分解:

  1. 第一步,我们使用Mediapipe 库中的process函数将手部地标检测结果存储在变量results中,同时我们将图像从 BGR 格式转换为 RGB 格式。
  2. 在进入下一步时,我们将首先检查一些验证,是否检测到点,即变量results应该存放了一些结果。
  3. 如果是,那么我们将遍历在图像中检测到的具有手部地标的所有点。
  4. 现在在另一个循环中,我们可以看到只有 2 次迭代,因为我们只想显示手的 2 个地标。
  5. 最后,我们将根据要求打印出所有检测到并过滤掉的地标。

从上面的处理中,我们发现所有检测到的地标都被归一化为通用尺度,但是现在对于用户端,这些缩放点是不相关的,因此我们会将这些地标恢复到原始状态。

image_height, image_width, _ = sample_img.shape if results.multi_hand_landmarks:     for hand_no, hand_landmarks in enumerate(results.multi_hand_landmarks):                print(f'HAND NUMBER: {hand_no+1}')        print('-----------------------')                for i in range(2):                print(f'{mp_hands.HandLandmark(i).name}:')             print(f'x: {hand_landmarks.landmark[mp_hands.HandLandmark(i).value].x * image_width}')            print(f'y: {hand_landmarks.landmark[mp_hands.HandLandmark(i).value].y * image_height}')            print(f'z: {hand_landmarks.landmark[mp_hands.HandLandmark(i).value].z * image_width}n')

输出:85996c657b8e52358a96340301f70972.png

代码分解:

我们只需要在这里执行一个额外的步骤,即我们将从我们定义的示例图像中获得图像的原始宽度和高度,然后所有步骤将与我们之前所做的相同,唯一不同的将是现在地标点没有专门缩放。

在图像上绘制地标

由于我们已经从上述预处理中获得了手部地标,现在是时候执行我们的最后一步了,即在图像上绘制点,以便我们可以直观地看到我们的手部地标检测模型是如何执行的。

img_copy = sample_img.copy() if results.multi_hand_landmarks:     for hand_no, hand_landmarks in enumerate(results.multi_hand_landmarks):                mp_drawing.draw_landmarks(image = img_copy, landmark_list = hand_landmarks,                                  connections = mp_hands.HAND_CONNECTIONS)    fig = plt.figure(figsize = [10, 10])     plt.title("Resultant Image");plt.axis('off');plt.imshow(img_copy[:,:,::-1]);plt.show()

输出:6a0c07e5f042039cfbbe0c406dc2e1cd.png

代码分解:

  1. 首先,我们将创建原始图像的副本,此步骤是出于安全目的,因为我们不想失去图像的原创性。
  2. 然后我们将处理之前所做的验证工作。
  3. 然后我们将遍历手的每个地标。
  4. 最后,借助mp_drawing.draw_landmarks函数,我们将在图像上绘制地标。
  5. 是时候使用 matplotlib 绘制图像了,所以首先,我们将给出图形大小(此处为 width-10 和 height-10),然后在最后绘制,imshow将 BGR 格式转换为 RGB 格式后的图像使用函数,因为对于 RGB 格式更有意义。

结论

在整个管道中,我们首先初始化模型,然后读取图像,查看输入图像,然后进行预处理。我们缩小了地标点,但这些点与用户无关,因此我们将其恢复到原始状态,最后我们将在图像上绘制地标。

免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空