0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

node.js在訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)模型識(shí)別圖像中物體的方法

zhKF_jqr_AI ? 2018-04-06 13:11 ? 次閱讀

編者按:opencv4nodejs及face-recognition.js維護(hù)者Vincent Mühler介紹了如何在Node.js環(huán)境下使用訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)模型識(shí)別圖像中的物體。

今天我們將看看Node.js的OpenCV深度神經(jīng)網(wǎng)絡(luò)模塊。

如果你希望釋放神經(jīng)網(wǎng)絡(luò)的魔力,來(lái)辨識(shí)和分類(lèi)圖像中的物體,卻對(duì)深度學(xué)習(xí)是如何工作的毫無(wú)頭緒(像我一樣),更不知道如何創(chuàng)建和訓(xùn)練神經(jīng)網(wǎng)絡(luò),那么本文正適合你!

所以我們今天將創(chuàng)建什么?

在這一篇教程中,我們將了解如何通過(guò)OpenCV的DNN模塊,從Tensorflow和Caffe加載預(yù)訓(xùn)練的模型,然后我們將深入兩個(gè)基于Node.js和OpenCV進(jìn)行物體識(shí)別的例子。

首先我們將使用Tensorflow的Inception模型來(lái)辨識(shí)圖像中的物體,之后我們將使用COCO SSD模型檢測(cè)和辨識(shí)同一圖像中的多個(gè)不同物體。

你可以在我的github倉(cāng)庫(kù)上找到樣例代碼:justadudewhohacks/opencv4nodejs

Tensorflow Inception

訓(xùn)練過(guò)的Tensorflow Inception模型可以辨別約1000個(gè)分類(lèi)的物體。如果你將圖像傳入網(wǎng)絡(luò),它將給出圖像中的物體的每個(gè)分類(lèi)的似然。

要在OpenCV下使用Inception模型,我們需要加載二進(jìn)制文件tensorflow_inception_graph.pb以及分類(lèi)名稱(chēng)列表imagenet_comp_graph_label_strings.txt。你可以下載inception5h.zip并解壓以獲得這些文件(下面的代碼內(nèi)有下載鏈接):

// 替換路徑為你解壓縮inception模型的路徑

const inceptionModelPath = '../data/dnn/tf-inception'

const modelFile = path.resolve(inceptionModelPath, 'tensorflow_inception_graph.pb');

const classNamesFile = path.resolve(inceptionModelPath, 'imagenet_comp_graph_label_strings.txt');

if (!fs.existsSync(modelFile) || !fs.existsSync(classNamesFile)) {

console.log('退出: 找不到inception模型');

console.log('從以下網(wǎng)址下載模型: https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip');

return;

}

// 讀取classNames(分類(lèi)名稱(chēng)),然后在數(shù)組中儲(chǔ)存它們

const classNames = fs.readFileSync(classNamesFile).toString().split(" ");

// 從modelFile初始化tensorflow inception模塊

const net = cv.readNetFromTensorflow(modelFile);

分類(lèi)圖像中的物品

為了分類(lèi)圖像中的物品,我們將編寫(xiě)以下幫助函數(shù):

const classifyImg = (img) => {

// inception模型使用224 x 224 圖像,

// 因此我們調(diào)整輸入圖像的大小,

// 并使用白像素補(bǔ)齊圖像

const maxImgDim = 224;

const white = new cv.Vec(255, 255, 255);

const imgResized = img.resizeToMax(maxImgDim).padToSquare(white);

// 網(wǎng)絡(luò)接受blob作為輸入

const inputBlob = cv.blobFromImage(imgResized);

net.setInput(inputBlob);

// 前向傳播輸入至整個(gè)網(wǎng)絡(luò),

// 將返回包含每個(gè)分類(lèi)的置信度的1xN矩陣分類(lèi)結(jié)果

const outputBlob = net.forward();

// 找到大于最小置信度的所有標(biāo)簽

const minConfidence = 0.05;

const locations =

outputBlob

.threshold(minConfidence, 1, cv.THRESH_BINARY)

.convertTo(cv.CV_8U)

.findNonZero();

const result =

locations.map(pt => ({

confidence: parseInt(outputBlob.at(0, pt.x) * 100) / 100,

className: classNames[pt.x]

}))

// 根據(jù)置信度排序

.sort((r0, r1) => r1.confidence - r0.confidence)

.map(res => `${res.className} (${res.confidence})`);

return result;

}

這一函數(shù)做了這些事:

準(zhǔn)備輸入圖像

Tensorflow Inception網(wǎng)絡(luò)接受224x224大小的輸入圖像。因此我們調(diào)整圖像大小,使其最大邊的大小為224,然后用白像素補(bǔ)齊。

讓圖像穿過(guò)網(wǎng)絡(luò)

