MediaPipe+UNO手勢控制伺服馬達


MediaPipe+UNO手勢控制伺服馬達

tags: mediapipe arduino servo

參考視頻網址:

https://youtu.be/9iEPzbG-xLE

MediaPipe

簡單來說是google跨平台而且開源的機器學習運用

MediaPipe是一款由Google開發並開源的數據流處理機器學習應用開發框架。它是一個基於圖的數據處理管線,用於構建使用了多種形式的數據源,如視頻、音頻、傳感器數據以及任何時間序列數據。 MediaPipe是跨平台的,可以運行在嵌入式平台(樹莓派等),移動設備(iOS和Android),工作站和服務器上,並支持移動端GPU加速。使用MediaPipe,可以將機器學習任務構建為一個圖形的模塊表示的數據流管道,可以包括推理模型和流媒體處理功能。

pinpong

pinpong庫是一套控制開源硬件主控板的Python庫

,基於Firmata協議並兼容MicroPython語法,5分鐘即可讓你上手使用Python控制開源硬件。

有興趣可以到pinpong官網看一下,

我是使用pycharm,所以首先安裝opencv-python,mediapipe和pinpong這兩個主要的程式庫

步驟1:

先把這個程式庫命名為handutil.py和主程式放一起

import cv2  
import mediapipe as mp  
  
class HandDetector():  
'''  
   手势识别类  
'''   
def _init_(self, mode=False, max_hands=2, detection_con=0.5, track_con=0.5):  
'''  
   初始化  
   :param mode: 是否静态图片,默认为False  
   :param max_hands: 最多几只手,默认为2只  
   :param detection_con: 最小检测信度值,默认为0.5  
   :param track_con: 最小跟踪信度值,默认为0.5  
 '''   
    self.mode = mode  
    self.max_hands = max_hands  
    self.detection_con = detection_con  
    self.track_con = track_con  

    self.hands = mp.solutions.hands.Hands(self.mode, self.max_hands, self.detection_con, self.track_con)  
  
    def find_hands(self, img, draw=True):  
        '''  
   检测手势  
   :param img: 视频帧图片  
   :param draw: 是否画出手势中的节点和连接图  
   :return: 处理过的视频帧图片  
 '''   imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  
        # 处理图片,检测是否有手势,将数据存进self.results中  
        self.results = self.hands.process(imgRGB)  
                if draw:  
                    if self.results.multi_hand_landmarks:  
                        for handlms in self.results.multi_hand_landmarks:  
                            mp.solutions.drawing_utils.draw_landmarks(img, handlms, mp.solutions.hands.HAND_CONNECTIONS)  
        return img  
  
    def find_positions(self, img, hand_no=0):  
        '''  
   获取手势数据  
   :param img: 视频帧图片  
   :param hand_no: 手编号(默认第1只手)  
   :return: 手势数据列表,每个数据成员由id, x, y组成,代码这个手势位置编号以及在屏幕中的位置  
    '''   
        self.lmslist = []  
        if self.results.multi_hand_landmarks:  
            hand = self.results.multi_hand_landmarks[hand_no]  
            for id, lm in enumerate(hand.landmark):  
                h, w, c = img.shape  
                cx, cy = int(lm.x * w), int(lm.y * h)  
                self.lmslist.append([id, cx, cy])  
  
        return self.lmslist

步驟2:

複制貼上主程式

*這裡留意一下計算斜角轉成角度的公式

算出角度:

假如两点坐标分别是(x1,y1)(x2,y2)

那么斜率是:(y2-y1)/(x2-x1)

k=(y2-y1)/(x2-x1) 其中(x1,y1),(x2,y2) 是已知两点的坐标

已知A(x1,y1),B(x2,y2)  
1、若x1=x2,则斜率不存在;  
2、若x1≠x2,则斜率k=(y2-y1)/(x2-x1)

算出弧度:

import math

math.degrees(x)

**x為一個值**
import cv2  
from HandTrackingMoudle import handDetector  
import math  
import numpy as np  
from pinpong.board import Board, Pin, Servo  
import time  
  
Board("uno").begin()  
myServo = Servo(Pin(Pin.A0))  
  
cap = cv2.VideoCapture(0)  
  
detector = handDetector()  
angle = 0  
while True:  
    success, img = cap.read()  
    img = detector.findHands(img, draw=True)  
    lmList = detector.findPosition(img, personDraw=False)  
    if len(lmList) > 0:  
        print(lmList[4], lmList[8])  
        x1, y1 = lmList[4][1], lmList[4][2]  
        x2, y2 = lmList[8][1], lmList[8][2]  
        cv2.circle(img, (x1, y1), 15, (200, 10, 100), cv2.FILLED)  
        cv2.circle(img, (x2, y2), 15, (200, 10, 100), cv2.FILLED)  
        cv2.line(img, (x1, y1), (x2, y2), (200, 10, 100), 4)  
  
        if (x1 - x2) != 0:  
            angle = math.degrees(np.arctan((y2 - y1)/(x2 - x1)))  
            a = 180 - angle  
            myServo.write_angle(int(a))  
            print(int(a))  
        if angle < 0:  
            angle = abs(angle)  
            myServo.write_angle(int(angle))  
            print(int(angle))  
  
  
    cv2.imshow("Image", img)  
    cv2.waitKey(1)

步驟3:

執行程式碼



文章作者: blairan
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY 4.0 許可協議。轉載請註明來源 blairan !
评论
  目錄