OpenCV是計(jì)算機(jī)視覺(jué)領(lǐng)域使用最為廣泛的開(kāi)源庫(kù),以功能全面使用方便著稱。自3.3版本開(kāi)始,OpenCV加入了對(duì)深度神經(jīng)網(wǎng)絡(luò)(DNN)推理運(yùn)算的支持。在LiveVideoStack線上交流分享中英特爾亞太研發(fā)有限公司開(kāi)源技術(shù)中心軟件工程師吳至文詳細(xì)介紹了OpenCVDNN模塊的現(xiàn)狀,架構(gòu),以及加速技術(shù)。
注:文中的ppt是作者在EmbeddedLinuxConference2018上的演講“DeepLearninginOpenCV”的ppt
大家好,我是吳至文,目前就職于英特爾開(kāi)源技術(shù)中心,主要從事圖形、圖像深度學(xué)習(xí)算法方面的開(kāi)發(fā)和優(yōu)化工作。很高興有機(jī)會(huì)和大家分享一下關(guān)于OpenCV深度學(xué)習(xí)模塊的內(nèi)容,同時(shí),也會(huì)介紹一下我們團(tuán)隊(duì)在OpenCV深度學(xué)習(xí)方面所做的一些工作。
本次分享的主要內(nèi)容包含以下幾個(gè)方面:
首先,我會(huì)介紹一下OpenCV和深度學(xué)習(xí)的背景知識(shí);然后,介紹今天的主題——OpenCV深度學(xué)習(xí)模塊;接下來(lái),會(huì)簡(jiǎn)單介紹我們團(tuán)隊(duì)在OpenCL加速方面所做的工作,以及開(kāi)發(fā)的一個(gè)Vulkan后端;最后,會(huì)以一個(gè)例子的形式來(lái)展示如何使用DNN模塊開(kāi)發(fā)深度神經(jīng)網(wǎng)絡(luò)的應(yīng)用。
一,OpenCV背景介紹
首先,什么是OpenCV呢?我相信做過(guò)圖形圖像、計(jì)算機(jī)視覺(jué)應(yīng)用開(kāi)發(fā)的同學(xué)可能對(duì)OpenCV都不會(huì)陌生。OpenCV是一個(gè)包含了2500多個(gè)經(jīng)過(guò)優(yōu)化的計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)算法的開(kāi)源計(jì)算機(jī)視覺(jué)庫(kù)。換句話說(shuō),目前主流的、比較知名的計(jì)算機(jī)視覺(jué)算法和論文在OpenVC里都能找到相應(yīng)的實(shí)現(xiàn)。OpenCV不僅僅是一個(gè)很好用的開(kāi)發(fā)工具集,它同時(shí)對(duì)有志于學(xué)習(xí)計(jì)算機(jī)視覺(jué)開(kāi)發(fā)的學(xué)生也是一個(gè)寶庫(kù)。OpenVC支持C、C++和Python語(yǔ)言,但是從OpenCV4.0開(kāi)始,C語(yǔ)言的API就逐漸被清除出去了,現(xiàn)在比較常用的API是C++和Python語(yǔ)言的。此外,OpenCV也是一個(gè)很活躍的開(kāi)源項(xiàng)目,到目前為止它在Github上有兩萬(wàn)多個(gè)Forks。
2018年11月份,OpenCV發(fā)布了4.0的版本。在這個(gè)版本有了比較大的變化,大概有以下這幾點(diǎn):首先,它使用了C++11標(biāo)準(zhǔn)編譯器,并且移除了大多數(shù)的C語(yǔ)言的API接口;另外,它不再對(duì)之前的版本有二進(jìn)制的兼容,同時(shí)它使用了大量AVX2的指令集優(yōu)化,從而大大提高了一些算法在CPU上的運(yùn)行效率;再者就是,它具有更小的內(nèi)存占用以及支持OpenVINO作為DNN模塊的后端。OpenVINO對(duì)于有的同學(xué)可能比較陌生,它是英特爾發(fā)布的一個(gè)針對(duì)深度學(xué)習(xí)視覺(jué)應(yīng)用的SDK。OpenVINO支持各種設(shè)備上的加速,包括CPU、GPU和VPU上面的加速,我們?cè)诤竺孢€會(huì)提及這個(gè)內(nèi)容。
二,深度神經(jīng)網(wǎng)絡(luò)的關(guān)鍵概念
接下來(lái),我將介紹一些深度神經(jīng)網(wǎng)絡(luò)的關(guān)鍵概念。
深度神經(jīng)網(wǎng)絡(luò)最基本的組成單元是神經(jīng)元,我們?cè)谖墨I(xiàn)中一般稱作Node、Neuron或Perceptron。一個(gè)神經(jīng)元會(huì)對(duì)多個(gè)輸入進(jìn)行加權(quán)和的運(yùn)算,然后經(jīng)過(guò)一個(gè)激活函數(shù),最后輸出一個(gè)響應(yīng)結(jié)果。多個(gè)神經(jīng)元就組成了網(wǎng)絡(luò)的層,我們將神經(jīng)網(wǎng)絡(luò)的第一層稱為輸入層,一般用來(lái)加載輸入數(shù)據(jù),如一幅圖像。我們將神經(jīng)網(wǎng)絡(luò)的最后一層稱為輸出層,根據(jù)具體網(wǎng)絡(luò)結(jié)構(gòu)的不同,輸出層的含義也會(huì)不同。以分類網(wǎng)絡(luò)為例,輸出層的每個(gè)節(jié)點(diǎn)表示屬于某個(gè)類別的概率大小。我們將在輸入層和輸出層之間的層稱為隱層,所謂的深度神經(jīng)網(wǎng)絡(luò)就是隱層數(shù)大于1的神經(jīng)網(wǎng)絡(luò)。
接下來(lái)是網(wǎng)絡(luò)訓(xùn)練。我們可以把神經(jīng)網(wǎng)絡(luò)看成一個(gè)復(fù)雜的函數(shù),在這個(gè)函數(shù)里有許多參數(shù)是未知的,因此我們需要通過(guò)訓(xùn)練來(lái)確定這些參數(shù)。為了方便理解,我把訓(xùn)練大體分為四個(gè)步驟:第一步,選定訓(xùn)練參數(shù),如學(xué)習(xí)比例、批次大小、損失函數(shù)類型,初始化網(wǎng)絡(luò)權(quán)重;第二步、設(shè)置輸入數(shù)據(jù),然后進(jìn)行前向的網(wǎng)絡(luò)運(yùn)算;第三步、比較運(yùn)算結(jié)果和真實(shí)結(jié)果的差異;第四步、進(jìn)行反向傳播運(yùn)算,然后修改網(wǎng)絡(luò)參數(shù),再回到第二步直到差異足夠小,或者人為終止訓(xùn)練過(guò)程。雖然整個(gè)訓(xùn)練過(guò)程看起來(lái)比較復(fù)雜,但是深度學(xué)習(xí)框架會(huì)幫我們把這些事完成的,深度學(xué)習(xí)框架有Tensorflow、Caffe和Torch等。因此,我們只需要設(shè)計(jì)好網(wǎng)絡(luò)結(jié)構(gòu)、選定訓(xùn)練參數(shù),剩下的事就可以交給框架去做。
在通過(guò)足夠的訓(xùn)練之后,我們就可以確定所有的網(wǎng)絡(luò)參數(shù),那么這個(gè)復(fù)雜的函數(shù)就可以確定了。然后,我們輸入數(shù)據(jù)來(lái)通過(guò)深度學(xué)習(xí)庫(kù)計(jì)算函數(shù)結(jié)果的過(guò)程就叫推理。與訓(xùn)練相比,推理過(guò)程簡(jiǎn)單的多。上圖羅列了幾個(gè)使用了深度神經(jīng)網(wǎng)絡(luò)的計(jì)算機(jī)視覺(jué)應(yīng)用場(chǎng)景,如人臉識(shí)別、對(duì)象語(yǔ)義分割以及目標(biāo)檢測(cè)的應(yīng)用。
三,OpenCV深度學(xué)習(xí)模塊
從OpenCV3.3版本開(kāi)始,OpenCV加入了深度學(xué)習(xí)模塊,但這個(gè)模塊它只提供推理功能,而不涉及訓(xùn)練,與此同時(shí)它支持多種深度學(xué)習(xí)框架,比如Tensorflow,Caffe,Torch和Darknet。
聽(tīng)到這里,可能有的同學(xué)會(huì)問(wèn):“既然我們已經(jīng)有了Tensorflow、Caffe、Torch這些深度學(xué)習(xí)框架,為什么還要在OpenCV中再實(shí)現(xiàn)一個(gè)呢?這是不是在重復(fù)造輪子呢?”其實(shí)不是的,有下面幾個(gè)理由:第一、輕量,由于DNN模塊只實(shí)現(xiàn)了推理功能,它的代碼量、編譯運(yùn)行開(kāi)銷與其他深度學(xué)習(xí)框架比起來(lái)會(huì)少很多;第二、方便使用,DNN模塊提供了內(nèi)建的CPU和GPU加速且無(wú)須依賴第三方庫(kù),如果在之前項(xiàng)目使用了OpenCV,那么通過(guò)DNN模塊可以很方便的無(wú)縫的為原項(xiàng)目添加神經(jīng)網(wǎng)絡(luò)推理能力;第三、通用性,DNN模塊支持多種網(wǎng)絡(luò)模型格式,因此用戶無(wú)須額外進(jìn)行網(wǎng)絡(luò)模型的轉(zhuǎn)換就可以直接使用,同時(shí)它還支持多種運(yùn)算設(shè)備和操作系統(tǒng),比如CPU、GPU、VPU等,操作系統(tǒng)包括Linux、Windows、安卓和MacOS。
目前,OpenCV的DNN模塊支持40多種層的類型,基本涵蓋了常見(jiàn)的網(wǎng)絡(luò)運(yùn)算需求,而且新的類型也在不斷的加入當(dāng)中。
如上圖所示,這里列出的網(wǎng)絡(luò)架構(gòu)都是經(jīng)過(guò)了很好的測(cè)試。它們?cè)贠penCV中能很好支持的,基本涵蓋了常用的對(duì)象檢測(cè)和語(yǔ)義分割的類別,我們可以直接拿來(lái)使用。
接下來(lái)給大家介紹DNN模塊的架構(gòu)。如上圖所示,從而往下,第一層是語(yǔ)言綁定,它支持Python和Java,其中Python用的比較多,因?yàn)殚_(kāi)發(fā)起來(lái)會(huì)比較方便。此外,在第一層中還包括準(zhǔn)確度測(cè)試、性能測(cè)試以及一些示例程序。第二層是C++的API層,這屬于是原生的API,它的功能包括加載網(wǎng)絡(luò)模型、推理運(yùn)算以及獲取網(wǎng)絡(luò)輸出。第三層是實(shí)現(xiàn)層,它包括模型轉(zhuǎn)換器、DNN引擎、層實(shí)現(xiàn)等。模型轉(zhuǎn)換器負(fù)責(zé)將各種網(wǎng)絡(luò)模型格式轉(zhuǎn)換成DNN模塊內(nèi)部的表示,DNN引擎負(fù)責(zé)內(nèi)部網(wǎng)絡(luò)的組織和優(yōu)化,層實(shí)現(xiàn)是各種層運(yùn)算的具體實(shí)現(xiàn)過(guò)程。第四層是加速層,它包括CPU加速、GPU加速、Halide加速和新加入的Intel推理引擎加速。前三個(gè)均是DNN模塊的內(nèi)建實(shí)現(xiàn),無(wú)須外部依賴就直接可以使用。CPU加速用到了SSE和AVX指令以及大量的多線程元語(yǔ),而OpenCL加速是針對(duì)GPU進(jìn)行并行運(yùn)算的加速,這也是我們團(tuán)隊(duì)工作的主要內(nèi)容。Halide是一個(gè)實(shí)驗(yàn)性的實(shí)現(xiàn),并且性能一般,因此不建議使用。Intel推理引擎加速需要安裝OpenVINO庫(kù),它可以實(shí)現(xiàn)在CPU、GPU和VPU上的加速,在GPU上內(nèi)部會(huì)調(diào)用clDNN庫(kù)來(lái)做GPU上的加速,在CPU上內(nèi)部會(huì)調(diào)用MKL-DNN來(lái)做CPU加速,而Movidius主要是在VPU上使用的專用庫(kù)來(lái)進(jìn)行加速。
DNN模塊采用Backend和Target來(lái)管理各種加速方法。Backend分為三種類型:第一種是OpenCVBackend,這是OpenCV默認(rèn)的Backend;第二種是HalideBackend,第三種是推理引擎Backend。Target指的是最終的運(yùn)算設(shè)備,它包括四種類型,分別是CPU設(shè)備、OpenCL設(shè)備、OpenCL_FP16設(shè)備以及MYRIAD設(shè)備。強(qiáng)調(diào)一下,OpenCL和OpenCL_FP16實(shí)際上都是GPU設(shè)備,OpenCL_FP16設(shè)備指的是權(quán)重值的數(shù)據(jù)格式為16位浮點(diǎn)數(shù),OpenCL設(shè)備指的是權(quán)重值的數(shù)據(jù)格式為32位浮點(diǎn)數(shù)。MYRIAD設(shè)備是Movidius公司提供的VPU設(shè)備。我們通過(guò)Backend和Target的不同組合可以來(lái)決定具體的加速方法。舉個(gè)例子,如果你有Movidius的運(yùn)算棒,則可以通過(guò)SetPreferobleBackendAPI將Backend設(shè)置成Inference-NEGINE,通過(guò)SetPreferobleTargetAPI將Target設(shè)置成MYRIAD,然后你的網(wǎng)絡(luò)運(yùn)算將會(huì)在MYRIAD設(shè)備上進(jìn)行,而不再用任何的CPU資源。
除了上述的加速后端外,DNN模塊還做了一些網(wǎng)絡(luò)層面的優(yōu)化。由于在內(nèi)部使用了統(tǒng)一的網(wǎng)絡(luò)表示,網(wǎng)絡(luò)層級(jí)的優(yōu)化對(duì)DNN支持的所有格式的網(wǎng)絡(luò)模型都有好處。下面介紹兩種網(wǎng)絡(luò)層級(jí)的優(yōu)化方法:
一)層融合
第一種優(yōu)化方法是層融合的優(yōu)化。它是通過(guò)對(duì)網(wǎng)絡(luò)結(jié)構(gòu)的分析,把多個(gè)層合并到一起,從而降低網(wǎng)絡(luò)復(fù)雜度和減少運(yùn)算量。下面舉幾個(gè)具體的例子:
如上圖所示,在本例中黃色方框代表的是最終被融合掉的網(wǎng)絡(luò)層,在這種情況下,卷積層后面的BatchNorm層、Scale層和RelU層都被合并到了卷積層當(dāng)中。這樣一來(lái),四個(gè)層運(yùn)算最終變成了一個(gè)層運(yùn)算,這種結(jié)構(gòu)多出現(xiàn)在ResNet50的網(wǎng)絡(luò)架構(gòu)當(dāng)中。
如上圖所示,在本例中,網(wǎng)絡(luò)結(jié)構(gòu)將卷積層1和EltwiseLayer和RelULayer合并成一個(gè)卷積層,將卷積層2作為第一個(gè)卷積層新增的一個(gè)輸入。這樣一來(lái),原先的四個(gè)網(wǎng)絡(luò)層變成了兩個(gè)網(wǎng)絡(luò)層運(yùn)算,這種結(jié)構(gòu)也多出現(xiàn)于ResNet50的網(wǎng)絡(luò)架構(gòu)當(dāng)中。
如上圖所示,在本例中,這種網(wǎng)絡(luò)結(jié)構(gòu)是把三個(gè)層的輸出通過(guò)連接層連接之后輸入到后續(xù)層,這種情況可以把中間的連接層直接去掉,將三個(gè)網(wǎng)絡(luò)層輸出直接接到第四層的輸入上面,這種網(wǎng)絡(luò)結(jié)構(gòu)多出現(xiàn)SSD類型的網(wǎng)絡(luò)架構(gòu)當(dāng)中。
二)內(nèi)存復(fù)用
第二種優(yōu)化方式是內(nèi)存復(fù)用的優(yōu)化。深度神經(jīng)網(wǎng)絡(luò)運(yùn)算過(guò)程當(dāng)中會(huì)占用非常大量的內(nèi)存資源,一部分是用來(lái)存儲(chǔ)權(quán)重值,另一部分是用來(lái)存儲(chǔ)中間層的運(yùn)算結(jié)果。我們考慮到網(wǎng)絡(luò)運(yùn)算是一層一層按順序進(jìn)行的,因此后面的層可以復(fù)用前面的層分配的內(nèi)存。
上圖是一個(gè)沒(méi)有經(jīng)過(guò)優(yōu)化的內(nèi)存重用的運(yùn)行時(shí)的存儲(chǔ)結(jié)構(gòu),紅色塊代表的是分配出來(lái)的內(nèi)存,綠色塊代表的是一個(gè)引用內(nèi)存,藍(lán)色箭頭代表的是引用方向。數(shù)據(jù)流是自下而上流動(dòng)的,層的計(jì)算順序也是自下而上進(jìn)行運(yùn)算。每一層都會(huì)分配自己的輸出內(nèi)存,這個(gè)輸出被后續(xù)層引用為輸入。對(duì)內(nèi)存復(fù)用也有兩種方法:
第一種內(nèi)存復(fù)用的方法是輸入內(nèi)存復(fù)用。如上圖所示,如果我們的層運(yùn)算是一個(gè)in-place模式,那么我們無(wú)須為輸出分配內(nèi)存,直接把輸出結(jié)果寫(xiě)到輸入的內(nèi)存當(dāng)中即可。in-place模式指的是運(yùn)算結(jié)果可以直接寫(xiě)回到輸入而不影響其他位置的運(yùn)算,如每個(gè)像素點(diǎn)做一次Scale的運(yùn)算。類似于in-place模式的情況,就可以使用輸入內(nèi)存復(fù)用的方式。
第二種內(nèi)存復(fù)用的方法是后續(xù)層復(fù)用前面層的輸出。如上圖所示,在這個(gè)例子中,Layer3在運(yùn)算時(shí),Layer1和Layer2已經(jīng)完成了運(yùn)算。此時(shí),Layer1的輸出內(nèi)存已經(jīng)空閑下來(lái),因此,Layer3不需要再分配自己的內(nèi)存,直接引用Layer1的輸出內(nèi)存即可。由于深度神經(jīng)網(wǎng)絡(luò)的層數(shù)可以非常多,這種復(fù)用情景會(huì)大量的出現(xiàn),使用這種復(fù)用方式之后,網(wǎng)絡(luò)運(yùn)算的內(nèi)存占用量會(huì)下降30%~70%。
接下來(lái),我會(huì)為大家介紹一下我們團(tuán)隊(duì)在深度學(xué)習(xí)模塊中做的一些工作。
四,OpenCL加速
OpenCL的加速是一個(gè)內(nèi)建的加速實(shí)現(xiàn),它是可以直接使用而不依賴與外部加速庫(kù)的,只需安裝有OpenCL的運(yùn)行時(shí)環(huán)境即可。此外,它還支持32位浮點(diǎn)數(shù)據(jù)格式和16位浮點(diǎn)數(shù)據(jù)格式。如果我們想要使用OpenCL加速,只需要把Backend設(shè)置成OpenCV,把Target設(shè)置成OpenCL或者OpenCL_FP16即可。
在OpenCL的加速方案中,我們提供了一組經(jīng)過(guò)高度優(yōu)化的卷積運(yùn)算和auto-tuning方案,來(lái)為特定的GPU和卷積運(yùn)算找到最佳的卷積核。簡(jiǎn)單地說(shuō),auto-tuning方案針對(duì)每個(gè)卷積任務(wù),會(huì)選擇不同的子塊大小進(jìn)行運(yùn)算,然后選出用時(shí)最短的子塊大小來(lái)作為卷積和的配置。DNN模塊中內(nèi)置了一些已經(jīng)設(shè)好的卷積和配置,用戶也可以為自己的網(wǎng)絡(luò)和GPU重新運(yùn)行一次auto-tuning,從而找到最佳的卷積核。如果想要設(shè)置auto-tuning,則需要設(shè)置環(huán)境變量OpenCV_OCL4DNN_CONFIG_PATH,讓它指向一個(gè)可寫(xiě)的目錄。這樣一來(lái),DNN模塊就會(huì)把最佳的卷積核配置存儲(chǔ)在這個(gè)目錄下。注意,如果打開(kāi)了auto-tuing,那么第一次運(yùn)行某個(gè)網(wǎng)絡(luò)模型的時(shí)間就會(huì)比較長(zhǎng)。
對(duì)于OpenCL的驅(qū)動(dòng),我們建議使用Neo。Neo是開(kāi)源IntelGPU的OpenCL驅(qū)動(dòng),它支持Gen8以及Gen8之后的英特爾GPU。我們建議盡量使用最新的版本,根據(jù)我們的調(diào)試經(jīng)驗(yàn),越新的版本性能越好。
最后,上圖是一個(gè)CPU和GPU加速的對(duì)比圖,其中一列是OpenCL的加速,其中另一列是C++的加速。CPU是i7-6770、8核、2.6G,GPU是IrisProGraphics580的,這種CPU和GPU都算是比較強(qiáng)勁的配置。我們可以看到,OpenCL加速之后的運(yùn)算時(shí)間比CPU會(huì)短很多,但也不是所有的情況都是這樣的。對(duì)于不同的CPU,這個(gè)數(shù)據(jù)有所不同,大家可以通過(guò)上面的網(wǎng)站鏈接查看到在其他CPU配置下的CPU和GPU運(yùn)算時(shí)間的對(duì)比。
五,Vulkan后端
Vulkan后端是由我開(kāi)發(fā)的一個(gè)基于VulkanComputerShade的DNN加速方案,目前已經(jīng)合并到OpenCV的主分支,OpenCV4.0里就包含有Vulkanbackend,感興趣的同學(xué)可以通過(guò)上圖的鏈接了解一下技術(shù)細(xì)節(jié)。
如果要使用Vulkanbackend,將backend類型設(shè)置成VKCOM,將target設(shè)置成Vulkan即可。Vulkan后端可以讓DNN模塊在更多的平臺(tái)上使用到GPU的加速。例如,安卓系統(tǒng)中是不支持OpenCL的,但是它支持Vulkan,這種情況就可以通過(guò)Vulkanbackend來(lái)加速。
六,應(yīng)用實(shí)例
最后一部分,這是一個(gè)通過(guò)DNN開(kāi)發(fā)的用于對(duì)象檢測(cè)的端到端的應(yīng)用,下面我會(huì)分部分來(lái)詳細(xì)講解這些代碼段。
在這里使用的是Python的接口,采用Python語(yǔ)言來(lái)開(kāi)發(fā),模型使用的是MobileNetSSD模型。首先,引入OpenCV的Python包,代碼第2行、第4行、第5行則是指定MobileNetSSD的模型以及它的Graph描述文件。然后,設(shè)置輸入Image的大小為300*300,置信度閾值設(shè)置為0.5,第9行的均值是用來(lái)做圖像域處理的一個(gè)數(shù)值。第10行是可分類的類別,說(shuō)明我們的MobileNETSSD是一個(gè)可以對(duì)20個(gè)類別進(jìn)行分類的模型,我們也可以有97或者1000個(gè)類別的模型,但是那樣的模型會(huì)比較大。第16行則是打開(kāi)一個(gè)Camera設(shè)備采集圖像。
從第19行到第26行就是所有的DNN相關(guān)的代碼段,可以看到使用起來(lái)是非常簡(jiǎn)單的。第19行是加載網(wǎng)絡(luò)模型,并返回一個(gè)網(wǎng)絡(luò)對(duì)象。從第20行開(kāi)始進(jìn)入一個(gè)while循環(huán),逐幀處理攝像頭讀入的數(shù)據(jù)。第22行是讀入的數(shù)據(jù),第23行是對(duì)這個(gè)讀入的Image做Resize,讓它符合網(wǎng)絡(luò)模型對(duì)輸入數(shù)據(jù)的大小要求。第24行是調(diào)用DNN模塊的BlobFromImageAPI對(duì)輸入的Image做預(yù)處理,這里主要是對(duì)輸入數(shù)據(jù)做規(guī)則化處理,即先減均值,再乘以一個(gè)Scale。這些都是MobileNETSSD網(wǎng)絡(luò)在訓(xùn)練中引入的均值和Scale,在推理中也需要把它用作輸入Image的預(yù)處理,我們將處理好的數(shù)據(jù)稱為blob。在第25行把這個(gè)blob設(shè)置為網(wǎng)絡(luò)的輸入,第26行來(lái)調(diào)用網(wǎng)絡(luò)的Forward做推理預(yù)算,然后得到最終的輸出結(jié)果Detections,Detections記錄了在這一幀圖像中檢測(cè)出來(lái)的所有對(duì)象,并且每個(gè)對(duì)象會(huì)以一個(gè)Vector的形式來(lái)描述。
接下來(lái),在這個(gè)循環(huán)中對(duì)每一個(gè)對(duì)象進(jìn)行可視化處理,也就是把檢測(cè)出來(lái)的對(duì)象描繪在原圖像上。在第47行是取出對(duì)象的置信值與之前設(shè)置的閾值進(jìn)行比較,如果超過(guò)了閾值,我們就判定它是一個(gè)可信的對(duì)象,將其繪制到原圖上面。接下來(lái)的代碼段就是繪制對(duì)象的代碼段以及繪制對(duì)象類別的代碼段,最后是將繪制好對(duì)象方框的原圖顯示出來(lái),隨后整個(gè)程序結(jié)束。在OpenCV的代碼庫(kù)當(dāng)中有許多基于DNN的示例程序,包括C++、Python,大家感興趣則可以在上面的鏈接中去看一下。
-
計(jì)算機(jī)視覺(jué)
+關(guān)注
關(guān)注
8文章
1696瀏覽量
45930 -
OpenCV
+關(guān)注
關(guān)注
30文章
628瀏覽量
41274 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5493瀏覽量
120999
原文標(biāo)題:OpenCV中那些深度學(xué)習(xí)模塊
文章出處:【微信號(hào):livevideostack,微信公眾號(hào):LiveVideoStack】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論