基于深度學(xué)習(xí)和OpenCV的目標(biāo)檢測(cè)(Python)

今天說說使用深度學(xué)習(xí)進(jìn)行目標(biāo)檢測(cè)的文章努溃,第一部分講講Single shot detector(SSD)和MobileNet泽本。這二者相結(jié)合蠢琳,可以用來實(shí)現(xiàn)更快速的,實(shí)時(shí)的目標(biāo)檢測(cè)笋敞,尤其是在資源有限的設(shè)備上(包括Raspberry Pi, smartphones等等)碱蒙。

這里就說說如何使用OpenCV中的dnn模塊,用來導(dǎo)入一個(gè)實(shí)現(xiàn)訓(xùn)練好的目標(biāo)檢測(cè)網(wǎng)絡(luò)夯巷。使我們可以把圖像傳送到深度網(wǎng)絡(luò)中赛惩,然后得到圖中每個(gè)物體的包圍框(x,y)坐標(biāo)。最后趁餐,我們使用MobileNet SSDs來檢驗(yàn)這些圖像喷兼。

使用Single Shot Detectors進(jìn)行目標(biāo)檢測(cè)

當(dāng)提到用深度學(xué)習(xí)進(jìn)行目標(biāo)檢測(cè)時(shí),主要有下面三種方法:

  • Faster R-CNNs

  • You Only Look Once(YOLO)

  • Single Shot Detectors(SSDs)

Faster R-CNNs是最常聽說的基于深度學(xué)習(xí)的神經(jīng)網(wǎng)絡(luò)了后雷。然而季惯,這種方法在技術(shù)上是很難懂的(尤其是對(duì)于深度學(xué)習(xí)新手),也難以實(shí)現(xiàn)臀突,訓(xùn)練起來也是很困難勉抓。

此外,即使是使用了“Faster”的方法實(shí)現(xiàn)R-CNNs(這里R表示候選區(qū)域Region Proposal)候学,算法依然是比較慢的藕筋,大約是7FPS。

如果我們追求速度梳码,我們可以轉(zhuǎn)向YOLO隐圾,因?yàn)樗浅5目欤赥ianXGPU上可以達(dá)到40-90 FPS掰茶,最快的版本可能達(dá)到155 FPS暇藏。但YOLO的問題在于它的精度還有待提高。

SSDs最初是由谷歌開發(fā)的濒蒋,可以說是以上兩者之間的平衡盐碱。相對(duì)于Faster R-CNNs,它的算法更加直接沪伙。相對(duì)于YOLO瓮顽,又更加準(zhǔn)確。

MobileNets:高效(深度)神經(jīng)網(wǎng)路
20170425202801182.png

如上圖:
(左)標(biāo)準(zhǔn)的卷積層焰坪,包含batchnorm和ReLU。
(右)將卷基層分為depthwise 和pointwise 層聘惦,然后再加上batchnorm和ReLU(圖片和標(biāo)題出自Liu et al.)

當(dāng)搭建目標(biāo)檢測(cè)網(wǎng)絡(luò)時(shí)某饰,我們一般使用現(xiàn)有的網(wǎng)絡(luò)架構(gòu)儒恋,例如VGG 或者ResNet,然后在目標(biāo)檢測(cè)過程中使用它們黔漂。問題是诫尽,這些網(wǎng)絡(luò)結(jié)構(gòu)可能非常大,大約會(huì)有200-500MB炬守。

這類網(wǎng)絡(luò)架構(gòu)不適用于資源有限的設(shè)備牧嫉,因?yàn)橐驗(yàn)樗麄兊囊?guī)模太大計(jì)算結(jié)果太多。作為替代的選擇减途,我們使用MobileNets,另一個(gè)谷歌研究員的文章作品酣藻,我們稱之為“MobileNets”。因?yàn)檫@就是為了資源有限的設(shè)備(比如說手機(jī))而設(shè)計(jì)的鳍置。MobileNets與傳統(tǒng)CNNs不同之處在于可分離卷積(depthwiseseparable convolution)辽剧。

depthwise separable convolution的概念一般是指把卷積分解成兩部分:

1.一個(gè)3x3的denthwise卷積(深度卷積)

2.接著一個(gè)1x1的pointwise卷積(點(diǎn)卷積)

這使我們可以減少網(wǎng)絡(luò)中的參數(shù),降低計(jì)算量

這里有個(gè)問題就是損失了精度——MobileNets并不像其他的網(wǎng)絡(luò)那樣精度高税产。

但是他們更加的節(jié)省資源怕轿。

結(jié)合MobileNets和SSDs進(jìn)行更快更高效的深度學(xué)習(xí)目標(biāo)檢測(cè)

如果我們把MobileNets和SSDs框架結(jié)合起來,我們可以實(shí)現(xiàn)更快速辟拷,更高效的基于深度學(xué)習(xí)的目標(biāo)檢測(cè)撞羽。這里使用的模型是original tensorflow impetension的Caffe版本,是由chuanqi305訓(xùn)練的衫冻。

