一文了解如何使用Python+OpenCV构建手部跟踪系统

磐创AI

    OpenCV 是一个用于计算机视觉应用程序的库。在 OpenCV 的帮助下,我们可以构建大量实时运行更好的应用程序。主要用于图像和视频处理。可以在此处获取有关 OpenCV 的更多信息
    除了 OpenCV,我们将使用 MediaPipe 库。MediaPipeMediaPipe是一个主要用于构建音频、视频或任何时间序列数据的框架。在 MediaPipe 框架的帮助下,我们可以为不同的媒体处理功能构建管道。MediaPipe 的一些主要应用。多手追踪人脸检测对象检测和跟踪Objection:3D 对象检测和跟踪AutoFlip:自动视频裁剪管道等。
    手地标模型
    
    MediaPipe 使用单次手掌检测模型,一旦完成,它会对检测到的手部区域中的 21 个 3D 手掌坐标执行精确的关键点定位。MediaPipe 管道使用多个模型,例如,从完整图像返回定向手边界框的手掌检测模型。裁剪后的图像区域被馈送到由手掌检测器定义的手部标志模型,并返回高保真 3D 手部关键点。现在让我们实现手部跟踪模型。安装所需的模块–> pip install opencv-python–> pip install mediapipe首先,让我们检查网络摄像头的工作情况。import cv2
    import time
    cap = cv2.VideoCapture(0)
    pTime = 0
    while True:
        success, img = cap.read()
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        cTime = time.time()
        fps = 1 / (cTime - pTime)
        pTime = cTime
        cv2.putText(img, f'FPS:{int(fps)}', (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
        cv2.imshow("Test", img)
    cv2.waitKey(1)
    
    如果任何网络摄像头连接到你的 PC,上面的代码将弹出一个窗口,并在输出窗口的左上角显示每秒帧数 (fps)。现在让我们开始实施。导入所需的模块并初始化所需的变量。import cv2
    import mediapipe as mp
    import time
    cap = cv2.VideoCapture(0)
    mpHands = mp.solutions.hands
    hands = mpHands.Hands(static_image_mode=False,
                          max_num_hands=2,
                          min_detection_confidence=0.5,
                          min_tracking_confidence=0.5)
    mpDraw = mp.solutions.drawing_utils
    pTime = 0
    cTime = 0
    在上面这段代码中,我们在mp.solutions.hand 中声明了一个名为“hands”的对象来检测手部,默认情况下,查看类“ Hands() ”内部,要检测的手部数量设置为2、最小检测置信度设置为0.5,最小跟踪置信度设置为0.5。我们将使用mpDraw绘制关键点。现在让我们编写一个 while 循环来执行我们的代码。while True:
        success, img = cap.read()
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        results = hands.process(imgRGB)
        #print(results.multi_hand_landmarks)
        if results.multi_hand_landmarks:
            for handLms in results.multi_hand_landmarks:
                for id, lm in enumerate(handLms.landmark):
                    #print(id,lm)
                    h, w, c = img.shape
                    cx, cy = int(lm.x *w), int(lm.y*h)
                    #if id ==0:
                    cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)
                mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
        cTime = time.time()
        fps = 1/(cTime-pTime)
        pTime = cTime
        cv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)
        cv2.imshow("Image", img)
        cv2.waitKey(1)
    在上面的代码中,我们从网络摄像头读取帧并将图像转换为 RGB。然后我们在“ hands.process()” 函数的帮助下检测帧中的手。一旦检测到手,我们将找到关键点,然后使用cv2.circle突出显示关键点中的点,并使用mpDraw.draw_landmarks连接关键点。整个代码如下import cv2
    import mediapipe as mp
    import time
    cap = cv2.VideoCapture(0)
    mpHands = mp.solutions.hands
    hands = mpHands.Hands(static_image_mode=False,
                          max_num_hands=2,
                          min_detection_confidence=0.5,
                          min_tracking_confidence=0.5)
    mpDraw = mp.solutions.drawing_utils
    pTime = 0
    cTime = 0
    while True:
        success, img = cap.read()
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        results = hands.process(imgRGB)
        #print(results.multi_hand_landmarks)
        if results.multi_hand_landmarks:
            for handLms in results.multi_hand_landmarks:
                for id, lm in enumerate(handLms.landmark):
                    #print(id,lm)
                    h, w, c = img.shape
                    cx, cy = int(lm.x *w), int(lm.y*h)
                    #if id ==0:
                    cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)
                mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
        cTime = time.time()
        fps = 1/(cTime-pTime)
        pTime = cTime
        cv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)
        cv2.imshow("Image", img)
        cv2.waitKey(1)
    输出是:
    
    手部追踪模型输出现在让我们创建一个手部跟踪模块,以便我们可以在其他项目中使用它。创建一个新的 python 文件,首先让我们创建一个名为handDetector的类,其中有两个成员函数,名为findHands 和findPosition。函数findHands将接受一个 RGB 图像并检测帧中的手并定位关键点,绘制地标,函数findPosition 将给出手的位置和 id。然后是我们初始化模块的 main 函数,我们还编写了一个 while 循环来运行模型。你可以在此处将此设置或模块导入到任何其他相关项目作品中。整个代码如下import cv2
    import mediapipe as mp
    import time
    class handDetector():
        def __init__(self, mode = False, maxHands = 2, detectionCon = 0.5, trackCon = 0.5):
            self.mode = mode
            self.maxHands = maxHands
            self.detectionCon = detectionCon
            self.trackCon = trackCon
            self.mpHands = mp.solutions.hands
            self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.detectionCon, self.trackCon)
            self.mpDraw = mp.solutions.drawing_utils
            
        def findHands(self,img, draw = True):
            imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            self.results = self.hands.process(imgRGB)
            # print(results.multi_hand_landmarks)
            if self.results.multi_hand_landmarks:
                for handLms in self.results.multi_hand_landmarks:
                    if draw:
                        self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
            return img
        def findPosition(self, img, handNo = 0, draw = True):
            lmlist = []
            if self.results.multi_hand_landmarks:
                myHand = self.results.multi_hand_landmarks[handNo]
                for id, lm in enumerate(myHand.landmark):
                    h, w, c = img.shape
                    cx, cy = int(lm.x * w), int(lm.y * h)
                    lmlist.append([id, cx, cy])
                    if draw:
                        cv2.circle(img, (cx, cy), 3, (255, 0, 255), cv2.FILLED)
            return lmlist
    def main():
        pTime = 0
        cTime = 0
        cap = cv2.VideoCapture(0)
        detector = handDetector()
        while True:
            success, img = cap.read()
            img = detector.findHands(img)
            lmlist = detector.findPosition(img)
            if len(lmlist) != 0:
                print(lmlist[4])
            cTime = time.time()
            fps = 1 / (cTime - pTime)
            pTime = cTime
            cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
            cv2.imshow("Image", img)
            cv2.waitKey(1)
    if __name__ == "__main__":
        main()
    输出将与上面显示的相同,以及被跟踪的手的位置。