1. 程式人生 > >SSD目標檢測(1):圖片+視訊內的物體定位(附原始碼)

SSD目標檢測(1):圖片+視訊內的物體定位(附原始碼)

一、SSD用於圖片物體的定位與檢測

SSD原理介紹這一篇部落格對我的幫助比較大,很詳細的介紹了SSD原理,送給大家做了解

1、下載SSD框架原始碼

1.1:閒話不多說——下載SSD原始碼,解壓後開啟檔案,將checkpoints資料夾下的壓縮包也解壓出來,再在pycharm上建立工程,大體如下圖所示: 這裡寫圖片描述 1.2:開啟demo資料夾,這裡就是用於外測的圖片集 這裡寫圖片描述

2、SSD做目標檢測

notebooks資料夾下,建立demo_test.py檔案,在demo_test.py檔案內寫入如下程式碼後,直接執行demo_test.py(以下程式碼也是notebooks資料夾ssd_tests.ipynb

內的程式碼,可以用notebook讀取;我只是做了一些小改動)

# -*- coding:utf-8 -*-
# -*- author:zzZ_CMing  CSDN address:https://blog.csdn.net/zzZ_CMing
# -*- 2018/07/14; 15:19
# -*- python3.5
"""
address: https://blog.csdn.net/qq_35608277/article/details/78660469
本文程式碼來自於github中微軟官方倉庫
"""
import os
import cv2
import math
import random
import
tensorflow as tf import matplotlib.pyplot as plt import matplotlib.cm as mpcm import matplotlib.image as mpimg from notebooks import visualization from nets import ssd_vgg_300, ssd_common, np_methods from preprocessing import ssd_vgg_preprocessing import sys # 當引用模組和執行的指令碼不在同一個目錄下,需在指令碼開頭新增如下程式碼: sys.path.append('./SSD-Tensorflow/'
) slim = tf.contrib.slim # TensorFlow session gpu_options = tf.GPUOptions(allow_growth=True) config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options) isess = tf.InteractiveSession(config=config) l_VOC_CLASS = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningTable', 'dog', 'horse', 'motorbike', 'person', 'pottedPlant', 'sheep', 'sofa', 'train', 'TV'] # 定義資料格式,設定佔位符 net_shape = (300, 300) # 預處理,以Tensorflow backend, 將輸入圖片大小改成 300x300,作為下一步輸入 img_input = tf.placeholder(tf.uint8, shape=(None, None, 3)) # 輸入影象的通道排列形式,'NHWC'表示 [batch_size,height,width,channel] data_format = 'NHWC' # 資料預處理,將img_input輸入的影象resize為300大小,labels_pre,bboxes_pre,bbox_img待解析 image_pre, labels_pre, bboxes_pre, bbox_img = ssd_vgg_preprocessing.preprocess_for_eval( img_input, None, None, net_shape, data_format, resize=ssd_vgg_preprocessing.Resize.WARP_RESIZE) # 拓展為4維變數用於輸入 image_4d = tf.expand_dims(image_pre, 0) # 定義SSD模型 # 是否複用,目前我們沒有在訓練所以為None reuse = True if 'ssd_net' in locals() else None # 調出基於VGG神經網路的SSD模型物件,注意這是一個自定義類物件 ssd_net = ssd_vgg_300.SSDNet() # 得到預測類和預測座標的Tensor物件,這兩個就是神經網路模型的計算流程 with slim.arg_scope(ssd_net.arg_scope(data_format=data_format)): predictions, localisations, _, _ = ssd_net.net(image_4d, is_training=False, reuse=reuse) # 匯入官方給出的 SSD 模型引數 ckpt_filename = '../checkpoints/ssd_300_vgg.ckpt' # ckpt_filename = '../checkpoints/VGG_VOC0712_SSD_300x300_ft_iter_120000.ckpt' isess.run(tf.global_variables_initializer()) saver = tf.train.Saver() saver.restore(isess, ckpt_filename) # 在網路模型結構中,提取搜尋網格的位置 # 根據模型超引數,得到每個特徵層(這裡用了6個特徵層,分別是4,7,8,9,10,11)的anchors_boxes ssd_anchors = ssd_net.anchors(net_shape) """ 每層的anchors_boxes包含4個arrayList,前兩個List分別是該特徵層下x,y座標軸對於原圖(300x300)大小的對映 第三,四個List為anchor_box的長度和寬度,同樣是經過歸一化對映的,根據每個特徵層box數量的不同,這兩個List元素 個數會變化。其中,長寬的值根據超引數anchor_sizes和anchor_ratios制定。 """ # 載入輔助作圖函式 def colors_subselect(colors, num_classes=21): dt = len(colors) // num_classes sub_colors = [] for i in range(num_classes): color = colors[i * dt] if isinstance(color[0], float): sub_colors.append([int(c * 255) for c in color]) else: sub_colors.append([c for c in color]) return sub_colors def bboxes_draw_on_img(img, classes, scores, bboxes, colors, thickness=2): shape = img.shape for i in range(bboxes.shape[0]): bbox = bboxes[i] color = colors[classes[i]] # Draw bounding box... p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1])) p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1])) cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) # Draw text... s = '%s/%.3f' % (l_VOC_CLASS[int(classes[i]) - 1], scores[i]) p1 = (p1[0] - 5, p1[1]) # cv2.putText(img, s, p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 1.5, color, 3) colors_plasma = colors_subselect(mpcm.plasma.colors, num_classes=21) # 主流程函式 def process_image(img, case, select_threshold=0.15, nms_threshold=.1, net_shape=(300, 300)): # select_threshold:box閾值——每個畫素的box分類預測資料的得分會與box閾值比較,高於一個box閾值則認為這個box成功框到了一個物件 # nms_threshold:重合度閾值——同一物件的兩個框的重合度高於該閾值,則執行下面去重函式 # 執行SSD模型,得到4維輸入變數,分類預測,座標預測,rbbox_img引數為最大檢測範圍,本文固定為[0,0,1,1]即全圖 rimg, rpredictions, rlocalisations, rbbox_img = isess.run([image_4d, predictions, localisations, bbox_img], feed_dict={img_input: img}) # ssd_bboxes_select()函式根據每個特徵層的分類預測分數,歸一化後的對映座標, # ancohor_box的大小,通過設定一個閾值計算得到每個特徵層檢測到的物件以及其分類和座標 rclasses, rscores, rbboxes = np_methods.ssd_bboxes_select(rpredictions, rlocalisations, ssd_anchors, select_threshold=select_threshold, img_shape=net_shape, num_classes=21, decode=True) """ 這個函式做的事情比較多,這裡說的細緻一些: 首先是輸入,輸入的資料為每個特徵層(一共6個,見上文)的: rpredictions: 分類預測資料, rlocalisations: 座標預測資料, ssd_anchors: anchors_box資料 其中: 分類預測資料為當前特徵層中每個畫素的每個box的分類預測 座標預測資料為當前特徵層中每個畫素的每個box的座標預測 anchors_box資料為當前特徵層中每個畫素的每個box的修正資料 函式根據座標預測資料和anchors_box資料,計算得到每個畫素的每個box的中心和長寬,這個中心座標和長寬會根據一個演算法進行些許的修正, 從而得到一個更加準確的box座標;修正的演算法會在後文中詳細解釋,如果只是為了理解演算法流程也可以不必深究這個,因為這個修正演算法屬於經驗算 法,並沒有太多邏輯可循。 修正完box和中心後,函式會計算每個畫素的每個box的分類預測資料的得分,當這個分數高於一個閾值(這裡是0.5)則認為這個box成功 框到了一個物件,然後將這個box的座標資料,所屬分類和分類得分匯出,從而得到: rclasses:所屬分類 rscores:分類得分 rbboxes:座標 最後要注意的是,同一個目標可能會在不同的特徵層都被檢測到,並且他們的box座標會有些許不同,這裡並沒有去掉重複的目標,而是在下文 中專門用了一個函式來去重 """ # 檢測有沒有超出檢測邊緣 rbboxes = np_methods.bboxes_clip(rbbox_img, rbboxes) rclasses, rscores, rbboxes = np_methods.bboxes_sort(rclasses, rscores, rbboxes, top_k=400) # 去重,將重複檢測到的目標去掉 rclasses, rscores, rbboxes = np_methods.bboxes_nms(rclasses, rscores, rbboxes, nms_threshold=nms_threshold) # 將box的座標重新對映到原圖上(上文所有的座標都進行了歸一化,所以要逆操作一次) rbboxes = np_methods.bboxes_resize(rbbox_img, rbboxes) if case == 1: bboxes_draw_on_img(img, rclasses, rscores, rbboxes, colors_plasma, thickness=8) return img else: return rclasses, rscores, rbboxes """ # 只做目標定位,不做預測分析 case = 1 img = cv2.imread("../demo/person.jpg") img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(process_image(img, case)) plt.show() """ # 做目標定位,同時做預測分析 case = 2 path = '../demo/person.jpg' # 讀取圖片 img = mpimg.imread(path) # 執行主流程函式 rclasses, rscores, rbboxes = process_image(img, case) # visualization.bboxes_draw_on_img(img, rclasses, rscores, rbboxes, visualization.colors_plasma) # 顯示分類結果圖 visualization.plt_bboxes(img, rclasses, rscores, rbboxes)rscores, rbboxes)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180