我們可以直接從圖像創(chuàng)建blob,然后調(diào)用net.forward()前向傳播輸入,然后獲取輸出blob.

從輸出blob提取結(jié)果

為了通用性,輸出blob的表達(dá)形式直接是矩陣(cv.Mat),而它的維度取決于模型。在Inception下這很簡(jiǎn)單。blob不過(guò)是一個(gè)1xN矩陣(其中N等于分類(lèi)數(shù)),描述了所有分類(lèi)的概率分布。每個(gè)條目為一個(gè)浮點(diǎn)數(shù),表示相應(yīng)分類(lèi)的置信度。所有條目相加,總和為1.0(100%)。

我們想仔細(xì)看看圖像可能性最大的分類(lèi),因此我們查看所有置信度大于minConfidence(這個(gè)例子中是5%)。最后,我們根據(jù)置信度排序結(jié)果,并返回className、confidence對(duì)。

測(cè)試

現(xiàn)在我們將讀取一些我們希望網(wǎng)絡(luò)辨識(shí)的樣本數(shù)據(jù):

const testData = [

{

image: '../data/banana.jpg',

label: 'banana'

},

{

image: '../data/husky.jpg',

label: 'husky'

},

{

image: '../data/car.jpeg',

label: 'car'

},

{

image: '../data/lenna.png',

label: 'lenna'

}

];

testData.forEach((data) => {

const img = cv.imread(data.image);

console.log('%s: ', data.label);

const predictions = classifyImg(img);

predictions.forEach(p => console.log(p));

console.log();

cv.imshowWait('img', img);

});

輸出為:(你可以參考本文開(kāi)頭的圖片)

banana:

banana (0.95)

husky:

Siberian husky (0.78)

Eskimo dog (0.21)

car:

sports car (0.57)

racer (0.12)

lenna:

sombrero (0.34)

cowboy hat (0.3)

很有趣。我們得到了愛(ài)基斯摩犬和香蕉圖像非常準(zhǔn)確的描述。對(duì)于汽車(chē)圖像而言,汽車(chē)的具體類(lèi)別不太準(zhǔn),但模型確實(shí)辨識(shí)出了圖像中的汽車(chē)。當(dāng)然,網(wǎng)絡(luò)不可能在無(wú)限的分類(lèi)上進(jìn)行訓(xùn)練,因此它沒(méi)有為最后一張圖像返回“婦女”描述。然而,它確實(shí)辨識(shí)出了帽子。

COCO SSD

好,模型表現(xiàn)不錯(cuò)。但是我們?nèi)绾翁幚戆鄠€(gè)物體的圖像呢?為了辨識(shí)單一圖像中的多個(gè)物體,我們將利用單圖多盒檢測(cè)器(Single Shot Multibox Detector, SSD)。在我們的第二個(gè)例子中,我們將查看一個(gè)在COCO(Common Object in Context)數(shù)據(jù)集上訓(xùn)練的SSD模型。我們使用的這一模型在84個(gè)不同分類(lèi)上訓(xùn)練過(guò)。

這一模型來(lái)自Caffe,因此我們將加載二進(jìn)制文件VGG_coco_SSD_300x300_iter_400000.caffemodel,以及protoxt文件deploy.prototxt:

// 替換路徑為你解壓縮coco-SSD模型的路徑

const ssdcocoModelPath = '../data/dnn/coco-SSD_300x300'

const prototxt = path.resolve(ssdcocoModelPath, 'deploy.prototxt');

const modelFile = path.resolve(ssdcocoModelPath, 'VGG_coco_SSD_300x300_iter_400000.caffemodel');

if (!fs.existsSync(prototxt) || !fs.existsSync(modelFile)) {

console.log('退出: 找不到ssdcoco模型');

console.log('從以下網(wǎng)址下載模型 https://drive.google.com/file/d/0BzKzrI_SkD1_dUY1Ml9GRTFpUWc/view');

return;

}

// 從prototxt和modelFile初始化ssdcoco模型

const net = cv.readNetFromCaffe(prototxt, modelFile);

基于COCO分類(lèi)

我們的分類(lèi)函數(shù)和基于Inception的分類(lèi)函數(shù)幾乎一樣,不過(guò)這次輸入將是300x300的圖像,而輸出將是1x1xNx7矩陣。

