MeidaPipe+UNO手勢控制neopixel燈條

MeidaPipe+UNO手勢控制neopixel燈條

偶然間看到一些神們分享mediapipe的神作,我一心響往,但又摸不著頭緒,因為學著學著很多東西弄了整個生活很緊張,一刻不得閒。


參考視頻網址:

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

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:

複制貼上主程式
 
*注意一下這個計算兩點之間距離的公式 ,這個會概括到食指和姆指間的伸縮
自動取距離

import cv2
from pinpong.board import Board, Pin, NeoPixel
import time
import HandTrackingMoudle as htm
import math
#######################################
wCam, hCam = 640, 480 #視窗大小
#######################################
#pinpong初始化設定
Board('uno').begin()
ledPin = Pin(Pin.D6)
LED_NUM = 8
neoPixel_LED = NeoPixel(ledPin, LED_NUM)
######################################
num = 0
cap = cv2.VideoCapture(0) #視窗
cap.set(3, wCam)
cap.set(4, hCam)
pTime = 0
detector = htm.handDetector() #呼叫"手勢追蹝"的函式
while True:
success, img = cap.read() #讀取視窗
cTime = time.time()
img = detector.findHands(img, draw=True) #找手
lmList = detector.findPosition(img, personDraw=False) #在找出的手上畫出節點
if len(lmList) != 0:
# print(lmList[4], lmList[8])
#因只要大姆指和食指,節點截取48即可
x1, y1 = lmList[4][1], lmList[4][2]
x2, y2 = lmList[8][1], lmList[8][2]
cv2.circle(img, (x1, y1), 10, (255, 255, 0), cv2.FILLED)
cv2.circle(img, (x2, y2), 10,(255, 255, 0), cv2.FILLED)
cv2.line(img, (x1, y1), (x2, y2), (255,255,0), 7)
length = math.hypot(x2 - x1, y2 - y1) #計算兩點間的距離
print(length)
if length < 40:
cv2.line(img, (x1, y1), (x2, y2), (255, 100, 100), 7)
cv2.putText(img, f'distance: {round(length)}', (30, 80), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 50))
for num in range(0, int(length/220*8)):
if num > 7:
num = 7
neoPixel_LED[num] = (200, 10, 150)
if num != 7:
for k in range(0, 8):
neoPixel_LED[k] = (0, 0, 0)

print("num= %d"%num)

fps = 1/(cTime - pTime)
pTime = cTime
cv2.putText(img, f'FPS: {int(fps)}', (30, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (50,125,50))
cv2.imshow("img", img)
cv2.waitKey(1)
因為pinpong這個程式庫目前支援uno,所以我是用uno來實驗

步驟3:

準備Adafruit燈條,pinpong裡也支援燈條的庫,所以只管把它安裝上去uno即可


步驟4:

執行程式










留言

這個網誌中的熱門文章

平衡小車(balance-Robot)-基本平衡-Arduino