3、SSD目標檢測結果

會得到如下圖示,如圖已經成功的把物體標註出來,每個標記框中前一個數是標籤項,後一個是預測的準確率;

# 標籤項與其對應的標籤內容
dict = {1:'aeroplane',    2:'bicycle', 3:'bird',   4:'boat',       5:'bottle',
        6:'bus',          7:'car',     8:'cat',    9:'chair',      10:'cow',
        11:'diningTable', 12:'dog',    13:'horse', 14:'motorbike', 15:'person',
        16:'pottedPlant', 17:'sheep',  18:'sofa',  19:'train',     20:'TV'}
  • 1
  • 2
  • 3
  • 4
  • 5

這裡寫圖片描述—-—-—-—-—-—-—-—-—-—-—-—–—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—- –—-—-—-—-—-—-—-—-—-—-—-—–—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-

二、SSD用於視訊內物體的定位

以上demo資料夾內都只是圖片,如果你想在視訊中標記物體——首先你需要拍一段視訊,建議不要太長不然你要跑很久,然後需要在主目錄下建立Video資料夾,在其下建立inputoutput資料夾,如下圖所示: 這裡寫圖片描述

再將拍攝的視訊存入input資料夾下,注意視訊的名稱哦!最後在主目錄下建立demo_Video.py檔案,存入如下程式碼,執行demo_Video.py

