引言
我是一名專注于機器學習和機器人技術自由者。我的熱情始于大學期間的人工智能課程,這促使我探索人機交互的新方法。尤其對于機械臂的操作,我一直想要簡化其復雜性,使之更加直觀和易于使用。
這個項目的靈感源自于我對創新技術的熱愛以及對改善人機互動方式的追求。我的目標是開發一個基于手勢的機械臂控制系統,使非專業人士也能輕松操作。為此,我選擇了Google的MediaPipe庫進行手勢識別,并以myCobot 320 m5作為實驗平臺。
技術概述
Google MediaPipe
MediaPipe是由Google開發的一個開源跨平臺框架,專門用于構建各種感知管道。這個框架提供了豐富的工具和預先構建的模塊,使得開發者能夠輕松地構建和部署復雜的機器學習模型和算法,尤其在圖像和視頻分析方面。
MediaPipe的一個顯著特點是它對實時手勢和面部識別的支持。它能夠高效地處理視頻流,并實時識別和追蹤人的手勢、面部特征等。這種能力使其在交互式應用程序、增強現實(AR)、虛擬現實(VR)以及機器人技術中變得極其有用。
你可以嘗試試用一下手勢識別在線功能,無需安裝。
https://mediapipe-studio.webapps.google.com/home
它的簡單易用的API和豐富的文檔使得更容易集成這個框架,非常適合使用在機器學習和計算機視覺領域當中。
pymycobot
pymycobot 是一個用于與 mycobot 機械臂進行串行通信和控制的 Python API。這個庫是為了方便開發者使用 Python 語言控制 mycobot 機械臂而設計的。它提供了一系列的函數和命令,讓用戶可以通過編程方式控制機械臂的動作和行為。例如,用戶可以使用該庫獲取機械臂的角度、發送角度指令來控制機械臂的移動,或者獲取和發送機械臂的坐標信息。
使用這個庫唯一的標準是,得使用mycobot 系列的機械臂,這是專門為mycobot進行適配的一款機械臂。
產品介紹
myCobot 320M5 stack
myCobot 320 M5 是大象機器人開發的一款面向用戶的六軸協作機械臂。它具有350mm的工作半徑和最大1000g的負載能力。該機械臂適用于開放的ROS仿真開發環境,并包含運動學正逆解算法。它支持多種編程語言,包括Python、C++、Arduino、C# 和 JavaScript,且兼容Android、Windows、Mac OSX和Linux平臺。myCobot 320 M5的多功能性使其適用于多種開發和集成應用。
2D 相機
一個能夠安裝在mycobot320末端的2D相機,用USB數據線進行通信。能夠呈現機械臂末端所看到的視野。
開發過程
項目架構
我將該項目主要分為三個木塊功能:
Gesture Recognition: 主要用來處理手勢的識別,能夠返回信息當欠手勢是什么,比如說豎大拇指等等。
Robotic Arm Control:主要功能用于設置機械臂的運動控制,例如坐標控制,角度控制等等。
Program logic:用來處理程序運行的邏輯,設置確認手勢時間,重置識別時間等,后續將一一詳細介紹。
編譯環境
操作系統:windows 11
編程語言:Python3.9+
使用的庫:opencv,mediapipe,pymycobot,time
手勢的識別
做識別首先得獲得到相機的一個畫面,這里我們就用到了opencv庫來獲取相機的畫面
import cv2 # 獲取相機流,默認的攝像頭-0 外接的攝像頭按照順序往上- 1,2,3 cap = cv2.VideoCapture(1) # 持續獲取相機畫面 while cap.isOpened(): #獲取當前圖像畫面 ret, frame = cap.read() # 將BGR圖像轉換為RGB rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 在電腦中顯示畫面 cv2.imshow('gesture control',frame) # 按下 'q' 鍵退出,避免死循環 if cv2.waitKey(1) & 0xFF == ord('q'): break
到這里圖像畫面就獲取成功了,接下來我們用mediapipe手勢進行識別。
import mediapipe as mp # 初始化MediaPipe Hands模塊 mp_hands = mp.solutions.hands hands = mp_hands.Hands() mp_draw = mp.solutions.drawing_utils # 處理圖像并檢測手部 result = hands.process(rgb_frame) if result.multi_hand_landmarks: for hand_landmarks in result.multi_hand_landmarks: mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
這是識別手勢之后的輸出的結果,它能夠精準的識別出手上的每個關節,并且將每個關節的點都命名。MediaPipe Hands 提供了21個手部關鍵點(landmarks),這些關鍵點共同描繪了手的結構,包括手腕、各個手指的各個關節。以大拇指舉例子,一共有四個關節,從下往上分別是CMC,MCP,IP,TIP.
cmc: Carpometacarpal Joint mcp:Metacarpophalangeal Joint ip:Interphalangeal Joint tip:tip
有了這些還不夠,我們要讓他識別特定的手勢,要需要去設定一個方法,來確定這個手勢,比如說我想要一個手勢是豎大拇指,那么我們分析在豎大拇指的時候,拇指的指尖的位置是在整個手掌的最上方,這樣就容易多了。只要確定在畫面中大拇指的指尖是高于其他所有手指頭的都指尖,那么這個手勢就是豎大拇指。(也可以通過別的進行分析)
一般情況下,我們可以獲取到某個關節的X,Y,Z的三個屬性,表示改關節在圖像中的位置。
#獲取大拇指指尖的屬性 thump_tip = hand_landmarks.landmark[mp.hands.HandLandmark.THUMB_TIP] #獲取大拇指指尖的高度 thump_tip.y #判斷豎大拇指手勢 def is_thump_up(hand_landmarks): thumb_tip = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP] index_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP] # 判斷那個關節比較高。 if thumb_tip.y < index_tip.y: return True return False
如果想要別的手勢的話,也可以根據手型的特點來設定一個專門的辨別方法。到這里手勢的識別就完成了。
機械臂運動控制
我一開始的想法是,當相機識別到手勢的時候就會給機械臂發送一條控制命令,這里我們先簡單的設置一個讓機械臂點頭的動作。
pymycobot 這個功能庫,開放了很多功能在控制機械臂的時候非常的方便。
from pymycobot.mycobot import Mycobot import time #鏈接機械臂 mc = Mycobot(port,baud) #以關節角度控制機械臂運動 mc.send_angles([angles_list],speed) #以坐標控制機械臂進行運動 mc.send_coords([coords_list],speed,mode) #點頭動作 def ThumpUpAction(self): self.mc.send_angles([0.96, 86.22, -98.26, 10.54, 86.92, -2.37], 60) time.sleep(1.5) for count in range(3): self.mc.send_angles([0.79, 2.46, (-8.17), 4.3, 88.94, 0.26], 70) time.sleep(1) self.mc.send_angles([(-3.6), 30.32, (-45.79), (-46.84), 97.38, 0.35], 70) time.sleep(1) self.mc.send_angles([0.79, 2.46, (-8.17), 4.3, 88.94, 0.26], 70) time.sleep(1) self.mc.send_angles([0.96, 86.22, -98.26, 10.54, 86.92, -2.37], 60)
為了讓整體代碼看起來可讀性高,可修改性高,創建機械臂類方便進行調用和修改
class RobotArmController: def __init__(self,port): #初始化鏈接 self.mc = MyCobot(port, 115200) self.init_pose = [0.96, 86.22, -98.26, 10.54, 86.92, -2.37] self.coords = [-40, -92.5, 392.7, -92.19, -1.91, -94.14] self.speed = 60 self.mode = 0 def ThumpUpAction(self): ... def OtherAction(self): ...
程序邏輯的處理
在調試的過程中,出現了一些問題,在識別收拾的時候,它是一直識別,這就意味著如果在1s中內識別了10次的話,會給機械臂發送10個命令,這樣肯定不是我一開始所設想的。
所以在邏輯上就要有所處理,下面是我處理的方式。
# 設置一個2S的時間來確定這個手勢,當豎大拇指出現2s的時候才進行下發機械臂控制的命令,用控制變量的方式來進行。 #初始化變量 #檢測手勢是否存在的變量 gesture_detected = False #確定手勢出現后計時的變量 gesture_start_time = None # 設定手勢出現2s后的變量 gesture_confirmation_time = 2 后續的處理邏輯: 當特定手勢出現的時候,gesture_start_time就開始計時,這個時候在不停的做判斷如果時間到達了2S之后,確定手勢接下來執行相對應手勢的機械臂運動。 current_time = time.time() if current_gesture: if not gesture_detected: gesture_detected = True gesture_start_time = current_time elif current_time - gesture_start_time > gesture_confirmation_time and not action_triggered: # 根據手勢執行相應動作 if current_gesture == "thumb_up": robotic arm action()
但是這樣還不夠,因為手如果出現超過2s后也會持續發送機械臂的指令,這里我們需要在設置一個冷卻的時間,有充足的時間讓機械臂完成運動。
#冷卻時間的變量 #機械臂是否完成動作的變量 action_triggered = False #冷卻時間計時的變量 cooldown_start_time = None #固定2s冷卻時間 cooldown_period = 2
這樣就能夠滿足需求了。完整的邏輯代碼處理如下
# 處理手勢 current_time = time.time() if current_gesture: if not gesture_detected: gesture_detected = True gesture_start_time = current_time elif current_time - gesture_start_time > gesture_confirmation_time and not action_triggered: # 根據手勢執行相應動作 if current_gesture == "thumb_up": print('good good') mc.thum_up() elif current_gesture == "palm_open": print('forward') mc.increment_x_and_send() # 可以添加更多手勢和對應動作的判斷 action_triggered = True cooldown_start_time = current_time else: gesture_detected = False gesture_start_time = None if action_triggered and current_time - cooldown_start_time > cooldown_period: print('can continue') action_triggered = False cooldown_start_time = None
演示
https://youtu.be/9vOPKO_IG9M
總結
這個項目展示了使用手勢識別控制myCobot 320的方法,開創了人機互動的新形式。盡管目前僅實現了有限的幾個手勢與機械臂動作的對應,但它為未來更廣泛的機械臂應用奠定了基礎。結合手勢與機械臂的創新嘗試不僅提升了我的編程技能,還鍛煉了我的問題解決能力,為未來的相關項目提供了寶貴經驗。
審核編輯 黃宇
-
手勢識別
+關注
關注
8文章
225瀏覽量
47773 -
人工智能
+關注
關注
1791文章
46896瀏覽量
237660 -
開源
+關注
關注
3文章
3256瀏覽量
42419 -
python
+關注
關注
56文章
4783瀏覽量
84473 -
機械臂
+關注
關注
12文章
510瀏覽量
24499
發布評論請先 登錄
相關推薦
評論