久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

實(shí)用教程詳解:用OpenCV的DNN模塊部署YOLOv5目標(biāo)檢測(cè)

 極市平臺(tái) 2021-01-26

作者丨nihate
審稿|鄧富城
編輯丨極市平臺(tái)

極市導(dǎo)讀

 

本文中介紹的整套程序只依賴OpenCV庫(kù)就能正常運(yùn)行,,徹底擺脫了對(duì)深度學(xué)習(xí)框架的依賴。文章講述了作者在自己編寫用OpenCV的dnn模塊做YOLOv5目標(biāo)檢測(cè)的程序的過程中遇到的bug以及解決的辦法,。 >>加入極市CV技術(shù)交流群,,走在計(jì)算機(jī)視覺的最前沿

最近看到多篇講解YOLOv5在OpenVINO部署做目標(biāo)檢測(cè)文章,但是沒看到過用OpenCV的DNN模塊做YOLOv5目標(biāo)檢測(cè)的,。于是,,我就想編寫一套用OpenCV的DNN模塊做YOLOv5目標(biāo)檢測(cè)的程序。

在編寫這套程序時(shí),,遇到的bug和解決辦法,,在這篇文章里講述一下。

YOLOv5之前的YOLOv3和YOLOv4的官方代碼都是基于darknet框架的實(shí)現(xiàn)的,,因此OpenCV的DNN模塊做目標(biāo)檢測(cè)時(shí),,讀取的是.cfg和.weight文件,那時(shí)候編寫程序很順暢,,沒有遇到bug,。

但是YOLOv5的官方代碼(https://github.com/ultralytics/yolov5)是基于Pytorch框架實(shí)現(xiàn)的,而OpenCV的DNN模塊不支持讀取Pytorch的訓(xùn)練模型文件,。如果想要把Pytorch的訓(xùn)練模型.pth文件加載到OpenCV的DNN模塊里,,需要先把Pytorch的訓(xùn)練模型.pth文件轉(zhuǎn)換到.onnx文件,然后才能載入到Opencv的DNN模塊里,。

因此,,用OpenCV的DNN模塊做YOLOv5目標(biāo)檢測(cè)的程序,包含兩個(gè)步驟:

1. 把Pytorch的訓(xùn)練模型.pth文件轉(zhuǎn)換到.onnx文件,。

2. OpenCV的DNN模塊讀取.onnx文件做前向計(jì)算,。

1. 把Pytorch的訓(xùn)練模型.pth文件轉(zhuǎn)換到.onnx文件

在做這一步時(shí),我得吐槽一下官方代碼:

https://github.com/ultralytics/yolov5

這套程序里的代碼混亂,,在Pytorch里,,通常是在.py文件里定義網(wǎng)絡(luò)結(jié)構(gòu)的,但是官方代碼是在.yaml文件定義網(wǎng)絡(luò)結(jié)構(gòu),,利用Pytorch動(dòng)態(tài)圖特性,,解析.yaml文件自動(dòng)生成網(wǎng)絡(luò)結(jié)構(gòu)。在.yaml文件里有depth_multiple和width_multiple,,它是控制網(wǎng)絡(luò)的深度和寬度的參數(shù),。

這么做的好處是能夠靈活的配置網(wǎng)絡(luò)結(jié)構(gòu),但是不利于理解網(wǎng)絡(luò)結(jié)構(gòu),。假如你想設(shè)斷點(diǎn)查看某一層的參數(shù)和輸出數(shù)值,,那就沒辦法了,。因此,在我編寫的轉(zhuǎn)換到.onnx文件的程序里,,網(wǎng)絡(luò)結(jié)構(gòu)是在.py文件里定義的,。

其次,在官方代碼里,,還有一個(gè)奇葩的地方,,那就是.pth文件。

起初,,我下載官方代碼到本地運(yùn)行時(shí),torch.load讀取.pth文件總是出錯(cuò),,后來把pytorch升級(jí)到1.7,,就讀取成功了。可以看到版本兼容性不好,,這是它的一個(gè)不足之處,。

設(shè)斷點(diǎn)查看讀取的.pth文件里的內(nèi)容,可以看到.pth里既存儲(chǔ)有模型參數(shù),,也存儲(chǔ)有網(wǎng)絡(luò)結(jié)構(gòu),,還儲(chǔ)存了一些超參數(shù),包括anchors,,stride等等的,。第一次見到有這種操作的,通常情況下,,.pth文件里只存儲(chǔ)了訓(xùn)練模型參數(shù)的,。

查看models\yolo.py里的Detect類,在構(gòu)造函數(shù)里,,有這么兩行代碼:

我嘗試過把這兩行代碼改成self.anchors = a 和 self.anchor_grid = a.clone().view(self.nl, 1, -1, 1, 1, 2),,程序依然能正常運(yùn)行,但是torch.save保存模型文件后,,可以看到.pth文件里沒有存儲(chǔ)anchors和anchor_grid了,,在網(wǎng)頁(yè)搜索register_buffer,解釋是:pytorch中register_buffer模型保存和加載的時(shí)候可以寫入和讀出,。

在這兩行代碼的下一行:

它的作用是做特征圖的輸出通道對(duì)齊,,通過1x1卷積把三種尺度特征圖的輸出通道都調(diào)整到 num_anchors*(num_classes+5)。

閱讀Detect類的forward函數(shù)代碼,,可以看出它的作用是根據(jù)偏移公式計(jì)算出預(yù)測(cè)框的中心坐標(biāo)和高寬,,這里需要注意的是,計(jì)算高和寬的代碼:

pwh = (ps[:, 2:4].sigmoid() * 2) ** 2 * anchors[i]

沒有采用exp操作,,而是直接乘上anchors[i],,這是YOLOv5與YOLOv3v4的一個(gè)最大區(qū)別(還有一個(gè)區(qū)別就是在訓(xùn)練階段的loss函數(shù)里,YOLOv5采用鄰域的正樣本anchor匹配策略,增加了正樣本,。其它的是一些小區(qū)別,,比如YOLOv5的第一個(gè)模塊采用FOCUS把輸入數(shù)據(jù)2倍下采樣切分成4份,在channel維度進(jìn)行拼接,,然后進(jìn)行卷積操作,,YOLOv5的激活函數(shù)沒有使用Mish)。

現(xiàn)在可以明白Detect類的作用是計(jì)算預(yù)測(cè)框的中心坐標(biāo)和高寬,,簡(jiǎn)單來說就是生成proposal,,作為后續(xù)NMS的輸入,進(jìn)而輸出最終的檢測(cè)框,。我覺得在Detect類里定義的1x1卷積是不恰當(dāng)?shù)?,?yīng)該把它定義在Detect類的外面,緊鄰著Detect類之前定義1x1卷積,。

