【前言】
目前人體姿態(tài)估計(jì)總體分為Top-down和Bottom-up兩種,與目標(biāo)檢測(cè)不同,無(wú)論是基于熱力圖或是基于檢測(cè)器處理的關(guān)鍵點(diǎn)檢測(cè)算法,都較為依賴計(jì)算資源,推理耗時(shí)略長(zhǎng),今年出現(xiàn)了以YOLO為基線的關(guān)鍵點(diǎn)檢測(cè)器。玩過(guò)目標(biāo)檢測(cè)的童鞋都知道YOLO以及各種變種目前算是工業(yè)落地較多的一類檢測(cè)器,其簡(jiǎn)單的設(shè)計(jì)思想,長(zhǎng)期活躍的社區(qū)生態(tài),使其始終占據(jù)著較高的話題度。
【演變】
在ECCV 2022和CVPRW 2022會(huì)議上,YoLo-Pose和KaPao(下稱為yolo-like-pose)都基于流行的YOLO目標(biāo)檢測(cè)框架提出一種新穎的無(wú)熱力圖的方法,類似于很久以前谷歌使用回歸計(jì)算關(guān)鍵點(diǎn)的思想,yolo-like-pose一不使用檢測(cè)器進(jìn)行二階處理,二部使用熱力圖拼接,雖然是一種暴力回歸關(guān)鍵點(diǎn)的檢測(cè)算法,但在處理速度上具有一定優(yōu)勢(shì)。

kapao
去年11月,滑鐵盧大學(xué)率先提出了 KaPao:Rethinking Keypoint Representations: Modeling Keypoints and Poses as Objects for Multi-Person Human Pose Estimation,基于YOLOv5進(jìn)行關(guān)鍵點(diǎn)檢測(cè),該文章目前已被ECCV 2022接收,該算法所取得的性能如下:

paper:https://arxiv.org/abs/2111.08557 code:https://github.com/wmcnally/kapao
yolov5-pose
今年4月,yolo-pose也掛在了arvix,在論文中,通過(guò)調(diào)研發(fā)現(xiàn) HeatMap 的方式普遍使用L1 Loss。然而,L1損失并不一定適合獲得最佳的OKS。且由于HeatMap是概率圖,因此在基于純HeatMap的方法中不可能使用OKS作為loss,只有當(dāng)回歸到關(guān)鍵點(diǎn)位置時(shí),OKS才能被用作損失函數(shù)。因此,yolo-pose使用oks loss作為關(guān)鍵點(diǎn)的損失

相關(guān)代碼在https://github.com/TexasInstruments/edgeai-yolov5/blob/yolo-pose/utils/loss.py也可見(jiàn)到:
ifself.kpt_label: #Directkptprediction pkpt_x=ps[:,6::3]*2.-0.5 pkpt_y=ps[:,7::3]*2.-0.5 pkpt_score=ps[:,8::3] #mask kpt_mask=(tkpt[i][:,0::2]!=0) lkptv+=self.BCEcls(pkpt_score,kpt_mask.float()) #l2distancebasedloss #lkpt+=(((pkpt-tkpt[i])*kpt_mask)**2).mean()#Trytomakethislossbasedondistanceinsteadofordinarydifference #oksbasedloss d=(pkpt_x-tkpt[i][:,0::2])**2+(pkpt_y-tkpt[i][:,1::2])**2 s=torch.prod(tbox[i][:,-2:],dim=1,keepdim=True) kpt_loss_factor=(torch.sum(kpt_mask!=0)+torch.sum(kpt_mask==0))/torch.sum(kpt_mask!=0) lkpt+=kpt_loss_factor*((1-torch.exp(-d/(s*(4*sigmas**2)+1e-9)))*kpt_mask).mean()
相關(guān)性能如下:

yolov7-pose
上個(gè)星期,YOLOv7的作者也放出了關(guān)于人體關(guān)鍵點(diǎn)檢測(cè)的模型,該模型基于YOLOv7-w6,

目前作者提供了.pt文件和推理測(cè)試的腳本,有興趣的童靴可以去看看,本文的重點(diǎn)更偏向于對(duì)yolov7-pose.pt進(jìn)行onnx文件的抽取和推理。
【yolov7-pose + onnxruntime】
首先下載好官方的預(yù)訓(xùn)練模型,使用提供的腳本進(jìn)行推理:
%weigths=torch.load('weights/yolov7-w6-pose.pt') %image=cv2.imread('sample/pose.jpeg') !pythonpose.py

一、yolov7-w6 VS yolov7-w6-pose
-
首先看下yolov7-w6使用的檢測(cè)頭

- 表示一共有四組不同尺度的檢測(cè)頭,分別為15×15,30×30,60×60,120×120,對(duì)應(yīng)輸出的節(jié)點(diǎn)為114,115,116,117
- nc對(duì)應(yīng)coco的80個(gè)類別
- no表示
- 再看看yolov7-w6-pose使用的檢測(cè)頭:

