python openpose

如今說到體感遊戲,大家一定都不陌生,比如微軟的 Kinect、任天堂的 Switch,都曾是遊戲業的革命性產品。而另一款網紅產品—抖音,也在去年底上線過一個“尬舞機”的音樂體感遊戲(現在成了隱藏功能):

遊戲開始後,隨着音樂會給出不同的動作提示,用戶按照提示擺出正確動作即可得分。援引官方說法,“尬舞機”主要應用了今日頭條 AI Lab 自主開發的“人體關鍵點檢測技術”,依靠這項技術,抖音能夠檢測到圖像中所包含人體的各個關鍵點的位置,從而實現從用戶姿態到目標姿態的準確匹配。

以上這些體感遊戲,都牽涉到計算機視覺中的一個細分領域: 人體姿態估計(pose estimation) ,即識別圖像中的人體關鍵點(人體上有一定自由度的關節,如頭、頸、肩、肘、腕、腰、膝、踝等)並正確的聯繫起來,通過對人體關鍵點在三維空間相對位置的計算,來估計人體當前的姿態。

人體姿態估計有不少難點,比如:如何從圖片中區分出人和背景;如何定位人體的關鍵點;如何根據二維的關鍵點座標計算出三維中的姿態;如何處理四肢交叉或遮擋的情況;如何定位多人;如何提升計算速度等等。而相關技術在遊戲、安防、人機交互、行爲分析等方面都有應用前景。因此,這是計算機視覺甚至人工智能領域中極具挑戰的一個課題。(小聲說句,我的碩士畢業論文就是這個方向)

不過,因爲前人的貢獻,現在你只需通過少量的 Python 代碼,也可以實現從照片或視頻中進行人體姿態估計。這都要仰賴於 CMU 的開源項目: Openpose

OpenPose 是基於卷積神經網絡和監督學習並以 caffe 爲框架寫成的開源庫,可以實現人的面部表情、軀幹和四肢甚至手指的跟蹤,適用多人且具有較好的魯棒性。是世界上第一個基於深度學習的實時多人二維姿態估計,爲機器理解人類提供了一個高質量的信息維度。
其理論基礎來自《Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields》,是 CVPR 2017 的一篇論文,作者是來自 CMU 感知計算實驗室的曹哲、Tomas Simon、Shih-En Wei、Yaser Sheikh。
項目地址: https://github.com/ZheC/Realtime_Multi-Person_Pose_Estimation
(摘自網絡)

論文演示效果:

 

此方法可以達到對視頻流的實時多人檢測。要知道,Kinect 可是加了一個額外的紅外深度攝像頭才做到如此準確地識別(還不能是這麼多人)。

詳細的原理,我在這裏就不冒充大牛強行解釋了。但通俗地說幾點,爲什麼 Openpose 有如此突破性地效果:

  1. 以往的識別思路是自上而下:先找人,找到人了再進一步區分身體不同部分。Openpose 則是自下而上: 先找手腳關節等特徵部位,再組合人體
  2. Openpose 團隊將 人臉識別手部識別 的已有成果整合到了姿態識別中,取得了更好的效果;
  3. 有了 大數據 的支持,這是過去的研究所沒有的。看看這個 CMU 爲採集人體數據所搭建的設備,你就會有所體會:

之前的文章 Python+OpenCV 十幾行代碼模仿世界名畫 中,我們提到 OpenCV-Python 在 3.3 版本中加入了 深度神經網絡(DNN) 的支持。同樣在項目 Samples 中,提供 Openpose 的一個 Python 簡單實現版本。(只支持圖像中有單個人)

官方代碼:

https://github.com/opencv/opencv/blob/master/samples/dnn/openpose.py

使用方法,命令行進入代碼所在目錄執行:



python openpose.py --model pose.caffemodel --proto pose.prototxt --dataset MPI

--model 參數和 --proto 參數分別是預先訓練好的人體姿態模型和配置文件。因爲模型文件很大,並不包括在 OpenCV 代碼庫中,可以在 Openpose 項目(https://github.com/CMU-Perceptual-Computing-Lab/openpose )找到下載地址。

另外可以通過 --input 參數指定識別的圖片或視頻地址,默認則使用攝像頭實時採集。

執行後效果:

核心代碼:



net = cv.dnn.readNetFromCaffe(args.proto, args.model)
inp = cv.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight), (0, 0, 0), swapRB=False, crop=False)
net.setInput(inp)
out = net.forward()

和之前 fast-neural-style 的代碼類似,大部分的工作都是 Openpose 做好的,OpenCV 這裏只是使用訓練好的神經網絡進行計算。所以核心代碼其實沒有幾行,而且跟上次的例子幾乎一致。剩下一半的代碼都是在把獲取到的關鍵點座標繪製成人體的骨架結構。

這裏順帶提醒一下,我發現代碼中的一個斷言 assert(len(BODY_PARTS) == out.shape[1]) 無法滿足,會導致程序終止。如果出現這樣的問題,就把這句註釋掉,並不會對結果有影響。

拿到人體關鍵點數據後,我們就可以做進一步的判斷。比如我們加一個很簡單的判斷:



neck = points[BODY_PARTS['Neck']]
left_wrist = points[BODY_PARTS['LWrist']]
right_wrist = points[BODY_PARTS['RWrist']]
print(neck, left_wrist, right_wrist)if neck and left_wrist and right_wrist and left_wrist[1] < neck[1] and right_wrist[1] < neck[1]:
    cv.putText(frame, 'HANDS UP!', (10, 100), cv.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 2)

如果左手腕和右手腕的高度都超過脖子的高度,就認爲是一個擡手的動作,在屏幕上輸出“ HANDS UP! ”。注意在 OpenCV 座標系裏,圖像的座標原點是左上角。

效果:

如此,一個簡單的動作識別程序就有了。雖然很粗糙,但已經可以附加在很多應用上,比如:商場、科技館裏的互動遊戲、交互式的視覺藝術作品等等。感興趣的同學不妨親自試一試,期待看到你們藉此做出更有意思的項目。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章