MobileNets SSDs最初是在COCO dataset 上訓(xùn)練的诀紊,然后在PASCAL VOC進(jìn)行調(diào)試并得到了72.7%的平均準(zhǔn)確率∮鸾埽可以檢測(cè)20種物體(1種是背景類的)渡紫,包括飛機(jī)、單車考赛、鳥惕澎、船、瓶子颜骤、公交車唧喉、汽車、貓忍抽、椅子八孝、奶牛、餐桌鸠项、狗干跛、馬、摩托車祟绊、人楼入、盆栽哥捕、羊、沙發(fā)嘉熊、火車遥赚、和電視機(jī)。

基于深度學(xué)習(xí)的OpenCV目標(biāo)檢測(cè)

下面說說使用OpenCV搭建深度學(xué)習(xí)目標(biāo)檢測(cè)器阐肤。

首先新建一個(gè)文件凫佛,命名為“deep_learning_object_detection.py”,并插入如下代碼:

# import the necessary packages
import numpy as np
import argparse
import cv2

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
 help="path to input image")
ap.add_argument("-p", "--prototxt", required=True,
 help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", required=True,
 help="path to Caffe pre-trained model")
ap.add_argument("-c", "--confidence", type=float, default=0.4,
 help="minimum probability to filter weak detections")
args = vars(ap.parse_args())

我們要做的第一件事是導(dǎo)入這個(gè)例子中需要的包——cv2中包含的dnn模塊孕惜,前提是使用的是OpenCV3.3版本愧薛。

然后傳入?yún)?shù):

  • --image : 輸入圖像的路徑

  • --prototxt: Caffe模型的路徑

  • --model:預(yù)訓(xùn)練的模型的路徑

  • --confidence: 能過濾弱檢測(cè)器的最小的可能性的閾值,默認(rèn)是20%诊赊。

接下來厚满,初始化類的標(biāo)簽和包圍框的顏色:

CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
 "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
 "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
 "sofa", "train", "tvmonitor"]
COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3))

上面創(chuàng)建了一個(gè)叫“CLASSES”的列表,接下來是顏色列表碧磅,用于存放對(duì)應(yīng)的包圍框的顏色碘箍。接下來導(dǎo)入模型:

# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])

上面這段代碼,主要是導(dǎo)入模型并打印了相關(guān)的信息鲸郊。
接下來丰榴,我們導(dǎo)入待測(cè)的圖片并準(zhǔn)備blob,以便傳輸?shù)皆诰W(wǎng)絡(luò)中秆撮。

# load the input image and construct an input blob for the image
# by resizing to a fixed 300x300 pixels and then normalizing it
# (note: normalization is done via the authors of the MobileNet SSD
# implementation)

image = cv2.imread(args["image"])
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 0.007843, (300, 300), 127.5)

注意上面的注釋塊四濒,我們導(dǎo)入了圖片,提取了高度和寬度职辨,計(jì)算了300x300的像素blob

現(xiàn)在我們準(zhǔn)備關(guān)鍵的工作——把這個(gè)blob傳入神經(jīng)網(wǎng)絡(luò)盗蟆。

# pass the blob through the network and obtain the detections and
# predictions
print("[INFO] computing object detections...")
net.setInput(blob)
detections = net.forward()

這里我們?cè)O(shè)置了神經(jīng)網(wǎng)絡(luò)的輸入,并且計(jì)算輸入的前向傳播舒裤,并將結(jié)果存儲(chǔ)為“detections”計(jì)算前向傳播和相關(guān)檢測(cè)將花費(fèi)一點(diǎn)時(shí)間喳资,具體取決于模型和輸入的尺寸,但是在這個(gè)例子里腾供,大部分CPU都能進(jìn)行快速的完成仆邓。

我們?cè)凇癲etections”中進(jìn)行循環(huán),檢測(cè)圖像中什么位置有什么樣的目標(biāo):


# loop over the detections
for i in np.arange(0, detections.shape[2]):
 # extract the confidence (i.e., probability) associated with the
 # prediction
 confidence = detections[0, 0, i, 2]
 # filter out weak detections by ensuring the `confidence` is
 # greater than the minimum confidence
 if confidence > args["confidence"]:
 # extract the index of the class label from the `detections`,
 # then compute the (x, y)-coordinates of the bounding box for
 # the object
 idx = int(detections[0, 0, i, 1])

 box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])

 (startX, startY, endX, endY) = box.astype("int")

 # display the prediction
 label = "{}: {:.2f}%".format(CLASSES[idx], confidence * 100)

 print("[INFO] {}".format(label))

 cv2.rectangle(image, (startX, startY), (endX, endY),
 COLORS[idx], 2)

 y = startY - 15 if startY - 15 > 15 else startY + 15

 cv2.putText(image, label, (startX, y),
 cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 2)

從detectons的循環(huán)開始伴鳖,記得單張圖片中可能出現(xiàn)多個(gè)目標(biāo)节值。我們還對(duì)每次檢測(cè)應(yīng)用了一個(gè)置信度的檢查機(jī)制。如果置信度足夠高(比如說超過了閾值)榜聂,那么我們將會(huì)在終端上顯示這個(gè)預(yù)測(cè)并且在圖像上繪制彩色的包圍框和文字搞疗,接下來我們逐句分析:

