【CV】手把手教你使用OpenCV,ONNXRuntime部署yolov5旋轉(zhuǎn)目標(biāo)檢測
導(dǎo)讀
?本文從旋轉(zhuǎn)角度、旋轉(zhuǎn)角度的余弦值、不規(guī)則四邊形的目標(biāo)檢測三個方向講述了模型需要注意的細(xì)節(jié),并附有代碼鏈接。?
1.學(xué)習(xí)旋轉(zhuǎn)角度
在無人機(jī)/遙感目標(biāo)檢測領(lǐng)域,拍攝到的物體通常是,如下圖中紅色矩形框里的飛機(jī),這是用ultralytics/yolov5檢測到的目標(biāo),很明顯水平矩形檢測框在檢測旋轉(zhuǎn)目標(biāo)時,檢測框里包含了無關(guān)背景區(qū)域,因此ultralytics/yolov5檢測旋轉(zhuǎn)目標(biāo),不是一個理想的解決方案。

在ultralytics/yolov5的檢測頭里添加一個學(xué)習(xí)旋轉(zhuǎn)角度angle的分支,考慮到旋轉(zhuǎn)角度是分布在0到180度之內(nèi)的一個整數(shù)值,因此把旋轉(zhuǎn)角度angle做為一個分類問題來學(xué)習(xí)。
這時模型輸出的每一個候選檢測框里的信息是 x,y,w,h,box_score,class_score,angle_score 這種形式的,其中x,y,w,h表示檢測框的中心點坐標(biāo),寬度和高度,box_score表示檢測框的置信度,class_score表示類別置信度,假如在coco數(shù)據(jù)集上訓(xùn)練的,coco數(shù)據(jù)集里有80個類別,那么class_score是一個長度為80的數(shù)組,它里面第i個元素表示第i個類別的置信度。angle_score表示傾斜角度的置信度,它是一個長度為180的數(shù)組,它里面第i個元素表示檢測矩形框的傾斜角等于i度的置信度。那么這時檢測框里包含信息的長度是5+80+180=265,這就使得yolov5的檢測頭里的最后3個1x1卷積的輸出通道數(shù)也別大,這時無疑會增大模型的計算量。
我在github發(fā)布了一套分別使用OpenCV,ONNXRuntime部署yolov5旋轉(zhuǎn)目標(biāo)檢測的demo程序,分別包含C++和Python兩個版本的程序。程序輸出矩形框的中心點坐標(biāo)(x, y),矩形框的高寬(h, w),矩形框的傾斜角,源碼地址是:https://github.com/hpc203/rotate-yolov5-opencv-onnxrun
在編寫后處理NMS函數(shù)時,需要注意的一個問題是用C++編程實現(xiàn)計算兩個旋轉(zhuǎn)矩形框的重疊面積,實現(xiàn)細(xì)節(jié)可以參考源碼。

2.學(xué)習(xí)旋轉(zhuǎn)角度的余弦值
在第1部分里講到學(xué)習(xí)旋轉(zhuǎn)角度會存在的一個問題是:由于旋轉(zhuǎn)角度是分布在0到180度之內(nèi)的一個整數(shù)值,也就是說有180種取值的可能,把旋轉(zhuǎn)角度作為一個分類任務(wù),會使得yolov5的檢測頭里的最后3個1x1卷積的輸出通道數(shù)也別大,這時會增大模型的計算量。注意到角度的余弦值是分布在-1到1之間的小數(shù)值,那么可以考慮學(xué)習(xí)旋轉(zhuǎn)角度的余弦值和正弦值。如下圖所示:

損失函數(shù)是SmoothL1Loss,示意圖如下:

這時,模型輸出的每個候選框里包含的信息是x,y,w,h, cos,sin, box_score,class_score這種形式的,其中cos表示檢測矩形框的傾斜角的余弦值,sin表示檢測矩形框的傾斜角的正弦值。假如在coco數(shù)據(jù)集上訓(xùn)練的,那么這時候選框的長度是4+2+1+80=87,很明顯這時模型的計算量會減少很多。
程序輸出矩形框的中心點坐標(biāo)(x, y),矩形框的高寬(h, w),矩形框的傾斜角的余弦值和正弦值的GitHub源碼地址:https://github.com/hpc203/rotateyolov5-opencv-onnxrun

3.不規(guī)則四邊形的目標(biāo)檢測
最近在極市平臺的打榜項目里有車牌識別項目,項目里要求檢測車牌的4個角點。可以仿照第1部分里的思路,在ultralytics/yolov5的檢測頭里添加一個學(xué)習(xí)四個角點的分支,這時,模型輸出的每個候選框里包含的信息是 x,y,w,h, box_score, x1,y1,x2,y2,x3,y3,x4,y4, class_score這種形式,其中x1,y1,x2,y2,x3,y3,x4,y4表示4個角點的坐標(biāo)值x和y。這時候的模型就能滿足項目的需求,但是注意到水平矩形框的位置信息x,y,w,h在項目里并沒有起作用,因此水平矩形框的位置信息是一個冗余的信息。
接著對模型繼續(xù)做修改,使模型輸出的是x1,y1,x2,y2,x3,y3,x4,y4,box_score,class_score,也就是去掉box分支,這時可以減小模型體積,減少計算量。修改的地方在yolov5的檢測頭和loss函數(shù),圖解如下:
(1).build_targets函數(shù)和檢測頭Detect

(2). 4個角點逆時針排序

(3). polygon box loss

程序輸出不規(guī)則四邊形的4個角點的坐標(biāo)x,y的源碼地址:https://github.com/hpc203/polygonyolov5-opencv-onnxrun
在編寫后處理NMS函數(shù)時,一個棘手的問題是計算不規(guī)則四邊形的面積,計算兩個不規(guī)則四邊形的重疊面積。如果是編寫Python程序,可以直接調(diào)用shapely庫解決,如果是編寫C++程序,那就比較棘手了,C++編程實現(xiàn)的細(xì)節(jié)可以參考源碼。

為了便于直觀理解第2節(jié)里的旋轉(zhuǎn)目標(biāo)檢測和第3節(jié)里的不規(guī)則四邊形目標(biāo)檢測,它們的差異,圖解如下:

往期精彩回顧
