牟曉東

除了手勢識別追蹤和人臉的“面部網格”識別之外,MediaPipe 還能實現“姿勢偵測”(Pose,又稱“姿態識別”),它將人體模型標注出0-32 共33 個關鍵點,比如6對應的是右眼外眼角(right_eye_outer)、13 對應的是左肘尖(left_elbow)、30 對應的是右腳跟(right_heel)等等。頭部的關鍵點是從0到10,身體的左側關鍵點是奇數從11、13 直至31,右側是偶數從12、14 直至32,二者所對應的身體部位是對稱標注的(如圖)。
首先, 導入OpenCV 和MediaPipe 庫模塊:“importcv2”“import mediapipe asmp”;然后進行人體姿勢偵測模型的導入——建立變量mp_pose 并賦值為“mp.solutions.pose”;再建立變量mp_drawing,賦值為“mp.solutions.drawing_utils”,作用是導入繪圖模塊;建立姿勢偵測變量pose,賦值為“mp_pose.Pose(static_image_mode=True,model_complexity=2, smooth_l a n d m a r k s = T r u e , e n a b l e _s e g m e n t a t i o n = T r u e , m i n _detection_confidence=0.5,min_tracking_confidence=0.5)”,其中的參數“static_image_mode=True” 作用是設置為靜態圖像文件的檢測, 參數“model_complexity=2” 作用是設置為最佳的姿勢偵測(值為0 時速度最快但 性能較弱,值為1 時速度與性能比較均衡), 參數“smooth_landmarks=True” 作用是將平滑關鍵點的檢測設置為有效,參數“enable_segmentation=True”作用是將人體摳圖設置為有效, 參數“min_detection_confidence=0.5” 和“min_tracking_confidence=0.5)”作用是分別設置偵測的置信度與追蹤閾值。
接下來從圖片文件中讀入圖像, 建立變量img 并賦值為“cv2.imread('test.jpg')”, 其中的test.jpg 即為待測試的圖片文件; 建立變量img_RGB, 賦值為“cv2.cvtColor(img,cv2.COLOR_BGR2RGB)”, 作用是將讀入的圖像進行色彩模式的轉換, 從BGR 轉為RGB; 建立變量results, 賦值為“pose.process(img_RGB)”, 作用是將轉換模式后的圖像輸入至訓練模型并獲取對應的姿勢偵測結果;再進行可視化檢測結果的描繪,通過語句“mp_drawing.draw_landmarks(img,results.pose_landmarks,mp_pose.POSE_CONNECTIONS)” 來實現,其默認效果是用紅色小圓點標注33 個關鍵點,并且用白色細線進行連接; 最后, 通過語句“cv2.imwrite('result.jpg',img)” 將添加標注效果的圖像存儲為result.jpg文件。
將程序保存為“[01]Test_Single_Picture.py”,按F5運行測試,很快就生成了result.jpg 文件,與之前的test.jpg同時打開進行對比查看,人物身體上的33 個關鍵點被正確標注,同時也有若干條白色細線連接對應的關鍵點。
將“[01]Test_Single_Picture.py”復制粘貼為“[02]Three_Groups.py”,進行代碼的修改,在最后一行“cv2.imwrite('result.jpg',img)”代碼之前插入以下代碼:
建立變量h 和w, 分別賦值為“img.shape[0]” 和“img.shape[1]”,表示圖像的高度和寬度;建立變量radius 并賦值為8,用來控制關鍵點描繪時圓點的半徑大小;同時建立head_points 和left_points 兩個變量,均賦值為空列表“[]”,分別通過“for i in range(11):”和“for i in range(11,33):”兩個循環,將頭部和左側所對應的關鍵點序號追加(append)至各自列表中(剩余的即為右側關鍵點);在“for i in range(33):”循環中,變量cx 和cy 的值分別為“int(results.pose_landmarks.landmark[i].x * w)” 和“int(results.pose_landmarks.landmark[i].y * h)”,即該關鍵點的橫坐標值和縱坐標值。以鼻尖為例,由于該關鍵點所對應的序號是0,因此通過條件“if i==0:”判定為真時將其輸出:“print(" 鼻尖位置的二維坐標值為:(",cx,",",cy,")")”;接下來,如果滿足“if iin head_points:”,說明該關鍵點位于頭部,則通過語句“img = cv2.circle(img,(cx,cy),radius-5,(0,0,255),-1)”繪制為紅色圓點;如果滿足“elif i in left_points:”,說明關鍵點位于人體左側,則通過語句“img = cv2.circle(img,(cx,cy),radius,(255,0,0),-1)”繪制為藍色圓點;剩余的右側各個關鍵點,通過語句“img = cv2.circle(img,(cx,cy),radius,(0,255,0),-1)”繪制為綠色圓點。
運行測試,程序生成的圖片文件result.jpg 與之前相比,人體的頭部11 個關鍵點仍被標注為紅色圓點,但左側和右側各11 個關鍵點則分別被標注為藍色和綠色圓點;而且在命令行處輸出有提示信息:“鼻尖位置的二維坐標值為:(665, 249)”。
仍然是在“[01]Test_Single_Picture.py”基礎之上進行“[03]Test_Camera.py”代碼的修改,目的是完成攝像頭監控畫面中的人體姿勢偵測。注意在為變量pose賦值時,其中的“static_image_mode”參數必須設為“False”,表示“非靜態圖像模式”(即視頻的動態幀畫面);從變量camera 的賦值到“while True:”循環體中的代碼,像圖像顏色模式的轉換、默認姿勢偵測繪制效果的實現等等,均與之前相同。
運行測試,分別嘗試在攝像頭前面進行遠景和各種近景的拍攝測試,全身的33 個關鍵點能夠快速實時檢測到,并且以紅色圓點加白色細線連接標注;側身和正身的近景上半身若干個關鍵點同樣也能夠被檢測和標注,都是實時的測試效果。
關注“壹零社”公眾號下載源代碼。