- 代表person一個(gè)類別
- nkpt表示人體的17個(gè)關(guān)鍵點(diǎn)
#原代碼: fork,minmodel.named_modules(): m._non_persistent_buffers_set=set()#pytorch1.6.0compatibility ifisinstance(m,models.common.Conv):#assignexport-friendlyactivations ifisinstance(m.act,nn.Hardswish): m.act=Hardswish() elifisinstance(m.act,nn.SiLU): m.act=SiLU() model.model[-1].export=notopt.grid#setDetect()layergridexport #修改代碼: fork,minmodel.named_modules(): m._non_persistent_buffers_set=set()#pytorch1.6.0compatibility ifisinstance(m,models.common.Conv):#assignexport-friendlyactivations ifisinstance(m.act,nn.Hardswish): m.act=Hardswish() elifisinstance(m.act,nn.SiLU): m.act=SiLU() elifisinstance(m,models.yolo.IKeypoint): m.forward=m.forward_keypoint#assignforward(optional) #此處切換檢測(cè)頭 model.model[-1].export=notopt.grid#setDetect()layergridexport forward_keypoint在原始的yolov7 repo源碼中有,作者已經(jīng)封裝好,但估計(jì)是還沒(méi)打算開放使用。使用以下命令進(jìn)行抽取:
pythonexport.py--weights'weights/yolov7-w6-pose.pt'--img-size960--simplifyTrue 抽取后的onnx檢測(cè)頭:

importonnxruntime importmatplotlib.pyplotasplt importtorch importcv2 fromtorchvisionimporttransforms importnumpyasnp fromutils.datasetsimportletterbox fromutils.generalimportnon_max_suppression_kpt fromutils.plotsimportoutput_to_keypoint,plot_skeleton_kpts device=torch.device("cpu") image=cv2.imread('sample/pose.jpeg') image=letterbox(image,960,stride=64,auto=True)[0] image_=image.copy() image=transforms.ToTensor()(image) image=torch.tensor(np.array([image.numpy()])) print(image.shape) sess=onnxruntime.InferenceSession('weights/yolov7-w6-pose.onnx') out=sess.run(['output'],{'images':image.numpy()})[0] out=torch.from_numpy(out) output=non_max_suppression_kpt(out,0.25,0.65,nc=1,nkpt=17,kpt_label=True) output=output_to_keypoint(output) nimg=image[0].permute(1,2,0)*255 nimg=nimg.cpu().numpy().astype(np.uint8) nimg=cv2.cvtColor(nimg,cv2.COLOR_RGB2BGR) foridxinrange(output.shape[0]): plot_skeleton_kpts(nimg,output[idx,7:].T,3) #matplotlibinline plt.figure(figsize=(8,8)) plt.axis('off') plt.imshow(nimg) plt.show() plt.savefig("tmp")

- image = letterbox(image, 960, stride=64, auto=True)[0] 中stride指的是最大步長(zhǎng),yolov7-w6和yolov5s下采樣多了一步,導(dǎo)致在8,16,32的基礎(chǔ)上多了64的下采樣步長(zhǎng)
- output = non_max_suppression_kpt(out, 0.25, 0.65, nc=1, nkpt=17, kpt_label=True) ,nc 和 kpt_label 等信息在netron打印模型文件時(shí)可以看到
- 所得到的onnx相比原半精度模型大了將近三倍,后續(xù)排查原因
- yolov7-w6-pose極度吃顯存,推理一張960×960的圖像,需要2-4G的顯存,訓(xùn)練更難以想象
審核編輯 :李倩
-
檢測(cè)器
+關(guān)注
關(guān)注
1文章
887瀏覽量
48420 -
算法
+關(guān)注
關(guān)注
23文章
4698瀏覽量
94740 -
模型
+關(guān)注
關(guān)注
1文章
3486瀏覽量
49992
原文標(biāo)題:YOLOv7-Pose嘗鮮 | 基于YOLOv7的關(guān)鍵點(diǎn)模型測(cè)評(píng)
文章出處:【微信號(hào):3D視覺(jué)工坊,微信公眾號(hào):3D視覺(jué)工坊】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
在英特爾AI開發(fā)板上用OpenVINO NNCF優(yōu)化YOLOv7

yolov7 onnx模型在NPU上太慢了怎么解決?
無(wú)法使用MYRIAD在OpenVINO trade中運(yùn)行YOLOv7自定義模型怎么解決?
關(guān)于YOLOU中模型的測(cè)試
深度解析YOLOv7的網(wǎng)絡(luò)結(jié)構(gòu)
在AI愛(ài)克斯開發(fā)板上用OpenVINO?加速YOLOv8目標(biāo)檢測(cè)模型

AI愛(ài)克斯開發(fā)板上使用OpenVINO加速YOLOv8目標(biāo)檢測(cè)模型

YOLOv7訓(xùn)練自己的數(shù)據(jù)集包括哪些

在AI愛(ài)克斯開發(fā)板上用OpenVINO?加速YOLOv8-seg實(shí)例分割模型

一文徹底搞懂YOLOv8【網(wǎng)絡(luò)結(jié)構(gòu)+代碼+實(shí)操】

在AI愛(ài)克斯開發(fā)板上用OpenVINO?加速YOLOv8-seg實(shí)例分割模型

yolov5和YOLOX正負(fù)樣本分配策略

使用OpenVINO優(yōu)化并部署訓(xùn)練好的YOLOv7模型

詳細(xì)解讀YOLOV7網(wǎng)絡(luò)架構(gòu)設(shè)計(jì)

評(píng)論