在官方代碼里,,有轉(zhuǎn)換到onnx文件的程序:python models/export.py --weights yolov5s.pt --img 640 --batch 1

在pytorch1.7版本里,程序是能正常運(yùn)行生成onnx文件的,。觀察export.py里的代碼,,在執(zhí)行torch.onnx.export之前,有這么一段代碼:

注意其中的for循環(huán),,我試驗(yàn)過注釋掉它,,重新運(yùn)行就會(huì)出錯(cuò),打印出的錯(cuò)誤如下:

由此可見,,這段for循環(huán)代碼是必需的,。

2. OpenCV的DNN模塊讀取.onnx文件做前向計(jì)算

在生成.onnx文件后,就可以用OpenCV的DNN模塊里的cv2.dnn.readNet讀取它,。然而,,在讀取時(shí),出現(xiàn)了如下錯(cuò)誤:

我在網(wǎng)頁(yè)搜索這個(gè)問題的解決辦法,,看到一篇技術(shù)文章(https://zhuanlan.zhihu.com/p/286298001),,文章里講述的第一條:

于是查看YOLOv5的代碼,在common.py文件的Focus類,,torch.cat的輸入里有4次切片操作,,代碼如下:

那么現(xiàn)在需要更換索引式的切片操作,觀察到注釋的Contract類,,它就是用view和permute函數(shù)完成切片操作的,,于是修改代碼如下:

其次,在models\yolo.py里的Detect類里,,也有切片操作,,代碼如下:

前面說過,,Detect類的作用是計(jì)算預(yù)測(cè)框的中心坐標(biāo)和高寬,生成proposal,,這個(gè)是屬于后處理的,,因此不需要把它寫入到onnx文件里。

總結(jié)一下,,按照上面的截圖代碼,,修改Focus類,把Detect類里面的1x1卷積定義在緊鄰著Detect類之前的外面,,然后去掉Detect類,,組成新的model,作為torch.onnx.export的輸入,,

torch.onnx.export(model, inputs, output_onnx, verbose=False, opset_version=12, input_names=['images'], output_names=['out0', 'out1', 'out2'])

最后生成的onnx文件,,opencv的dnn模塊就能成功讀取了,接下來對(duì)照Detect類里的forward函數(shù),,用python或者C++編寫計(jì)算預(yù)測(cè)框的中心坐標(biāo)和高寬的功能。

周末這兩天,,我在win10+cpu機(jī)器里編寫了用OpenCV的DNN模塊做Yolov5目標(biāo)檢測(cè)的程序,,包含Python和C++兩個(gè)版本的。程序都調(diào)試通過了,,運(yùn)行結(jié)果也是正確的,。

我把這套代碼發(fā)布在了Github上,地址是:

https://github.com/hpc203/yolov5-dnn-cpp-python

后處理模塊,,python版本用numpy array實(shí)現(xiàn)的,,C++版本的用vector和數(shù)組實(shí)現(xiàn)的,整套程序只依賴OpenCV庫(kù)(opencv4版本以上的)就能正常運(yùn)行,,徹底擺脫對(duì)深度學(xué)習(xí)框架pytorch,tensorflow,caffe,mxnet等等的依賴,。

用OpenVINO作目標(biāo)檢測(cè),需要把onnx文件轉(zhuǎn)換到.bin和.xml文件,,相比于用DNN模塊加載onnx文件做目標(biāo)檢測(cè)是多了一個(gè)步驟的,。因此,我就想編寫一套用OpenCV的DNN模塊做YOLOv5目標(biāo)檢測(cè)的程序,,用Opencv的DNN模塊做深度學(xué)習(xí)目標(biāo)檢測(cè),,在win10和ubuntu,在cpu和gpu上都能運(yùn)行,,可見DNN模塊的通用性更好,,很接地氣。

作者檔案

作者:nihate

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多