const classifyImg = (img) => {

const white = new cv.Vec(255, 255, 255);

// ssdcoco模型接受300 x 300圖像

const imgResized = img.resize(300, 300);

// 網(wǎng)絡(luò)接受blob作為輸入

const inputBlob = cv.blobFromImage(imgResized);

net.setInput(inputBlob);

// 前向傳播輸入至整個(gè)網(wǎng)絡(luò),

// 將返回1x1xNxM矩陣作為分類(lèi)結(jié)果

let outputBlob = net.forward();

// 提取NxM矩陣

outputBlob = outputBlob.flattenFloat(outputBlob.sizes[2], outputBlob.sizes[3]);

const results = Array(outputBlob.rows).fill(0)

.map((res, i) => {

const className = classNames[outputBlob.at(i, 1)];

const confidence = outputBlob.at(i, 2);

const topLeft = new cv.Point(

outputBlob.at(i, 3) * img.cols,

outputBlob.at(i, 6) * img.rows

);

const bottomRight = new cv.Point(

outputBlob.at(i, 5) * img.cols,

outputBlob.at(i, 4) * img.rows

);

return ({

className,

confidence,

topLeft,

bottomRight

})

});

return results;

};

我不是很清楚為何輸出是1x1xNx7矩陣,不過(guò)我們實(shí)際上只關(guān)心Nx7部分。我們可以使用flattenFloat工具函數(shù)映射第三、第四維至2D矩陣。與Inception輸出矩陣相比,這次N不對(duì)應(yīng)每個(gè)分類(lèi),而是檢測(cè)到的每個(gè)物體。另外,每個(gè)物體對(duì)應(yīng)7個(gè)條目。

為什么是7個(gè)條目?

記住,這里我們遇到的問(wèn)題和之前有點(diǎn)不一樣。我們想要檢測(cè)單張圖像中的多個(gè)物體,因此我們不可能僅僅給出每個(gè)分類(lèi)的置信度。我們實(shí)際上想要得到的是一個(gè)指示每個(gè)物體在圖中的位置的矩形。7個(gè)條目分別為:

我其實(shí)毫無(wú)頭緒

物體的分類(lèi)標(biāo)簽

分類(lèi)的置信度

矩形左端的x

矩形底部的y

矩形右端的x

矩形頂部的y

輸出矩陣給了我們不少關(guān)于結(jié)果的信息,這看起來(lái)相當(dāng)整潔。我們同樣可以根據(jù)置信度再次過(guò)濾結(jié)果,并為每個(gè)辨識(shí)出的物體在圖像中繪制邊框。

看看它的效果!

出于行文的簡(jiǎn)潔,我將跳過(guò)繪制矩形的代碼,以及其他可視化的代碼。如果你想知道具體是怎么做的,可以訪問(wèn)前面提到的github倉(cāng)庫(kù)。

讓我們傳入一張汽車(chē)圖像到網(wǎng)絡(luò),然后過(guò)濾結(jié)果,看看是否檢測(cè)到了car分類(lèi):

很棒!下面提高一下難度。讓我們?cè)囅隆粡堅(jiān)绮妥溃?/p>

很不錯(cuò)!

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴

原文標(biāo)題:當(dāng)Node.js遇上OpenCV深度神經(jīng)網(wǎng)絡(luò)

