<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          YOLOv7-Pose嘗鮮,基于YOLOv7的關(guān)鍵點(diǎn)模型測(cè)評(píng)

          共 8917字,需瀏覽 18分鐘

           ·

          2022-08-01 11:41

          【前言】

          目前人體姿態(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è)器。玩過目標(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,在論文中,通過調(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也可見到:

              if self.kpt_label:
                              #Direct kpt prediction
                              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()) 
                              #l2 distance based loss
                              #lkpt += (((pkpt-tkpt[i])*kpt_mask)**2).mean()  #Try to make this loss based on distance instead of ordinary difference
                              #oks based loss
                              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')
          !python pose.py 

          一、yolov7-w6 VS yolov7-w6-pose

          1. 首先看下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表示
          1. 再看看yolov7-w6-pose使用的檢測(cè)頭:

          上述重復(fù)的地方不累述,講幾個(gè)點(diǎn):

          • 代表person一個(gè)類別
          • nkpt表示人體的17個(gè)關(guān)鍵點(diǎn)

          二、修改export腳本

          如果直接使用export腳本進(jìn)行onnx的抽取一定報(bào)錯(cuò),在上一節(jié)我們已經(jīng)看到pose.pt模型使用的檢測(cè)頭為IKeypoint,那么腳本需要進(jìn)行相應(yīng)更改:在export.py的這個(gè)位置插入:

              # 原代碼:
              for k, m in model.named_modules():
                  m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatibility
                  if isinstance(m, models.common.Conv):  # assign export-friendly activations
                      if isinstance(m.act, nn.Hardswish):
                          m.act = Hardswish()
                      elif isinstance(m.act, nn.SiLU):
                          m.act = SiLU()
               model.model[-1].export = not opt.grid  # set Detect() layer grid export
                          
              # 修改代碼:
              for k, m in model.named_modules():
                  m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatibility
                  if isinstance(m, models.common.Conv):  # assign export-friendly activations
                      if isinstance(m.act, nn.Hardswish):
                          m.act = Hardswish()
                      elif isinstance(m.act, nn.SiLU):
                          m.act = SiLU()
                  elif isinstance(m, models.yolo.IKeypoint):
                      m.forward = m.forward_keypoint  # assign forward (optional)
                      # 此處切換檢測(cè)頭
              model.model[-1].export = not opt.grid  # set Detect() layer grid export

          forward_keypoint在原始的yolov7 repo源碼中有,作者已經(jīng)封裝好,但估計(jì)是還沒打算開放使用。

          使用以下命令進(jìn)行抽?。?/p>

          python export.py --weights 'weights/yolov7-w6-pose.pt' --img-size 960 --simplify True

          抽取后的onnx檢測(cè)頭:

          三、onnxruntime推理

          onnxruntime推理代碼:

          import onnxruntime
          import matplotlib.pyplot as plt
          import torch
          import cv2
          from torchvision import transforms
          import numpy as np
          from utils.datasets import letterbox
          from utils.general import non_max_suppression_kpt
          from utils.plots import output_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.250.65, nc=1, nkpt=17, kpt_label=True)
          output = output_to_keypoint(output)
          nimg = image[0].permute(120) * 255
          nimg = nimg.cpu().numpy().astype(np.uint8)
          nimg = cv2.cvtColor(nimg, cv2.COLOR_RGB2BGR)
          for idx in range(output.shape[0]):
              plot_skeleton_kpts(nimg, output[idx, 7:].T, 3)

          # matplotlib inline
          plt.figure(figsize=(88))
          plt.axis('off')
          plt.imshow(nimg)
          plt.show()
          plt.savefig("tmp")

          在這里插入圖片描述

          推理效果幾乎無(wú)損,但耗時(shí)會(huì)縮短一倍左右,另外有幾個(gè)點(diǎn):

          • 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)練更難以想象


          瀏覽 106
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产免费大香蕉 | 西西西444www无码视 | 爽好紧别夹喷水无码 | 久久肏| 亚洲色情视频在线 |