『計算機視覺』目標檢測前沿及回顧(2018)

資料來源:人工智能前沿講習html

表格資料來源:hoya012的Githubpython

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

1、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是奠定性工做,基本全部的檢測算法的,都是在它的基礎上改進的,包括一步法SSDgit

Two Stage 的精度優點

二階段的分類:二步法的第一步在分類時,正負樣本是極不平衡的,致使分類器訓練比較困難,這也是一步法效果不如二步法的緣由之一,也是focal loss的motivation。而第二步在分類時,因爲第一步濾掉了絕大部分的負樣本,送給第二步分類的proposal中,正負樣本比例已經比較平衡了,因此第二步分類中不存在正負樣本極度不平衡的問題。即二步法能夠在很大程度上,緩和正負樣本極度不平衡的分類問題
二階段的迴歸:二步法中,第一步會先對初始候選框進行校訂,而後把校訂過的候選框送給第二步,做爲第二步校訂的初始候選框,再讓第二步進一步校訂
二階段的特徵:在二步法中,第一步和第二步法,除了共享的特徵外,他們都有本身獨有的特徵,專一於自身的任務。具體來講,這兩個步驟獨有的特徵,分別處理着不一樣難度的任務,如第一步中的特徵,專一於處理二分類任務(區分前景和背景)和粗略的迴歸問題;第二步的特徵,專一於處理多分類任務和精確的迴歸問題
特徵校準:在二步法中,有一個很重要的RoIPooling扣特徵的操做,它把候選區域對應的特徵摳出來,達到了特徵校準的目的,而一步法中,特徵是對不齊的github

2、One Stage目標檢測

一、One Stage目標檢測Pipeline 

二、One Stage目標檢測模型改進方向

    網絡設計(主幹網絡)
    anchors設置方案
    檢測框迴歸方式
    損失函數
PPT原文以下:算法

三、網絡設計改進

做者使用SSD系列網絡的發展展現了One Stage網絡主幹發展的脈絡,DSSD和FSSD我在學校的組會上作過講解,不過沒有整理成文,這裏不作過多講解,之後再提網絡

SSD

DSSD

FSSD

四、anchors生成方案改進

YOLOv1

SSD

YOLOv2-v3

RefineDet

這個網絡本文後面會介紹,這裏很少贅述。架構

五、迴歸目標設計

YOLO

YOLO用不相重疊的網格劃分區域,而選取的anchor爲真實框中心點所在的網格做爲迴歸的起始框,去匹配檢測目標,即一個anchor對應一個targetapp

SSD

SSD的網格多且相互重疊,其匹配策略也略複雜:每個anchor網格都有一個本身的class(都要去匹配一個真實框),在貢獻loss的時候,真實框僅和IOU大於閾值的anchor相匹配。ide

參見 :函數

『TensorFlow』SSD源碼學習_其二:基於VGG的SSD網絡前向架構

『TensorFlow』SSD源碼學習_其七:損失函數

CornetNet

ECCV 2018的文章,不採用anchor修正的方法作物體檢測,而是將ground-truth的左上和右下兩個角點視爲關鍵點,用熱圖來定位,實際設計很複雜,其損失函數設計也值得一看(特殊的網絡必定會有特殊的損失函數相匹配)。除了原文外,推薦個博客輔助理解:

CornetNet算法理解

六、損失函數

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,用來平衡正負樣本自己的比例不均

3、Two Stage目標檢測

一、Two Stage目標檢測Pipeline

二、Two Stage目標檢測模型改進方向

    生成Proposals
    ROI特徵獲取
    ROI算法設計
    加速檢測
    後處理迴歸框
PPT原文以下:

三、生成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

四、設計ROI算法

ROI Pooling 、ROI Align、PSROI Pool、PRROI Pool

五、兩步法準確率提高

六、模型後處理

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

IOU-Guided NMS

相關文章
相關標籤/搜索