請注意:166行的檔名要與資料夾視訊名一致 請注意:166行的檔名要與資料夾視訊名一致

# -*- coding:utf-8 -*-
# -*- author:zzZ_CMing  CSDN address:https://blog.csdn.net/zzZ_CMing
# -*- 2018/07/09; 15:19
# -*- python3.5
import os
import cv2
import math
import random
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.cm as mpcm
import matplotlib.image as mpimg
from notebooks import visualization
from nets import ssd_vgg_300, ssd_common, np_methods
from preprocessing import ssd_vgg_preprocessing
import sys

# 當引用模組和執行的指令碼不在同一個目錄下,需在指令碼開頭新增如下程式碼:
sys.path.append('./SSD-Tensorflow/')

slim = tf.contrib.slim

# TensorFlow session
gpu_options = tf.GPUOptions(allow_growth=True)
config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options)
isess = tf.InteractiveSession(config=config)

l_VOC_CLASS = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle',
               'bus', 'car', 'cat', 'chair', 'cow',
               'diningTable', 'dog', 'horse', 'motorbike', 'person',
               'pottedPlant', 'sheep', 'sofa', 'train', 'TV']

# 定義資料格式,設定佔位符
net_shape = (300, 300)
# 預處理,以Tensorflow backend, 將輸入圖片大小改成 300x300,作為下一步輸入
img_input = tf.placeholder(tf.uint8, shape=(None, None, 3))
# 輸入影象的通道排列形式,'NHWC'表示 [batch_size,height,width,channel]
data_format = 'NHWC'