文章出處:【微信號(hào):jqr_AI,微信公眾號(hào):論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    當(dāng)訓(xùn)練好神經(jīng)網(wǎng)絡(luò)用于應(yīng)用的時(shí)候,權(quán)值是不是不能變了?

    當(dāng)訓(xùn)練好神經(jīng)網(wǎng)絡(luò)用于應(yīng)用的時(shí)候,權(quán)值是不是不能變了????就是已經(jīng)訓(xùn)練好神經(jīng)網(wǎng)絡(luò)是不是相當(dāng)于得到一個(gè)公式了,權(quán)值不能變了
    發(fā)表于 10-24 21:55

    請(qǐng)問(wèn)Labveiw如何調(diào)用matlab訓(xùn)練好神經(jīng)網(wǎng)絡(luò)模型呢?

    matlab訓(xùn)練好了一個(gè)神經(jīng)網(wǎng)絡(luò)模型,想在labview調(diào)用,請(qǐng)問(wèn)應(yīng)該怎么做呢?或者la
    發(fā)表于 07-05 17:32

    MATLAB訓(xùn)練好神經(jīng)網(wǎng)絡(luò)移植到STM32F407上

    MATLAB中進(jìn)行了神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練,然后將訓(xùn)練好模型的閾值和權(quán)值導(dǎo)出來(lái),移植到STM32
    發(fā)表于 06-16 11:14

    基于深度神經(jīng)網(wǎng)絡(luò)的激光雷達(dá)物體識(shí)別系統(tǒng)

    的激光雷達(dá)物體識(shí)別技術(shù)一直難以嵌入式平臺(tái)上實(shí)時(shí)運(yùn)行。經(jīng)緯恒潤(rùn)經(jīng)過(guò)潛心研發(fā),攻克了深度神經(jīng)網(wǎng)絡(luò)嵌入式平臺(tái)部署所面臨的算子定制與加速、量化策
    發(fā)表于 12-21 07:59

    圖像預(yù)處理和改進(jìn)神經(jīng)網(wǎng)絡(luò)推理的簡(jiǎn)要介紹

    為提升識(shí)別準(zhǔn)確率,采用改進(jìn)神經(jīng)網(wǎng)絡(luò),通過(guò)Mnist數(shù)據(jù)集進(jìn)行訓(xùn)練。整體處理過(guò)程分為兩步:圖像預(yù)處理和改進(jìn)神經(jīng)網(wǎng)絡(luò)推理。
    發(fā)表于 12-23 08:07

    卷積神經(jīng)網(wǎng)絡(luò)模型發(fā)展及應(yīng)用

    network,DBN)[24], 從此拉開(kāi)了深度學(xué)習(xí)大幕。隨著深度學(xué)習(xí)理論的研究和發(fā)展,研究人員提 出了一系列卷積神經(jīng)網(wǎng)絡(luò)模型。為了比較不同模型 的質(zhì)量,收集并整理了文獻(xiàn)
    發(fā)表于 08-02 10:39

    卷積神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介:什么是機(jī)器學(xué)習(xí)?

    ,用于描述網(wǎng)絡(luò)的方程也有 32 個(gè)偏差和 32 個(gè)權(quán)重。CIFAR神經(jīng)網(wǎng)絡(luò)是一種廣泛用于圖像識(shí)別任務(wù)的CNN。它由兩種主要類(lèi)型的層組成:卷積層和池化層,它們
    發(fā)表于 02-23 20:11

    node.jsjs要點(diǎn)總結(jié)

    (Non-blocking)或異步I/O 由于Node.js一個(gè)服務(wù)器端框架,所以它主要工作之一是處理瀏覽器請(qǐng)求。傳統(tǒng)的I/O系統(tǒng),每個(gè)請(qǐng)求的發(fā)出都是在上一請(qǐng)求到達(dá)之后才發(fā)出的。所以這被稱(chēng)為阻塞
    發(fā)表于 10-13 10:39 ?0次下載

    介紹Node.js應(yīng)用全鏈路信息獲取的方法

    這種技術(shù),就是Node.js應(yīng)用全鏈路追蹤。它是 Node.js 涉及到復(fù)雜服務(wù)端業(yè)務(wù)場(chǎng)景,必不可少的技術(shù)保障。
    的頭像 發(fā)表于 02-10 11:21 ?782次閱讀

    node.js實(shí)戰(zhàn)源碼

    node.js實(shí)戰(zhàn)源碼
    發(fā)表于 05-16 18:06 ?1次下載

    卷積神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練步驟

    卷積神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練步驟? 卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network, CNN)是一種常用的深度學(xué)習(xí)算法,廣泛應(yīng)用于
    的頭像 發(fā)表于 08-21 16:42 ?2091次閱讀

    卷積神經(jīng)網(wǎng)絡(luò)如何識(shí)別圖像

    多層卷積層、池化層和全連接層。CNN模型通過(guò)訓(xùn)練識(shí)別并學(xué)習(xí)高度復(fù)雜的圖像模式,對(duì)于識(shí)別物體和進(jìn)行
    的頭像 發(fā)表于 08-21 16:49 ?2166次閱讀

    神經(jīng)網(wǎng)絡(luò)圖像識(shí)別的應(yīng)用

    隨著人工智能技術(shù)的飛速發(fā)展,神經(jīng)網(wǎng)絡(luò)圖像識(shí)別領(lǐng)域的應(yīng)用日益廣泛。神經(jīng)網(wǎng)絡(luò)以其強(qiáng)大的特征提取和分類(lèi)能力,為圖像識(shí)別帶來(lái)了革命性的進(jìn)步。本文將
    的頭像 發(fā)表于 07-01 14:19 ?1026次閱讀

    MATLAB如何使用訓(xùn)練好網(wǎng)絡(luò)

    引言 本文中,我們將探討如何在MATLAB中使用訓(xùn)練好神經(jīng)網(wǎng)絡(luò)。神經(jīng)網(wǎng)絡(luò)是一種強(qiáng)大的機(jī)器學(xué)習(xí)技術(shù),廣泛應(yīng)用于圖像識(shí)別、自然語(yǔ)言處理、預(yù)測(cè)
    的頭像 發(fā)表于 07-03 10:06 ?1646次閱讀

    怎么對(duì)神經(jīng)網(wǎng)絡(luò)重新訓(xùn)練

    重新訓(xùn)練神經(jīng)網(wǎng)絡(luò)是一個(gè)復(fù)雜的過(guò)程,涉及到多個(gè)步驟和考慮因素。 引言 神經(jīng)網(wǎng)絡(luò)是一種強(qiáng)大的機(jī)器學(xué)習(xí)模型,廣泛應(yīng)用于圖像識(shí)別、自然語(yǔ)言處理、語(yǔ)音
    的頭像 發(fā)表于 07-11 10:25 ?695次閱讀

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品