對(duì)detections進(jìn)行循環(huán),首先我們提取confidence值

如果confidence值超過了最小的閾值须肆,我們提取類的標(biāo)簽序號(hào)并且計(jì)算圍繞著被測(cè)物體的包圍框匿乃。

然后脐往,我們提取包圍框的(x,y)坐標(biāo),用于繪制矩形和顯示文字扳埂。

接下來,我們創(chuàng)建一個(gè)文字標(biāo)簽label瘤礁,包含類CLASS的名字和置信度阳懂。

使用該標(biāo)簽,在終端上顯示出來柜思,同時(shí)根據(jù)(x,y)坐標(biāo)繪制一個(gè)彩色的包圍著物體的矩形框岩调。

總的來說,我們希望標(biāo)簽在矩形之上赡盘,如果空間不夠号枕,也可以把他們顯示在矩形框的最上面一根線的下方。

最后陨享,我們?cè)趫D像上疊加彩色的標(biāo)簽文字

接下來的步驟就是顯示結(jié)果:

# show the output image
cv2.imshow("Output", image)
cv2.imwrite("output.jpg",image)
cv2.waitKey(0)

我們?cè)谄聊簧巷@示輸出的圖片葱淳,直到用戶按下一個(gè)任意鍵將其中止。同時(shí)將繪制標(biāo)記后的圖像保存下來抛姑。

OpenCV和深度學(xué)習(xí)目標(biāo)檢測(cè)結(jié)果

要運(yùn)行上面的代碼只要打開終端赞厕,運(yùn)行

$ python deep_learning_object_detection.py \
 --prototxt MobileNetSSD_deploy.prototxt.txt \
 --model MobileNetSSD_deploy.caffemodel --image images/example_19.jpg

結(jié)果


output-19.jpg
[INFO] loading model...
[INFO] computing object detections...
[INFO] car: 99.71%
[INFO] car: 98.40%

上圖識(shí)別出一輛汽車的概率是99.99%

換一個(gè)例子:

運(yùn)行


$ python deep_learning_object_detection.py \
 --prototxt MobileNetSSD_deploy.prototxt.txt \
 --model MobileNetSSD_deploy.caffemodel --image images/example_18.jpg

結(jié)果


output-18.jpg
[INFO] loading model...
[INFO] computing object detections...
[INFO] chair: 99.96%
[INFO] chair: 99.78%
[INFO] chair: 58.37%
[INFO] diningtable: 99.90%
[INFO] pottedplant: 51.57%

再換一個(gè)例子:

運(yùn)行

$ python deep_learning_object_detection.py \
 --prototxt MobileNetSSD_deploy.prototxt.txt \
 --model MobileNetSSD_deploy.caffemodel --image images/example_16.jpg

結(jié)果


output-16.jpg
[INFO] loading model...
[INFO] computing object detections...
[INFO] bicycle: 69.82%
[INFO] bicycle: 66.97%
[INFO] car: 99.99%
[INFO] person: 99.98%
[INFO] person: 51.63%
總結(jié)

這一篇我們使用了MobileNets + SSDs檢測(cè)器和OpenCV3.3最新的dnn模塊進(jìn)行圖像中的目標(biāo)檢測(cè)。接下來還會(huì)寫如何在視頻流中進(jìn)行目標(biāo)檢測(cè)定硝。

參考:
https://www.pyimagesearch.com/2017/09/11/object-detection-with-deep-learning-and-opencv/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皿桑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蔬啡,更是在濱河造成了極大的恐慌诲侮,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箱蟆,死亡現(xiàn)場(chǎng)離奇詭異沟绪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)顽腾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門近零,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抄肖,你說我怎么就攤上這事久信。” “怎么了漓摩?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵裙士,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我管毙,道長(zhǎng)腿椎,這世上最難降的妖魔是什么桌硫? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮啃炸,結(jié)果婚禮上铆隘,老公的妹妹穿的比我還像新娘。我一直安慰自己南用,他們只是感情好膀钠,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著裹虫,像睡著了一般肿嘲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上筑公,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天雳窟,我揣著相機(jī)與錄音,去河邊找鬼匣屡。 笑死封救,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捣作。 我是一名探鬼主播兴泥,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼虾宇!你這毒婦竟也來了搓彻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤嘱朽,失蹤者是張志新(化名)和其女友劉穎旭贬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搪泳,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稀轨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岸军。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奋刽。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖艰赞,靈堂內(nèi)的尸體忽然破棺而出佣谐,到底是詐尸還是另有隱情,我是刑警寧澤方妖,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布狭魂,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雌澄。R本人自食惡果不足惜斋泄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望镐牺。 院中可真熱鬧炫掐,春花似錦、人聲如沸睬涧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宙地。三九已至,卻和暖如春逆皮,著一層夾襖步出監(jiān)牢的瞬間宅粥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工电谣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秽梅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓剿牺,卻偏偏與公主長(zhǎng)得像企垦,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晒来,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容