# 資料預處理,將img_input輸入的影象resize為300大小,labels_pre,bboxes_pre,bbox_img待解析
image_pre, labels_pre, bboxes_pre, bbox_img = ssd_vgg_preprocessing.preprocess_for_eval(
    img_input, None, None, net_shape, data_format,
    resize=ssd_vgg_preprocessing.Resize.WARP_RESIZE)
# 拓展為4維變數用於輸入
image_4d = tf.expand_dims(image_pre, 0)

# 定義SSD模型
# 是否複用,目前我們沒有在訓練所以為None
reuse = True if 'ssd_net' in locals() else None
# 調出基於VGG神經網路的SSD模型物件,注意這是一個自定義類物件
ssd_net = ssd_vgg_300.SSDNet()
# 得到預測類和預測座標的Tensor物件,這兩個就是神經網路模型的計算流程
with slim.arg_scope(ssd_net.arg_scope(data_format=data_format)):
    predictions, localisations, _, _ = ssd_net.net(image_4d, is_training=False, reuse=reuse)

# 匯入官方給出的 SSD 模型引數
ckpt_filename = '../SSD-Tensorflow-master/checkpoints/ssd_300_vgg.ckpt'
# ckpt_filename = '../checkpoints/VGG_VOC0712_SSD_300x300_ft_iter_120000.ckpt'
isess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
saver.restore(isess, ckpt_filename)

# 在網路模型結構中,提取搜尋網格的位置
# 根據模型超引數,得到每個特徵層(這裡用了6個特徵層,分別是4,7,8,9,10,11)的anchors_boxes
ssd_anchors = ssd_net.anchors(net_shape)
"""
每層的anchors_boxes包含4個arrayList,前兩個List分別是該特徵層下x,y座標軸對於原圖(300x300)大小的對映
第三,四個List為anchor_box的長度和寬度,同樣是經過歸一化對映的,根據每個特徵層box數量的不同,這兩個List元素
個數會變化。其中,長寬的值根據超引數anchor_sizes和anchor_ratios制定。
"""


# 載入輔助作圖函式
def colors_subselect(colors, num_classes=21):
    dt = len(colors) // num_classes
    sub_colors = []
    for i in range(num_classes):
        color = colors[i * dt]
        if isinstance(color[0], float):
            sub_colors.append([int(c * 255) for c in color])
        else:
            sub_colors.append([c for c in color])
    return sub_colors


def bboxes_draw_on_img(img, classes, scores, bboxes, colors, thickness=2):
    shape = img.shape
    for i in range(bboxes.shape[0]):
        bbox = bboxes[i]
        color = colors[classes[i]]
        # Draw bounding box...
        p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1]))
        p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1]))
        cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness)
        # Draw text...
        s = '%s/%.3f' % (l_VOC_CLASS[int(classes[i]) - 1], scores[i])
        p1 = (p1[0] - 5, p1[1])
        # cv2.putText(img, s, p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 1.5, color, 3)


colors_plasma = colors_subselect(mpcm.plasma.colors, num_classes=21)


