資料來源:人工智能前沿講習
表格資料來源:hoya012的Github
Detector | VOC07 (mAP@IoU=0.5) | VOC12 (mAP@IoU=0.5) | COCO (mAP@IoU=0.5:0.95) | Published In |
---|---|---|---|---|
R-CNN | 58.5 | - | - | CVPR'14 |
SPP-Net | 59.2 | - | - | ECCV'14 |
MR-CNN | 78.2 (07+12) | 73.9 (07+12) | - | ICCV'15 |
Fast R-CNN | 70.0 (07+12) | 68.4 (07++12) | 19.7 | ICCV'15 |
Faster R-CNN | 73.2 (07+12) | 70.4 (07++12) | 21.9 | NIPS'15 |
YOLO v1 | 66.4 (07+12) | 57.9 (07++12) | - | CVPR'16 |
G-CNN | 66.8 | 66.4 (07+12) | - | CVPR'16 |
AZNet | 70.4 | - | 22.3 | CVPR'16 |
ION | 80.1 | 77.9 | 33.1 | CVPR'16 |
HyperNet | 76.3 (07+12) | 71.4 (07++12) | - | CVPR'16 |
OHEM | 78.9 (07+12) | 76.3 (07++12) | 22.4 | CVPR'16 |
MPN | - | - | 33.2 | BMVC'16 |
SSD | 76.8 (07+12) | 74.9 (07++12) | 31.2 | ECCV'16 |
GBDNet | 77.2 (07+12) | - | 27.0 | ECCV'16 |
CPF | 76.4 (07+12) | 72.6 (07++12) | - | ECCV'16 |
R-FCN | 79.5 (07+12) | 77.6 (07++12) | 29.9 | NIPS'16 |
DeepID-Net | 69.0 | - | - | PAMI'16 |
NoC | 71.6 (07+12) | 68.8 (07+12) | 27.2 | TPAMI'16 |
DSSD | 81.5 (07+12) | 80.0 (07++12) | 33.2 | arXiv'17 |
TDM | - | - | 37.3 | CVPR'17 |
FPN | - | - | 36.2 | CVPR'17 |
YOLO v2 | 78.6 (07+12) | 73.4 (07++12) | - | CVPR'17 |
RON | 77.6 (07+12) | 75.4 (07++12) | 27.4 | CVPR'17 |
DeNet | 77.1 (07+12) | 73.9 (07++12) | 33.8 | ICCV'17 |
CoupleNet | 82.7 (07+12) | 80.4 (07++12) | 34.4 | ICCV'17 |
RetinaNet | - | - | 39.1 | ICCV'17 |
DSOD | 77.7 (07+12) | 76.3 (07++12) | - | ICCV'17 |
SMN | 70.0 | - | - | ICCV'17 |
Light-Head R-CNN | - | - | 41.5 | arXiv'17 |
YOLO v3 | - | - | 33.0 | arXiv'18 |
SIN | 76.0 (07+12) | 73.1 (07++12) | 23.2 | CVPR'18 |
STDN | 80.9 (07+12) | - | - | CVPR'18 |
RefineDet | 83.8 (07+12) | 83.5 (07++12) | 41.8 | CVPR'18 |
SNIP | - | - | 45.7 | CVPR'18 |
Relation-Network | - | - | 32.5 | CVPR'18 |
Cascade R-CNN | - | - | 42.8 | CVPR'18 |
MLKP | 80.6 (07+12) | 77.2 (07++12) | 28.6 | CVPR'18 |
Fitness-NMS | - | - | 41.8 | CVPR'18 |
RFBNet | 82.2 (07+12) | - | - | ECCV'18 |
CornerNet | - | - | 42.1 | ECCV'18 |
PFPNet | 84.1 (07+12) | 83.7 (07++12) | 39.4 | ECCV'18 |
Pelee | 70.9 (07+12) | - | - | NIPS'18 |
HKRM | 78.8 (07+12) | - | 37.8 | NIPS'18 |
M2Det | - | - | 44.2 | AAAI'19 |
R-DAD | 81.2 (07++12) | 82.0 (07++12) | 43.1 | AAAI'19 |
一、One Stage 和 Two Stage
物體檢測算法大致分為兩類:一步法檢測器和二步法檢測器
一步法檢測器:在原圖上鋪設一系列錨點框(anchor),利用一個全卷積網絡,對這些錨點框進行一次分類和一次回歸,得到檢測結果。
二步法檢測器:在原圖上鋪設一系列錨點框(anchor),利用一個網絡,對這些錨點框進行兩次分類和兩次回歸,得到檢測結果。
相對於一步法檢測器,二步法檢測器多了一個步驟。如果這兩類方法在相同的條件下(如相同的輸入,相同的anchor設置,相同的機器等),一步法一般勝在高效率,因為它沒有耗時的第二步,而二步法的精度要更高一些,現在各個檢測庫上排名靠前的算法,基本都是二步法。
比較出名的一步法檢測器有YOLO、SSD、RetinaNet、CornerNet,其中SSD是一步法檢測器的集大成者,后續大部分的一步法工作都是基於它的
比較出名的二步法檢測器有Faster R-CNN、R-FCN、FPN、Cascade R-CNN、SNIP,其中Faster R-CNN是奠基性工作,基本所有的檢測算法的,都是在它的基礎上改進的,包括一步法SSD
Two Stage 的精度優勢
二階段的分類:二步法的第一步在分類時,正負樣本是極不平衡的,導致分類器訓練比較困難,這也是一步法效果不如二步法的原因之一,也是focal loss的motivation。而第二步在分類時,由於第一步濾掉了絕大部分的負樣本,送給第二步分類的proposal中,正負樣本比例已經比較平衡了,所以第二步分類中不存在正負樣本極度不平衡的問題。即二步法可以在很大程度上,緩和正負樣本極度不平衡的分類問題
二階段的回歸:二步法中,第一步會先對初始候選框進行校正,然后把校正過的候選框送給第二步,作為第二步校正的初始候選框,再讓第二步進一步校正
二階段的特征:在二步法中,第一步和第二步法,除了共享的特征外,他們都有自己獨有的特征,專注於自身的任務。具體來說,這兩個步驟獨有的特征,分別處理着不同難度的任務,如第一步中的特征,專注於處理二分類任務(區分前景和背景)和粗略的回歸問題;第二步的特征,專注於處理多分類任務和精確的回歸問題
特征校准:在二步法中,有一個很重要的RoIPooling扣特征的操作,它把候選區域對應的特征摳出來,達到了特征校准的目的,而一步法中,特征是對不齊的
二、One Stage目標檢測
1、One Stage目標檢測Pipeline
2、One Stage目標檢測模型改進方向
網絡設計(主干網絡)
anchors設置方案
檢測框回歸方式
損失函數
PPT原文如下:
3、網絡設計改進
作者使用SSD系列網絡的發展展示了One Stage網絡主干發展的脈絡,DSSD和FSSD我在學校的組會上做過講解,不過沒有整理成文,這里不做過多講解,以后再提
SSD
DSSD
FSSD
4、anchors生成方案改進
YOLOv1
SSD
YOLOv2-v3
RefineDet
這個網絡本文后面會介紹,這里不多贅述。
5、回歸目標設計
YOLO
YOLO用不相重疊的網格划分區域,而選取的anchor為真實框中心點所在的網格作為回歸的起始框,去匹配檢測目標,即一個anchor對應一個target
SSD
SSD的網格多且相互重疊,其匹配策略也略復雜:每一個anchor網格都有一個自己的class(都要去匹配一個真實框),在貢獻loss的時候,真實框僅和IOU大於閾值的anchor相匹配。
參見 :
『TensorFlow』SSD源碼學習_其二:基於VGG的SSD網絡前向架構
CornetNet
ECCV 2018的文章,不采用anchor修正的方法做物體檢測,而是將ground-truth的左上和右下兩個角點視為關鍵點,用熱圖來定位,實際設計很復雜,其損失函數設計也值得一看(特殊的網絡一定會有特殊的損失函數相匹配)。除了原文外,推薦個博客輔助理解:
6、損失函數
OHEM
OHEM是Fast RCNN的改進,適合於batch size(images)較少,但每張image的examples很多的情況,針對困難object進行提取。
思想概括如下:
In OHEM each example is scored by its loss, non-maximum suppression (nms) is then applied, and a minibatch is constructed with the highest-loss examples.
實際應用流程:
將Fast RCNN分成兩個components:ConvNet和RoINet. ConvNet為共享的底層卷積層,RoINet為RoI Pooling后的層,包括全連接層;
2 對於每張輸入圖像,經前向傳播,用ConvNet獲得feature maps(這里為RoI Pooling層的輸入);
3 將事先計算好的proposals,經RoI Pooling層投影到feature maps上,獲取固定的特征輸出作為全連接層的輸入;
需要注意的是,論文說,為了減少顯存以及后向傳播的時間,這里的RoINet是有兩個的,它們共享權重,
RoINet1是只讀(只進行forward),RoINet2進行forward和backward:
a 將原圖的所有props扔到RoINet1(上圖a部分),計算它們的loss(這里有兩個loss:cls和det);
b 根據loss從高到低排序,以及利用NMS,來選出前K個props(K由論文里的N和B參數決定)
為什么要用NMS? 顯然對於那些高度overlap的props經RoI的投影后,
其在feature maps上的位置和大小是差不多一樣的,容易導致loss double counting問題
c 將選出的K個props(可以理解成hard examples)扔到RoINet2(上圖b部分),
這時的RoINet2和Fast RCNN的RoINet一樣,計算K個props的loss,並回傳梯度/殘差給ConvNet,來更新整個網絡
Focal loss
RetinaNet提出的致力於解決正負樣本不均衡的新型損失函數
出發點:希望one-stage detector可以達到two-stage detector的准確率,同時不影響原有的速度
問題假設:作者認為one-stage detector的准確率不如two-stage detector的原因是樣本的類別不均衡
相關工作:作者認為OHEM算法雖然增加了錯分類樣本的權重,但是完全忽略了容易分類的樣本
focal loss:在標准交叉熵損失基礎上修改得到的。這個函數可以通過減少易分類樣本的權重,使得模型在訓練時更專注於難分類的樣本
原交叉熵:
Focal loss改進:
gamma>0使得減少易分類樣本的損失,使得更關注於困難的、錯分的樣本
添加正負樣本:
加入平衡因子alpha,用來平衡正負樣本本身的比例不均
三、Two Stage目標檢測
1、Two Stage目標檢測Pipeline
2、Two Stage目標檢測模型改進方向
生成Proposals
ROI特征獲取
ROI算法設計
加速檢測
后處理回歸框
PPT原文如下:
3、生成Proposals
R-CNN
使用某些算法生成推薦框,這些推薦區直接在原圖上crop生成Proposals,然后非極大值抑制合並這些Proposals的分類、回歸結果,作者使用“聚類”描述這個合並過程
Faster R-CNN
這個講濫了,直接用anchors經過第一次分類、回歸得到的推薦框crop原圖經過特征提取網生成的特征圖,結果作為Proposals進行分類、回歸
FPN
總體來看和Faster R-CNN類似,不過crop的目標不再是原圖經過網絡生成的一張特征圖,而是在特征金字塔上尋找某一層作為crop目標
Cascade R-CNN
這篇是CVPR 2018的文章,核心是Cascade roi-wise subnet,用於更好的利用IOU進行回歸結果的修正,簡單解釋一下下圖,經過conv出來的特征要經過align pool才能進入subnet,這里采用了聯級的方式操作,B0是二分類生成的框,選取一系列IOU閾值{0.5, 0.6, 0.7},B1是B0在conv輸出特征上crop出來子區域經過H1回歸的結果,B2則是B1在conv輸出……,閾值逐漸嚴格回歸效果更好
R-FCN
生成K*K*(C+1)張特征,K為ROI輸出尺寸,在K*K組中每一組只取對應輸出位置的Pool結果,重新排列整理得到我們想要的特征:『計算機視覺』R-FCN
4、設計ROI算法
ROI Pooling 、ROI Align、PSROI Pool、PRROI Pool
5、兩步法准確率提升
6、模型后處理
NMS
非極大值抑制
Soft NMS
def cpu_soft_nms(np.ndarray[float, ndim=2] boxes, float sigma=0.5, float Nt=0.3, float threshold=0.001, unsigned int method=0): cdef unsigned int N = boxes.shape[0] cdef float iw, ih, box_area cdef float ua cdef int pos = 0 cdef float maxscore = 0 cdef int maxpos = 0 cdef float x1,x2,y1,y2,tx1,tx2,ty1,ty2,ts,area,weight,ov for i in range(N): maxscore = boxes[i, 4] maxpos = i tx1 = boxes[i,0] ty1 = boxes[i,1] tx2 = boxes[i,2] ty2 = boxes[i,3] ts = boxes[i,4] pos = i + 1 # get max box while pos < N: if maxscore < boxes[pos, 4]: maxscore = boxes[pos, 4] maxpos = pos pos = pos + 1 # add max box as a detection boxes[i,0] = boxes[maxpos,0] boxes[i,1] = boxes[maxpos,1] boxes[i,2] = boxes[maxpos,2] boxes[i,3] = boxes[maxpos,3] boxes[i,4] = boxes[maxpos,4] # swap ith box with position of max box boxes[maxpos,0] = tx1 boxes[maxpos,1] = ty1 boxes[maxpos,2] = tx2 boxes[maxpos,3] = ty2 boxes[maxpos,4] = ts tx1 = boxes[i,0] ty1 = boxes[i,1] tx2 = boxes[i,2] ty2 = boxes[i,3] ts = boxes[i,4] pos = i + 1 # NMS iterations, note that N changes if detection boxes fall below threshold while pos < N: x1 = boxes[pos, 0] y1 = boxes[pos, 1] x2 = boxes[pos, 2] y2 = boxes[pos, 3] s = boxes[pos, 4] area = (x2 - x1 + 1) * (y2 - y1 + 1) iw = (min(tx2, x2) - max(tx1, x1) + 1) if iw > 0: ih = (min(ty2, y2) - max(ty1, y1) + 1) if ih > 0: ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih) ov = iw * ih / ua #iou between max box and detection box if method == 1: # linear if ov > Nt: weight = 1 - ov else: weight = 1 elif method == 2: # gaussian weight = np.exp(-(ov * ov)/sigma) else: # original NMS if ov > Nt: weight = 0 else: weight = 1 boxes[pos, 4] = weight*boxes[pos, 4] # if box score falls below threshold, discard the box by swapping with last box # update N if boxes[pos, 4] < threshold: boxes[pos,0] = boxes[N-1, 0] boxes[pos,1] = boxes[N-1, 1] boxes[pos,2] = boxes[N-1, 2] boxes[pos,3] = boxes[N-1, 3] boxes[pos,4] = boxes[N-1, 4] N = N - 1 pos = pos - 1 pos = pos + 1 keep = [i for i in range(N)] return keep