二維已經(jīng) OUT 了?3DPose 實(shí)現(xiàn)三維人體姿態(tài)識(shí)別真香 | 代碼干貨
引言
人體姿態(tài)估計(jì)是計(jì)算機(jī)視覺領(lǐng)域很多研究工作的基礎(chǔ),也是研究的熱點(diǎn)問題,在行為識(shí)別、人機(jī)交互、姿態(tài)跟蹤等領(lǐng)域有著廣泛的應(yīng)用前景。
按照人體姿態(tài)維度的差異,可以將人體姿態(tài)估計(jì)任務(wù)分為二維人體姿態(tài)估計(jì)和三維人體姿態(tài)估計(jì)。2D人體姿態(tài)估計(jì)的目標(biāo)是定位并識(shí)別出人體關(guān)鍵點(diǎn),將這些關(guān)鍵點(diǎn)按照關(guān)節(jié)順序相連形成在圖像二維平面的投影,從而得到人體骨架。3D人體姿態(tài)估計(jì)的主要任務(wù)是預(yù)測(cè)出人體關(guān)節(jié)點(diǎn)的三維坐標(biāo)位置和角度等信息。
在實(shí)際應(yīng)用中,由于3D姿態(tài)估計(jì)在2D姿態(tài)估計(jì)的基礎(chǔ)上加入了深度信息,其對(duì)于人體姿態(tài)的表述比2D更為精準(zhǔn),因此其應(yīng)用范圍和研究?jī)r(jià)值都要高于2D人體姿態(tài)估計(jì),但是3D姿態(tài)估計(jì)的難度也更高,存在著遮擋,單視角2D到3D的映射中固有的深度模糊性、不適定性,缺少大型的室外數(shù)據(jù)集等挑戰(zhàn)。
本項(xiàng)目通過使用3DPose模型實(shí)現(xiàn)對(duì)人體的三維實(shí)時(shí)姿態(tài)識(shí)別。其最終實(shí)現(xiàn)的效果如下圖可見:
1、基本介紹
在深度學(xué)習(xí)方法得到廣泛應(yīng)用之前,3D人體姿態(tài)標(biāo)注數(shù)據(jù)集和具有高運(yùn)算能力的GPU還沒有普及,研究人員主要通過一些應(yīng)用在傳統(tǒng)計(jì)算機(jī)視覺或機(jī)器學(xué)習(xí)領(lǐng)域的方法來進(jìn)行3D人體姿態(tài)的估計(jì)。傳統(tǒng)三維人體姿態(tài)估計(jì)和基于深度學(xué)習(xí)的姿態(tài)估計(jì)之間最明顯的特征在于是否使用了多層神經(jīng)網(wǎng)絡(luò)的學(xué)習(xí)方法,因?yàn)榻7绞讲煌?,在估?jì)精確性、計(jì)算復(fù)雜度等方面也有著較大的差別。其中建模是三維人體姿態(tài)估計(jì)一個(gè)很重要的方面,目的是表示從輸入數(shù)據(jù)中提取的關(guān)鍵點(diǎn)和特征。在解決實(shí)際問題時(shí)由于實(shí)驗(yàn)個(gè)體所處環(huán)境的復(fù)雜性,很大程度上增加了模型的建立難度,因此選取適當(dāng)且有效的圖像特征來簡(jiǎn)化模型建立過程十分重要。
1.1 環(huán)境要求:
本次環(huán)境使用的是python3.6.5+windows平臺(tái)。
主要用的庫有:ONNX Runtime庫、opencv-python模塊、Numpy模塊。
ONNX Runtime庫
ONNX Runtime庫是一個(gè)用于ONNX(Open Neural Network Exchange)模型推理的引擎。微軟聯(lián)合Facebook等在2017年搞了個(gè)深度學(xué)習(xí)以及機(jī)器學(xué)習(xí)模型的格式標(biāo)準(zhǔn)--ONNX,順路提供了一個(gè)專門用于ONNX模型推理的引擎。
opencv-python模塊
opencv-python是一個(gè)Python綁定庫,旨在解決計(jì)算機(jī)視覺問題。其使用Numpy,這是一個(gè)高度優(yōu)化的數(shù)據(jù)庫操作庫,具有MATLAB風(fēng)格的語法。所有Opencv數(shù)組結(jié)構(gòu)都轉(zhuǎn)換為Numpy數(shù)組。這也使得與使用Numpy的其他庫(如Scipy和Matplotlib)集成更容易。
Numpy模塊
Numpy是應(yīng)用Python進(jìn)行科學(xué)計(jì)算時(shí)的基礎(chǔ)模塊。它是一個(gè)提供多維數(shù)組對(duì)象的Python庫,除此之外,還包含了多種衍生的對(duì)象(比如掩碼式數(shù)組(masked arrays)或矩陣)以及一系列的為快速計(jì)算數(shù)組而生的例程,包括數(shù)學(xué)運(yùn)算,邏輯運(yùn)算,形狀操作,排序,選擇,I/O,離散傅里葉變換,基本線性代數(shù),基本統(tǒng)計(jì)運(yùn)算,隨機(jī)模擬等。
1.2 方法總結(jié):
傳統(tǒng)方法很多是采用基于人體模型的方法來描述和推斷人體姿態(tài),通過算法提取圖像姿態(tài)特征,因此對(duì)特征表示和關(guān)鍵點(diǎn)的空間位置關(guān)系這兩個(gè)維度有比較高的要求,除去邊界、顏色這類低層次特征,典型的有尺度不變特征變換、梯度直方圖等表達(dá)能力更強(qiáng)、可有效壓縮特征空間維度的高層次特征,它們雖然在時(shí)間效率方面具有優(yōu)勢(shì),但依然存在著較大的不足。
而深度學(xué)習(xí)模型操作過程相對(duì)簡(jiǎn)單且對(duì)特征的表示能力強(qiáng)大,對(duì)輸入信息自動(dòng)進(jìn)行特征提取而無需人為手動(dòng)提取特征。
基于深度學(xué)習(xí)的人體姿態(tài)估計(jì)可以通過建立網(wǎng)絡(luò)模型在圖像數(shù)據(jù)上進(jìn)行訓(xùn)練和學(xué)習(xí),直接得到最有效的表征方法,其核心是深度神經(jīng)網(wǎng)絡(luò),主要是利用卷積神經(jīng)網(wǎng)絡(luò)從圖像中提取出比人工特征語義信息更豐富、準(zhǔn)確性更高和更具魯棒性的卷積特征,并且網(wǎng)絡(luò)模型的表達(dá)能力會(huì)因網(wǎng)絡(luò)堆疊數(shù)量的增加而呈指數(shù)增長(zhǎng),因此相較于傳統(tǒng)方法可以進(jìn)一步提升復(fù)雜環(huán)境下的人體姿態(tài)的精度和魯棒性。深度學(xué)習(xí)在人體姿態(tài)估計(jì)任務(wù)中的應(yīng)用已經(jīng)取得了顯著的進(jìn)展,然而像遮擋、訓(xùn)練數(shù)據(jù)不足和深度模糊等挑戰(zhàn)仍然是難以克服的。
2.三維人體可視化
傳統(tǒng)方法與深度學(xué)習(xí)方法
其中3DPose算法提供的模型架構(gòu)如下圖可見:
2.1 圖片預(yù)處理:
其中圖片處理代碼如下,分別為讀取圖片,顯示圖片,BGR轉(zhuǎn)RGB以及尺寸變換等:
img=cv2.imread("1.jpg") cv2.imshow("test", img) cv2.waitKey(1) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.resize(img, (448, 448)) img = img.astype(np.float32) / 255.0 img = img.transpose(2, 1, 0) img = img[np.newaxis, ...]
2.2 模型訓(xùn)練:
首先通過使用onnxruntime,
然后讀取Resnet34_inputs_448x448_20200609.0nnx模型文件,實(shí)時(shí)需要識(shí)別的圖片數(shù)據(jù),獲取每一張圖片的offset圖和heatmap圖。通過找到第j個(gè)關(guān)節(jié)的28個(gè)特征圖,并找到最大值的索引來獲取個(gè)點(diǎn)坐標(biāo)。并把坐標(biāo)按照一定比例縮放。使得圖像變形較為符合人體規(guī)律。
for j in range(0, 24): # 找到第j個(gè)關(guān)節(jié)的28個(gè)特征圖,并找到最大值的索引 joint_heat = heatMap3D[j * 28:(j + 1) * 28, ...] if np.max(joint_heat)>0.1: print(np.max(joint_heat)) [x, y, z] = np.where(joint_heat == np.max(joint_heat)) x = int(x[-1]) y = int(y[-1]) z = int(z[-1]) # 通過heatmap的索引找到對(duì)應(yīng)的offset圖,并計(jì)算3D坐標(biāo)的xyz值 pos_x = offset3D[j * 28 + x, y, z] + x pos_y = offset3D[24 * 28 + j * 28 + x, y, z] + y pos_z = offset3D[24 * 28 * 2 + j * 28 + x, y, z] + z kps[j, 0] = pos_x kps[j, 1] = pos_y kps[j, 2] = pos_z else: try: kps[j, 0] = kps[j-1, 0] kps[j, 0] = kps[j-1, 0] kps[j, 2] = kps[j-1, 2] except: pass parent = np.array([15, 1, 2, 3, 3, 15, 6, 7, 8, 8, 12, 15, 14, 15, 24, 24, 16, 17, 18, 24, 20, 21, 22, 0]) - 1; for i in range(len(kps)): if (parent[i] != -1): ax.plot3D(kps[[i, parent[i]], 0], -kps[[i, parent[i]], 1], -kps[[i, parent[i]], 2], 'gray')
完整代碼:
鏈接:https://pan.baidu.com/s/1pb0uG9Uy36sOBuWNTsZUpA
提取碼:0ahr
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。