# 主流程函式
def process_image(img, select_threshold=0.2, nms_threshold=.1, net_shape=(300, 300)):
    # select_threshold:box閾值——每個畫素的box分類預測資料的得分會與box閾值比較,高於一個box閾值則認為這個box成功框到了一個物件
    # nms_threshold:重合度閾值——同一物件的兩個框的重合度高於該閾值,則執行下面去重函式

    # 執行SSD模型,得到4維輸入變數,分類預測,座標預測,rbbox_img引數為最大檢測範圍,本文固定為[0,0,1,1]即全圖
    rimg, rpredictions, rlocalisations, rbbox_img = isess.run([image_4d, predictions, localisations, bbox_img],
                                                              feed_dict={img_input: img})

    # ssd_bboxes_select函式根據每個特徵層的分類預測分數,歸一化後的對映座標,
    # ancohor_box的大小,通過設定一個閾值計算得到每個特徵層檢測到的物件以及其分類和座標
    rclasses, rscores, rbboxes = np_methods.ssd_bboxes_select(rpredictions, rlocalisations, ssd_anchors,
                                                              select_threshold=select_threshold,
                                                              img_shape=net_shape,
                                                              num_classes=21, decode=True)

    """
    這個函式做的事情比較多,這裡說的細緻一些:
    首先是輸入,輸入的資料為每個特徵層(一共6個,見上文)的:
                                                分類預測資料(rpredictions),
                                                座標預測資料(rlocalisations),
                                                anchors_box資料(ssd_anchors)
                                            其中:
                                               分類預測資料為當前特徵層中每個畫素的每個box的分類預測
                                               座標預測資料為當前特徵層中每個畫素的每個box的座標預測
                                               anchors_box資料為當前特徵層中每個畫素的每個box的修正資料

        函式根據座標預測資料和anchors_box資料,計算得到每個畫素的每個box的中心和長寬,這個中心座標和長寬會根據一個演算法進行些許的修正,
    從而得到一個更加準確的box座標;修正的演算法會在後文中詳細解釋,如果只是為了理解演算法流程也可以不必深究這個,因為這個修正演算法屬於經驗算
    法,並沒有太多邏輯可循。
        修正完box和中心後,函式會計算每個畫素的每個box的分類預測資料的得分,當這個分數高於一個閾值(這裡是0.5)則認為這個box成功
    框到了一個物件,然後將這個box的座標資料,所屬分類和分類得分匯出,從而得到:
        rclasses:所屬分類
        rscores:分類得分
        rbboxes:座標

        最後要注意的是,同一個目標可能會在不同的特徵層都被檢測到,並且他們的box座標會有些許不同,這裡並沒有去掉重複的目標,而是在下文
    中專門用了一個函式來去重
    """

    # 檢測有沒有超出檢測邊緣
    rbboxes = np_methods.bboxes_clip(rbbox_img, rbboxes)
    rclasses, rscores, rbboxes = np_methods.bboxes_sort(rclasses, rscores, rbboxes, top_k=400)
    # 去重,將重複檢測到的目標去掉
    rclasses, rscores, rbboxes = np_methods.bboxes_nms(rclasses, rscores, rbboxes, nms_threshold=nms_threshold)
    # 將box的座標重新對映到原圖上(上文所有的座標都進行了歸一化,所以要逆操作一次)
    rbboxes = np_methods.bboxes_resize(rbbox_img, rbboxes)

    bboxes_draw_on_img(img, rclasses, rscores, rbboxes, colors_plasma, thickness=8)
    return img


# 視訊物體定位
import imageio
imageio.plugins.ffmpeg.download()
from moviepy.editor import VideoFileClip

def process_video (input_path, output_path):
    video = VideoFileClip(input_path)
    result = video.fl_image(process_image)
    result.write_videofile(output_path, fps=40)

video_name = "3.mp4"
input_path = "./Video/input/" + video_name
output_path = "./Video/output/output_" + video_name
process_video(input_path,output_path )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169

經過一段時間的等待,終於跑完程式; 這裡寫圖片描述 開啟Video/input資料夾,檢視輸出的視訊是什麼樣子的吧!

由於部落格裡只能上傳gif圖,雖然原圖畫質很好,但到了這裡怎麼變成這樣?我能怎麼辦——我也很絕望 但是依稀可以看到裡面的汽車、行人、自行車都被不同的顏色框標註起來了,說明我們是成功的!趕快動手試一試,很好玩的 這裡寫圖片描述—-—-—-—-—-—-—-—-—-—-—-—–—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—- –—-—-—-—-—-—-—-—-—-—-—-—–—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-

後續:

SSD目標檢測(2):如何製作自己的資料集(詳細說明附原始碼) SSD目標檢測(3):使用自己的資料集做預測(詳細說明附原始碼) 這兩篇是SSD框架的實際運用——因為SSD框架只有20類物體被標註,也就是說只能用來識別這特定的20種物體,而實際需求會隨著環境有很大的改變,所以這兩篇就是教大家如何利用SSD框架,製作自己的資料集,並通過自己的資料集標註定位新物體,這個拓展練習有趣且實用,也是模式識別常見的問題研究,大家趕快動手試一試吧。