由于最近虛擬現實和增強現實的增長和普及,人體姿態估計技術變得越來越流行。在我們之前的教程中,我們使用了 Media pipe Hand Tracking 模塊來使用手勢控制 Raspberry Pi 媒體播放器。在這個項目中,我們將使用MediaPipe Pose 估計包來構建一個俯臥撐。我們將使用姿勢估計包來獲取肩膀和肘部的坐標。肩部坐標將與肘部坐標進行比較。因此,如果肩膀與肘部處于同一水平或低于肘部,則將被視為俯臥撐。我們還將揚聲器連接到 Raspberry Pi 以告知俯臥撐的計數。
俯臥撐計數所需的組件
樹莓派 4
Pi 相機模塊
揚聲器
在這里,我們只需要安裝了 OpenCV 和 MediaPipe 的 Raspberry Pi 4 和 Pi 攝像頭模塊。 OpenCV 用于 數字圖像處理,而 MediaPipe 用于 Pose 估計。數字圖像處理最常見的應用是 物體檢測、 人臉識別和 人數統計。
什么是媒體管道?
MediaPipe是一個框架,用于構建跨平臺(即 Android、iOS、Web、邊緣設備)多模式(即視頻、音頻或任何時間序列數據)應用機器學習管道,包括快速 ML 推理、經典計算機視覺和媒體處理(例如視頻解碼)。MediaPipe 發布了各種預構建的 Python 和其他語言包,例如:
物體檢測
人臉檢測
手部追蹤
姿勢估計
多手追蹤
頭發分割
MediaPipePython 包可用于 Linux、macOS 和 Windows 的 PyPI。使用以下命令在 Raspberry Pi 4 上安裝 MediaPipe:
須藤 pip3 安裝 mediapipe-rpi4
如果您沒有 Pi 4,則可以使用以下命令將其安裝在 Raspberry Pi 3 上:
須藤 pip3 安裝 mediapipe-rpi3
安裝 OpenCV
在安裝 OpenCV 和其他依賴項之前,Raspberry Pi 需要完全更新。使用以下命令將 Raspberry Pi 更新到其最新版本:
sudo apt-get 更新
然后使用以下命令安裝在 Raspberry Pi 上安裝 OpenCV 所需的依賴項。
sudo apt-get install libhdf5-dev -y sudo apt-get install libhdf5-serial-dev –y sudo apt-get install libatlas-base-dev –y sudo apt-get install libjasper-dev -y sudo apt-get install libqtgui4 –y sudo apt-get install libqt4-test –y
之后,使用以下命令在您的 Raspberry Pi 上安裝 OpenCV。
pip3 安裝 opencv-contrib-python==4.1.0.25
為上推計數器編程 Raspberry Pi
文檔末尾給出了使用 OpenCV 上推計數器的完整代碼。在這里,我們將解釋代碼的重要部分以便更好地解釋。
通過導入 OpenCV 和 MediaPipe 包來啟動代碼。如前所述,MediaPipe 是 Pose 估計的核心包,而 OpenCV 用于圖像處理。
導入簡歷2 將媒體管道導入為 mp
在接下來的幾行中,我們創建了兩個新變量。第一個是mp_drawing,它將用于從 MediaPipe Python 包中獲取所有繪圖實用程序,第二個是mp_pose,用于導入姿勢估計模型。
mp_drawing = mp.solutions.drawing_utils mp_pose = mp.solutions.pose
之后,定義一個名為findPosition() 的函數。顧名思義,它用于查找所有身體標志的 X、Y 坐標,如肩膀、眼睛等。所有標志的坐標將存儲在名為lmList[]的變量中。
def findPosition(圖像,繪制=真): lmList = [] 如果結果.pose_landmarks: mp_drawing.draw_landmarks( 圖像,results.pose_landmarks,mp_pose.POSE_CONNECTIONS) 對于 id, lm in enumerate(results.pose_landmarks.landmark): h, w, c = image.shape cx, cy = int(lm.x * w), int(lm.y * h) lmList.append([id, cx, cy]) 返回 lmList
然后從 Raspberry Pi 攝像頭開始視頻流。您甚至可以使用預先錄制的視頻,而不是使用實時流。為此,將“0”替換為視頻路徑。
上限 = cv2.VideoCapture(0) #cap = cv2.VideoCapture(“我的視頻.mp4”)
然后在下一行,為 mediapipe feed 設置一個新實例,以訪問我們之前導入的姿勢估計模型。我們還傳遞了兩個關鍵字參數,即最小檢測置信度和最小跟蹤置信度。接下來,我們將讀取視頻幀并將它們存儲在 image 變量中。
以 mp_pose.Pose(min_detection_confidence=0.7, min_tracking_confidence=0.7) 作為姿勢:
而 cap.isOpened(): 成功,圖像 = cap.read() 圖像 = cv2.resize(圖像, (1280, 720))
我們從視頻源獲得的圖像最初是 BGR 格式。S,在這一行中,我們將首先將圖像水平翻轉以供稍后的自拍視圖顯示,然后將BGR圖像轉換為RGB。
圖像 = cv2.cvtColor(cv2.flip(圖像, 1), cv2.COLOR_BGR2RGB)
之后,我們將通過姿勢估計模型傳遞圖像以進行檢測并將結果存儲在一個名為“結果”的變量中。然后我們將 BGR 圖像轉換為 RGB。
結果=姿勢.過程(圖像) 圖像 = cv2.cvtColor(圖像,cv2.COLOR_BGR2RGB)
現在我們得到了檢測結果,我們將調用findPosition()函數在圖像上繪制這些檢測,并使用我們之前導入的繪圖實用程序連接所有檢測。
mp_drawing.draw_landmarks(圖像,results.pose_landmarks,mp_pose.POSE_CONNECTIONS)
之后,我們會將所有檢測的 id 和坐標存儲在一個名為 lmList 的變量中。
lmList = findPosition(圖像,繪制=真)
然后在接下來的幾行中,我們將首先獲取兩個肩膀的坐標,然后在上面畫圓。如下圖所示,左右肩的 id 分別為 12 和 11。
如果 len(lmList) != 0:
cv2.circle(圖像, (lmList[12][1], lmList[12][2]), 20, (0, 0, 255), cv2.FILLED) cv2.circle(圖像, (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED) cv2.circle(圖像, (lmList[12][1], lmList[12][2]), 20, (0, 0, 255), cv2.FILLED) cv2.circle(圖像, (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)
現在,當我們找到肩膀的坐標時,我們將把這些坐標與兩個肘部的坐標進行比較。所以,如果肩膀與肘部在同一水平或在肘部以下,我們將階段設置為“向下”,當肩膀在肘部以上時,階段將變為向上,這將被視為俯臥撐.
如果(lmList[12][2] 和 lmList[11][2] >= lmList[14][2] 和 lmList[13][2]): cv2.circle(圖像, (lmList[12][1], lmList[12][2]), 20, (0, 255, 0), cv2.FILLED) cv2.circle(圖像, (lmList[11][1], lmList[11][2]), 20, (0, 255, 0), cv2.FILLED) 階段=“下降” if (lmList[12][2] and lmList[11][2] <= lmList[14][2] and lmList[13][2]) and stage == "down": 階段=“向上” 計數器 += 1 打印(計數器)
現在,隨著俯臥撐的計數,我們將使用cv2.putText() 在視頻流上打印俯臥撐計數。
text = "{}:{}".format("俯臥撐", counter) cv2.putText(圖像, 文本, (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) cv2.imshow('MediaPipe 姿勢', image)
最后,我們將視頻流保存在我們的項目文件夾中。
如果創建是無: fourcc = cv2.VideoWriter_fourcc(*'XVID') create = cv2.VideoWriter(opname,fourcc, 30, (image.shape[1], image.shape[0]), True) create.write(圖像)
測試上推計數器腳本
現在 Push Up 計數器腳本已準備就緒,讓我們繼續測試它。有兩種測試方法。您可以使用預先錄制的視頻,也可以使用 Pi 相機進行實時視頻流。在這里,我們將使用 Pi 攝像頭模塊,因此,將 Raspberry Pi 攝像頭模塊與 Pi 連接,如下所示:
現在,檢查 Pi 相機是否正常工作。查看相機后,啟動 python 腳本,您會發現彈出一個窗口,其中包含您的視頻源。最初做俯臥撐時,肩膀上的點將是紅色:
當肩膀低于肘部時,點將從紅色變為綠色,俯臥撐計數將增加一。
這就是您可以使用 MediaPipe 計算俯臥撐的方法。您還可以使用此庫來計算仰臥起坐或任何其他鍛煉。下面給出了完整的工作視頻和代碼。
代碼
import cv2
import mediapipe as mp
import os
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
counter = 0
stage = None
create = None
opname = “output.avi”
def findPosition(image, draw=True):
lmList = []
if results.pose_landmarks:
mp_drawing.draw_landmarks(
image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
for id, lm in enumerate(results.pose_landmarks.landmark):
h, w, c = image.shape
cx, cy = int( lm.x * w), int(lm.y * h)
lmList.append([id, cx, cy])
#cv2.circle(image, (cx, cy), 5, (255, 0, 0), cv2.填充)
返回 lmList
cap = cv2.VideoCapture(0)
與 mp_pose.Pose(
min_detection_confidence=0.7,
min_tracking_confidence=0.7) 作為姿勢:
而 cap.isOpened():
成功,image = cap.read()
image = cv2.resize(image, (640,480))
if not success:
print(“Ignoring empty camera frame.”)
# 如果加載視頻,使用 ‘break’ 而不是 ‘continue’。
continue
# 水平翻轉圖像以供稍后的自拍視圖顯示,并將
# BGR 圖像轉換為 RGB。
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
# 為了提高性能,可選擇將圖像標記為不可寫入
# 通過引用傳遞。
results = pose.process(image)
# 在圖像上繪制姿態標注。
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
lmList = findPosition(image, draw=True)
if len(lmList) != 0:
cv2.circle(image, (lmList[12][1], lmList[12] [2]), 20, (0, 0, 255), cv2.FILLED)
cv2.circle(image, (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)
cv2.circle(image, (lmList[12][1], lmList[12][2]), 20, (0, 0, 255), cv2.FILLED)
cv2.circle(image , (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)
if (lmList[12][2] 和 lmList[11][2] 》= lmList[14][2] 和 lmList[13][2]):
cv2.circle(image, (lmList[12][1], lmList[12][2]), 20, (0, 255, 0), cv2.FILLED)
cv2.circle(image, (lmList[11][ 1], lmList[11][2]), 20, (0, 255, 0), cv2.FILLED)
stage = “down”
if (lmList[12][2] and lmList[11][2] 《= lmList[14][2] 和 lmList[13][2]) 和 stage == “down”:
stage = “up”
counter += 1
counter2 = str(int(counter))
print(counter)
os.system( “echo ‘” + counter2 + “’ | festival --tts”)
text = “{}:{}”.format(“Push Ups”, counter)
cv2.putText(image, text, (10, 40), cv2 .FONT_HERSHEY_SIMPLEX,
1, (255, 0, 0), 2)
cv2.imshow(‘MediaPipe Pose’, image)
如果 create 為 None:
fourcc = cv2.VideoWriter_fourcc(*‘XVID’)
create = cv2.VideoWriter(opname,fourcc, 30, (image.shape[1], image.shape[0]), True)
create.write(image)
key = cv2 .waitKey(1) & 0xFF
# 如果 `q` 鍵被按下,則退出循環
if key == ord(“q”):
break
# 做一些清理
cv2.destroyAllWindows()
-
揚聲器
+關注
關注
29文章
1338瀏覽量
63929 -
計數器
+關注
關注
32文章
2287瀏覽量
96080
發布評論請先 登錄
倫敦街頭的“俯臥撐”巴士
計數器,計數器的工作原理是什么?
同步計數器和異步計數器是什么 同步計數器和異步計數器的主要區別?

評論