目標檢測算法之SSD

2021-02-14 機器學習算法工程師

SSD在很多框架上都有了開源的實現,這裡基於balancap的TensorFlow版本(https://github.com/balancap/SSD-Tensorflow)來實現SSD的Inference過程。這裡實現的是SSD300,與paper裡面不同的是,這裡採用。首先定義SSD的參數:

self.ssd_params = SSDParams(img_shape=(300, 300),   # 輸入圖片大小
                               num_classes=21,     # 類別數+背景
                               no_annotation_label=21,
                               feat_layers=["block4", "block7", "block8", "block9", "block10", "block11"],   # 要進行檢測的特徵圖name
                               feat_shapes=[(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)],  # 特徵圖大小
                               anchor_size_bounds=[0.15, 0.90],  # 特徵圖尺度範圍
                               anchor_sizes=[(21., 45.),
                                             (45., 99.),
                                             (99., 153.),
                                             (153., 207.),
                                             (207., 261.),
                                             (261., 315.)],  # 不同特徵圖的先驗框尺度(第一個值是s_k,第2個值是s_k+1)
                               anchor_ratios=[[2, .5],
                                              [2, .5, 3, 1. / 3],
                                              [2, .5, 3, 1. / 3],
                                              [2, .5, 3, 1. / 3],
                                              [2, .5],
                                              [2, .5]], # 特徵圖先驗框所採用的長寬比(每個特徵圖都有2個正方形先驗框)
                               anchor_steps=[8, 16, 32, 64, 100, 300],  # 特徵圖的單元大小
                               anchor_offset=0.5,                       # 偏移值,確定先驗框中心
                               normalizations=[20, -1, -1, -1, -1, -1],  # l2 norm
                               prior_scaling=[0.1, 0.1, 0.2, 0.2]       # variance
                               )

然後構建整個網絡,注意對於stride=2的conv不要使用TF自帶的padding="same",而是手動pad,這是為了與Caffe一致:

def _built_net(self):
   """Construct the SSD net"""
   self.end_points = {}  # record the detection layers output
   self._images = tf.placeholder(tf.float32, shape=[None, self.ssd_params.img_shape[0],
                                                   self.ssd_params.img_shape[1], 3])
   with tf.variable_scope("ssd_300_vgg"):
       # original vgg layers
       # block 1
       net = conv2d(self._images, 64, 3, scope="conv1_1")
       net = conv2d(net, 64, 3, scope="conv1_2")
       self.end_points["block1"] = net
       net = max_pool2d(net, 2, scope="pool1")
       # block 2
       net = conv2d(net, 128, 3, scope="conv2_1")
       net = conv2d(net, 128, 3, scope="conv2_2")
       self.end_points["block2"] = net
       net = max_pool2d(net, 2, scope="pool2")
       # block 3
       net = conv2d(net, 256, 3, scope="conv3_1")
       net = conv2d(net, 256, 3, scope="conv3_2")
       net = conv2d(net, 256, 3, scope="conv3_3")
       self.end_points["block3"] = net
       net = max_pool2d(net, 2, scope="pool3")
       # block 4
       net = conv2d(net, 512, 3, scope="conv4_1")
       net = conv2d(net, 512, 3, scope="conv4_2")
       net = conv2d(net, 512, 3, scope="conv4_3")
       self.end_points["block4"] = net
       net = max_pool2d(net, 2, scope="pool4")
       # block 5
       net = conv2d(net, 512, 3, scope="conv5_1")
       net = conv2d(net, 512, 3, scope="conv5_2")
       net = conv2d(net, 512, 3, scope="conv5_3")
       self.end_points["block5"] = net
       print(net)
       net = max_pool2d(net, 3, stride=1, scope="pool5")
       print(net)

       # additional SSD layers
       # block 6: use dilate conv
       net = conv2d(net, 1024, 3, dilation_rate=6, scope="conv6")
       self.end_points["block6"] = net
       #net = dropout(net, is_training=self.is_training)
       # block 7
       net = conv2d(net, 1024, 1, scope="conv7")
       self.end_points["block7"] = net
       # block 8
       net = conv2d(net, 256, 1, scope="conv8_1x1")
       net = conv2d(pad2d(net, 1), 512, 3, stride=2, scope="conv8_3x3",
                    padding="valid")
       self.end_points["block8"] = net
       # block 9
       net = conv2d(net, 128, 1, scope="conv9_1x1")
       net = conv2d(pad2d(net, 1), 256, 3, stride=2, scope="conv9_3x3",
                    padding="valid")
       self.end_points["block9"] = net
       # block 10
       net = conv2d(net, 128, 1, scope="conv10_1x1")
       net = conv2d(net, 256, 3, scope="conv10_3x3", padding="valid")
       self.end_points["block10"] = net
       # block 11
       net = conv2d(net, 128, 1, scope="conv11_1x1")
       net = conv2d(net, 256, 3, scope="conv11_3x3", padding="valid")
       self.end_points["block11"] = net

       # class and location predictions
       predictions = []
       logits = []
       locations = []
       for i, layer in enumerate(self.ssd_params.feat_layers):
           cls, loc = ssd_multibox_layer(self.end_points[layer], self.ssd_params.num_classes,
                                         self.ssd_params.anchor_sizes[i],
                                         self.ssd_params.anchor_ratios[i],
                                         self.ssd_params.normalizations[i], scope=layer+"_box")
           predictions.append(tf.nn.softmax(cls))
           logits.append(cls)
           locations.append(loc)
       return predictions, logits, locations

對於特徵圖的檢測,這裡單獨定義了一個組合層ssd_multibox_layer,其主要是對特徵圖進行兩次卷積,分別得到類別置信度與邊界框位置:

# multibox layer: get class and location predicitions from detection layer
def ssd_multibox_layer(x, num_classes, sizes, ratios, normalization=-1, scope="multibox"):
   pre_shape = x.get_shape().as_list()[1:-1]
   pre_shape = [-1] + pre_shape
   with tf.variable_scope(scope):
       # l2 norm
       if normalization > 0:
           x = l2norm(x, normalization)
           print(x)
       # numbers of anchors
       n_anchors = len(sizes) + len(ratios)
       # location predictions
       loc_pred = conv2d(x, n_anchors*4, 3, activation=None, scope="conv_loc")
       loc_pred = tf.reshape(loc_pred, pre_shape + [n_anchors, 4])
       # class prediction
       cls_pred = conv2d(x, n_anchors*num_classes, 3, activation=None, scope="conv_cls")
       cls_pred = tf.reshape(cls_pred, pre_shape + [n_anchors, num_classes])
       return cls_pred, loc_pred

相關焦點

  • 目標檢測算法之SSD訓練過程
    與之匹配的先驗框所對應的邊界框將負責預測它。最後就是進行NMS算法,過濾掉那些重疊度較大的預測框。最後剩餘的預測框就是檢測結果了。性能評估首先整體看一下SSD在VOC2007,VOC2012及COCO數據集上的性能,如表1所示。相比之下,SSD512的性能會更好一些。
  • 【論文詳解】目標檢測算法之SSD 深入詳解
    ,                                feat_layers=["block4", "block7", "block8", "block9", "block10", "block11"],   # 要進行檢測的特徵圖name                                feat_shapes=[(38, 38), (19, 19), (10
  • 算法系列 | MobileNet V2—SSD 的車道線檢測方法剖析
    本文藉助 Tensorflow Object detection API 開源框架和 MobileNet V2—SSD 算法,闡述如何創建、訓練自定義車道線數據集,並獲得 LDW 目標檢測模型。文件中 id 和 name 分別代表被測對象的數字標籤 label 及其名稱的字符串文本,若為多目標檢測,本文件需要另起一行,同時 id 數字依次增 1,相應的 name 也要更新(字符串不能重名)。
  • tensorflow+目標檢測:龍哥教你學視覺—LabVIEW深度學習教程
    2、學會使用imglabel軟體標註圖片,弄清楚怎麼樣標註目標3、學會利用labview調用tensorflow進行ssd/faster-rcnn模型的訓練4、學會利用labview實現觀察模型訓練過程loss曲線5、學會利用labview調用tensorflow進行ssd/faster-rcnn模型的評估6、學會利用labview
  • 【AI實戰】手把手教你訓練自己的目標檢測模型
    目標檢測是AI的一項重要應用,通過目標檢測模型能在圖像中把人、動物、汽車、飛機等目標物體檢測出來,甚至還能將物體的輪廓描繪出來,就像下面這張圖
  • tensorflow使用object detection實現目標檢測超詳細全流程(視頻+圖像集檢測)
    使用tensorflow object detection進行訓練檢測。參考原始代碼:https://github.com/tensorflow/models/tree/master/research本文以mobilenet-ssd-v2為例進行處理,通過換模型即可實現faster RCNN等的訓練檢測。
  • YOLO 系列目標檢測算法介紹
    YOLO 算法是基於 one-stage 的主流目標檢測算法,它不需要 region  proposal階段,可以直接產生目標物體的類別概率和位置坐標值
  • 基於深度學習的目標檢測算法研究進展
    這些算法大多是借鑑窮舉的思想,在基於滑動窗口生成的候選框內提取特徵,並將特徵交給分類器去識別。常見方法包括Hear特徵+Adaboost算法、Hog特徵+SVM算法等。因為早期很多的目標檢測算法缺乏有效的特徵表示,所以設計了許多複雜的特徵表示和在有限資源情況下處理特徵加速的技巧。
  • 目標檢測 | Yolo1算法原理總結
    算法通過運行單個卷積網絡來定位和檢測物體,流程圖如下:步驟:1)將輸入圖像的大小調整為448×4482)在圖像上運行卷積神經網絡,輸出每個grid cell的Bounding Box和所屬每個類的概率值3)根據非極大值抑制算法,輸出最有可能包含物體的Bounding Box若僅包含上述步驟
  • 目標檢測算法Fast R-CNN詳解
    前面我們一起學了SPP-Net和R-CNN的相關知識,如下:目標檢測算法SPP-Net詳解目標檢測R-CNN通俗詳解由於每期都是逐步改進
  • 收藏 | YOLO 系目標檢測算法家族全景圖!
    YOLOv4 目標檢測tricks集大成者YOLOv4: Optimal Speed and Accuracy of Object DetectionMV-YOLOMV-YOLO: Motion Vector-aided Tracking by Semantic Object Detection一種結合壓縮視頻中的運動信息和YOLO目標檢測的目標跟蹤算法
  • 【深度學習】基於TensorFlow + LabVIEW的工業缺陷檢測
    【新課上線】TensorFlow+目標檢測:龍哥教你學視覺—LabVIEW深度學習教程很多特徵我們通過傳統算法無法量化,或者說很難去做到的, 深度學習可以搞定。特別是在圖像分類, 目標檢測這些問題上取得了顯著的提升。下圖是近幾年來深度學習在圖像分類問題上取得的成績。
  • 教程 | 如何使用Docker、TensorFlow目標檢測API和OpenCV實現實時目標檢測和視頻處理
    李詩萌、路雪本文展示了如何使用 Docker 容器中的 TensorFlow 目標檢測 API,通過網絡攝像頭執行實時目標檢測,同時進行視頻後處理。此外,我還在項目中添加了視頻後處理功能,這一功能也使用了多進程,以減少視頻處理的時間(如果使用原始的 TensorFlow 目標檢測 API 處理視頻,會需要非常非常長的時間)。在我的個人電腦上可以同時進行高性能的實時目標檢測和視頻後處理工作,該過程僅使用了 8GB 的 CPU。
  • 經典神經網絡 | fast rcnn目標檢測算法詳解
    訓練算法的主網絡還是VGG16,輸入是224* 224* 3,經過5個卷積層和2個降採樣層(這兩個降採樣層分別跟在第一和第二個卷積層後面)後除了算法提升外,數據集越大算法的精度越高,所以數據是資訊時代的「石油」。
  • 德克薩斯大學提出:One-stage目標檢測最強算法 ExtremeNet
    比如(點擊可訪問):今天頭條推送的是目前人臉檢測方向的SOTA論文:改進SRN人臉檢測算法。本文要介紹的是目前(2019-01-26) one-stage目標檢測中最強算法:ExtremeNet。涉及圖像分類、目標檢測、圖像分割、人臉檢測&識別、目標跟蹤、GANs、學術競賽交流、Re-ID、風格遷移、醫學影像分析、姿態估計、OCR、SLAM、場景文字檢測&識別和超解析度等方向。
  • 【模型訓練】目標檢測實現分享四:詳解 YOLOv4 算法實現
    本文是目標檢測類算法實現分享的第四篇,前面已經寫過三篇,感興趣的同學可以查閱:  (1) 《【模型訓練】目標檢測實現分享一:詳解 YOLOv1 算法實現》;  (2) 《【模型訓練】目標檢測實現分享二
  • Transformer在目標檢測領域的開山之作DETR模型
    目標檢測算法,pipeline太複雜?不同任務人工設計不同的非極大值抑制(NMS)閾值、生成新的錨點(Anchor)?
  • 基於HOG+SVM的目標檢測與識別
    今天,我不是以一個科研人員的身份進行說話,而是站在一個普通的圖像算法應用工程師的角度總結下我的工作經驗,不足之處,多多海涵!     下面,我以一個人臉目標的檢測為例,使用OpenCV2.4.7做一個HOG+SVM的檢測實例。實例中,使用皮膚檢測分割作為快速目標檢測。
  • 深入理解one-stage目標檢測算法(下篇)
    數據有很多常用的目標檢測訓練數據集,如Pascal VOC, COCO, KITTI。這裡我們關注Pascal VOC,因為它是最常用的,並且YOLO使用了它。對於目標檢測,我們需要損失函數它能夠使模型預測出正確的邊界框,並對這些框正確分類,另一方面,模型不應該預測不存在的物體。這實際上是多任務學習。因此,損失函數由幾個不同的部分組成,其中一部分是回歸以預測邊界框位置,另一部分用於分類。對於任何一個檢測器,有兩種可能的情況:對於不應該檢測到物體的檢測器,當它們預測出置信度大於0的邊界框時要懲罰它們。
  • 目標檢測新方式 | class-agnostic檢測器用於目標檢測(附論文下載連結)
    ,然而,由於創建和注釋檢測數據集的難度和成本,訓練過的模型檢測到數量有限的目標類型,未知目標被視為背景內容。目標檢測模型在定位和分類訓練期間顯示目標時表現良好,然而,由於創建和注釋檢測數據集的難度和成本,訓練過的模型檢測到數量有限的目標類型,未知目標被視為背景內容。