IOU、YOLO v1、v2、v3學習總結

目標檢測主要分爲兩大類算法:一種是one-stage,如yolo、ssd,另一種是two-stage,如R-CNN、Fast R-CNN、Faster R-CNN。這篇文章主要講的是one-stage中的yolo系列算法,包括yolo v1、yolo v2、yolo v3。

 

1、什麼是IOU

IOU(Intersection over Union):指的是候選框(candidate bound)和原標記框(ground truth bound)的交疊率。它的計算公式如下:

A、B代表兩個不同的集合,IOU爲集合A和B的交集除以並集。 

1)對於一維的數據,假設,[x1, x2]屬於集合A的閉區間,[y1, y2]屬於集合B的閉區間,畫圖如下:

綠色爲集合A,藍色爲集合B,紅色爲A∩B,黃色爲A∪B。

交集下限:z1  =  max(x1, y1)

交集上限:z2 = min(x2, y2)

若z2 - z1<=0說明集合A、B之間沒有交集,z2 - z1>0說明A、B之間存在交集

2)對於二維數據,A爲[x, y, w, h],B爲[xx, yy, ww, hh],其中x,y爲A的中心點,w,h爲A矩形的寬和高,xx,yy爲B的中心點,ww,hh爲B矩形的寬和高,畫圖如下:

交集的寬:w_and = min(x+w/2, xx+ww/2) - max(x-w/2, xx-ww/2)

交集的高:h_and = min(y+h/2,yy+hh/2) - max(y-h/2, yy-hh/2) 

當w_and和h_and同時大於0的時候,A和B存在交集

 

2、YOLO v1

引用paper:

Our system divides the input image into an SxS grid, if the center of an object falls into grad cell, that grid cell is responsible for detecting that object.【圖片分爲SxS個cell,每個cell負責檢測中心點落在cell的物體】

Each bounding box consists of 5 predictions:x, y, w, h and confidence. Each grid cell also predicts C conditional class probabilities.【每個bounding box有五個參數,分別是x, y, w, h以及置信度,每個cell有C個類別的預測值】

網絡結構如下(還存在全連接層):

YOLO將圖片劃分爲7*7個cell,每個cell允許預測出兩個邊框,所以總共有7*7*2=98個bounding box。每個cell返回一個30維的向量,包含兩個bounding box的位置2*4,兩個bounding box的置信度以及20個類的概率。置信度代表着是否包含對象以及定位的準確率,最後採用NMS(非極大值抑制)NMS,選擇每個cell的bounding box。

loss的計算如下:

 loss包含三部分,分別是對定位、置信度、分類的誤差計算。

github相關代碼:https://github.com/xiongzihua/pytorch-YOLO-v1

 

3、YOLO v2

YOLO v2是在YOLO v1 的基礎上增加了一些tricks。簡要說明一下tricks。

1)BN:卷積層後加BN

2)High Resolution Classifier:提高分辨率,輸入爲448*448

3)Convlution and Anchor box:設置了anchor box(模仿faster R-CNN)

4)Dimension Clusters:維度聚類,因爲YOLO v1的定位不準確,所以v2想要模仿faster R-CNN,設置anchor box,但它又不屑於手動設置,所以用k-means進行聚類初始化anchor box,這裏的k-means所採用的距離不再是歐式距離,它的度量距離如下:

5)Direct location prediction:

6)Fine-Grained Features:有更好的細粒度,因爲v2使用passthrough操作

7)Multi-Scale Training:多尺度訓練

github相關代碼:https://github.com/ruiminshen/yolo2-pytorch

 

4、YOLO v3

在yolo的基礎上進行優化:

1)class prediction:每個邊框都會使用多標記分類來預測可能包含的類,使用單獨的邏輯分類器

2)prediction across scale and feature extractor:使用特徵金字塔類似的概念從尺寸中提取特徵,使用網絡網絡darknet-53

網絡結構如下,13*13有更大的感受野,採用大的anchor box,52*52的感受野較小,採用小的anchor box。

(圖片來自:https://blog.csdn.net/leviopku/article/details/82660381)

github相關代碼:https://github.com/qqwweee/keras-yolo3

yolo-v3 model代碼:

import numpy as np
import tensorflow as tf
from keras import backend as K
from keras.layers import Conv2D, Add, ZeroPadding2D, UpSampling2D, Concatenate, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.regularizers import l2

@wraps(Conv2D)
def DarknetConv2D(*args, **kwargs):
    darknet_conv_kwargs = {'kernel_regularizer':l2(5e-4)}
    darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides') = (2,2) else 'same'
    darknet_conv_kwargs.update(kwargs)
    return Conv2D(*args, **darknet_conv_kwargs)

# DBL
def DarknetConv2D_BN_Leaky(*args, **kwargs):
    no_bias_kwargs = {'use_bias':False}
    no_bias_kwargs.update(kwargs)
    return compose(
        DarknetConv2D(*args, **no_bias_kwargs),
        BatchNormalization(),
        LeakyReLU(alpha=0.1)
    )

# resnet n
# DBL+DBL+Add
def restblock_body(x, num_filters, num_blocks):
    x = ZeroPadding((1.0), (1.0))(x)
    x = DarknetConv2D_BN_Leaky(num_filters, (3, 3), strides=(2,2))(x)
    for i in range(num_blocks):
        y = compose(
            DarknetConv2D_BN_Leaky(num_filters//2, (1,1)),
            DarknetConv2D_BN_Leaky(num_filters//2, (3,3))(x)
        )
        x = Add()([x, y])
    return x

def darknet_body(x):
    x = DarknetConv2D_BN_Leaky(32, (3,3))(x)
    x = restblock_body(x, 64, 1)
    x = restblock_body(x, 128, 2)
    x = restblock_body(x, 256, 8)
    x = restblock_body(x, 512, 8)
    x = restblock_body(x, 1024, 4)
    return x

def make_last_layers(x, num_filters, out_filters):
    # 5個DBL
    x = compose(
        DarknetConv2D_BN_Leaky(num_filters, (1,1)),
        DarknetConv2D_BN_Leaky(num_filters, (3,3)),
        DarknetConv2D_BN_Leaky(num_filters, (1,1)),
        DarknetConv2D_BN_Leaky(num_filters, (3,3)),
        DarknetConv2D_BN_Leaky(num_filters, (1,1))
    )(x)
    # 1個DBL+conv
    y = compose(
        DarknetConv2D_BN_Leaky(num_filters*2, (3,3)),
        DarknetConv2D(out_filters, (1,1))
    )(x)
    return x, y

def yolo_body(inputs, num_anchors, num_classes):
    darnet = Model(inputs, darknet_body(inputs))
    x, y1 = make_last_layers(darknet.output, 512, num_anchors*(num_classes+5))
    
    x = compose(
        DarknetConv2D_BN_Leaky(256, (1,1)),
        UpSampling2D(2)
    )(x)
    x = Concatenate()([x, darknet.layers[152].output])
    x, y2 = make_last_layers(x, 256, num_anchors*(num_classes+5))
    
    x = compose(
        DarknetConv2D_BN_Leaky(128, (1,1)),
        UpSampling2D(2)
    )(x)
    x = Concatenate()([x, darknet.layers[192].output])
    x, y3 = make_last_layers(x, 128, num_anchors*(num_classes+5))
    return Model(inputs, [y1, y2, y3])

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章