前面我們了解OpenVINO 如何部署圖像分類網(wǎng)絡(luò)ResNet,本文我們將會(huì)學(xué)習(xí)OpenVINO 中對(duì)象檢測(cè)網(wǎng)絡(luò)的部署與推理應(yīng)用。說到對(duì)象檢測(cè)網(wǎng)絡(luò),我們首先需要理解兩個(gè)概念:對(duì)象檢測(cè)與對(duì)象檢測(cè)網(wǎng)絡(luò)。
SSD對(duì)象檢測(cè)模型
對(duì)象檢測(cè)是計(jì)算機(jī)視覺核心任務(wù)之一,也是最常見與應(yīng)用最廣泛的視覺場(chǎng)景。OpenVINO 已經(jīng)提供了以下通用場(chǎng)景下的對(duì)象檢測(cè)包括人臉檢測(cè)、行人檢測(cè)、物體檢測(cè)、車輛檢測(cè)、車牌檢測(cè)等,一個(gè)圖像對(duì)象檢測(cè)顯示示意圖如下:
圖-1(來自SSD論文)
相比圖像分類,對(duì)象檢測(cè)多了每個(gè)對(duì)象位置信息,所以簡(jiǎn)單的認(rèn)為對(duì)象檢測(cè)=圖像分類+Box位置信息。第一個(gè)深度學(xué)習(xí)相關(guān)的對(duì)象檢測(cè)網(wǎng)絡(luò)正是基于這樣思想的RCNN模型,但是它的缺點(diǎn)是無法實(shí)時(shí),所以2015年底有人提出了一個(gè)實(shí)時(shí)對(duì)象檢測(cè)網(wǎng)絡(luò)Single Shot MultiBox Detector縮寫為SSD。它的模型結(jié)構(gòu)如下:
圖2(來自SSD論文)
圖2中SSD對(duì)象檢測(cè)網(wǎng)絡(luò)簡(jiǎn)單說可以分為三個(gè)部分:
- 基礎(chǔ)網(wǎng)絡(luò)(backbone) 這里為VGG16
- 特征提取Neck,構(gòu)建多尺度特征
- 檢測(cè)頭 – 非最大抑制與輸出
OpenVINO 中模型庫(kù)自帶預(yù)訓(xùn)練的人臉檢測(cè)網(wǎng)絡(luò)有很多,分別針對(duì)不同的應(yīng)用場(chǎng)景與輸入分辨率。這里我們以face-detection-0202人臉檢測(cè)模型為例說明,它是一個(gè)MobileNetV2作為基礎(chǔ)網(wǎng)絡(luò)的SSD對(duì)象檢測(cè)模型,模型支持的輸入圖像大小與格式如下:
NCHW=1x3x384x384其中
N表示圖像數(shù)目,這里為1
C表示輸入圖像通道數(shù)目,這里彩色圖像為3
H表示圖像高度
W表示圖像寬度
期望的圖像通道順序:BGR
圖-3
模型推理計(jì)算得輸出格式為:
1x1xNx7其中
N表示檢測(cè)到的對(duì)象數(shù)目
7表示[image_id, label, conf, x_min, y_min, x_max, y_max]這七個(gè)值,其中
Image_id 表示圖像編號(hào),這個(gè)輸入的是一張圖像,base為0
Label 表示標(biāo)簽,跟數(shù)據(jù)集的label_map文本文件相關(guān),根據(jù)標(biāo)簽編號(hào)可以查找標(biāo)簽文本名
Conf 表示對(duì)象的置信度,取值范圍在0~1之間,值越大表示置信程度越高
x_min, y_min, x_max, y_max 四個(gè)值對(duì)象位置信息,分別是左上角與有下角的坐標(biāo)
該模型的相關(guān)性能參數(shù)如下:
圖-4
從上面我們可以知道模型來自Pytorch訓(xùn)練生成。
OpenVINO基于SSD模型實(shí)時(shí)人臉檢測(cè)
現(xiàn)在我們已經(jīng)了解SSD模型的基本網(wǎng)絡(luò)結(jié)構(gòu),OpenVINO 自帶SSD人臉檢測(cè)模型face-detection-0202的輸入與輸出相關(guān)格式與參數(shù)細(xì)節(jié)信息,這里我們就基于該模型使用OpenVINO 中的推理引擎模型實(shí)現(xiàn)一個(gè)實(shí)時(shí)人臉檢測(cè)應(yīng)用,根據(jù)之前的內(nèi)容,我們首先需要加載模型,相關(guān)代碼如下:
// 加載檢測(cè)模型
auto network = ie.ReadNetwork(model_xml, model_bin);
其中
model_xml表示face-detection-0202模型文件
model_bin表示face-detection-0202權(quán)重文件
然后設(shè)置模型的輸入與輸出相關(guān)的格式,代碼如下:
// 請(qǐng)求網(wǎng)絡(luò)輸入與輸出信息
InferenceEngine::InputsDataMap input_info(network.getInputsInfo());
InferenceEngine::OutputsDataMap output_info(network.getOutputsInfo());
// 設(shè)置輸入格式
for (auto &item : input_info) {
auto input_data = item.second;
input_data->setPrecision(Precision::U8);
input_data->setLayout(Layout::NCHW);
}
printf("get it ");
// 設(shè)置輸出格式
for (auto &item : output_info) {
auto output_data = item.second;
output_data->setPrecision(Precision::FP32);
}
加載可執(zhí)行網(wǎng)絡(luò),創(chuàng)建推理請(qǐng)求對(duì)象實(shí)例,代碼如下:
// 創(chuàng)建可執(zhí)行網(wǎng)絡(luò)對(duì)象
auto executable_network = ie.LoadNetwork(network, "CPU");
// 請(qǐng)求推斷圖
auto infer_request = executable_network.CreateInferRequest();
設(shè)置推理輸入圖像數(shù)據(jù),轉(zhuǎn)換為NCHW格式的blob數(shù)據(jù),代碼如下:
/** Getting input blob **/
auto input = infer_request.GetBlob(input_name);
size_t num_channels = input->getTensorDesc().getDims()[1];
size_t h = input->getTensorDesc().getDims()[2];
size_t w = input->getTensorDesc().getDims()[3];
size_t image_size = h*w;
Mat blob_image;
resize(src, blob_image, Size(w, h));
// NCHW
unsigned char* data = static_cast
for (size_t row = 0; row < h; row++) {
for (size_t col = 0; col < w; col++) {
for (size_t ch = 0; ch < num_channels; ch++) {
data[image_size*ch + row*w + col] = blob_image.at
}
}
}
預(yù)測(cè)與解析輸出結(jié)果,代碼如下:
// 執(zhí)行預(yù)測(cè)
infer_request.Infer();
// 處理輸出結(jié)果
for (auto &item : output_info) {
auto output_name = item.first;
// 獲取輸出數(shù)據(jù)
auto output = infer_request.GetBlob(output_name);
const float* detection = static_cast
const SizeVector outputDims = output->getTensorDesc().getDims();
const int maxProposalCount = outputDims[2];
const int objectSize = outputDims[3];
// 解析輸出結(jié)果
for (int curProposal = 0; curProposal < maxProposalCount; curProposal++) {
float label = detection[curProposal * objectSize + 1];
float confidence = detection[curProposal * objectSize + 2];
float xmin = detection[curProposal * objectSize + 3] * image_width;
float ymin = detection[curProposal * objectSize + 4] * image_height;
float xmax = detection[curProposal * objectSize + 5] * image_width;
float ymax = detection[curProposal * objectSize + 6] * image_height;
if (confidence > 0.5) {
printf("label id : %d ", static_cast
Rect rect;
rect.x = static_cast
rect.y = static_cast
rect.width = static_cast
rect.height = static_cast
putText(src, "OpenVINO-2021R02", Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);
rectangle(src, rect, Scalar(0, 255, 255), 2, 8, 0);
}
std::cout << std::endl;
}
}
imshow("OpenVINO+SSD人臉檢測(cè)", src);
最終顯示結(jié)果如下:
圖-5
總結(jié)
本文我們完成了OpenVINO 人臉檢測(cè)模型的推理調(diào)用演示,關(guān)鍵知識(shí)點(diǎn)在于模型的輸入與輸出格式,以及推理以后的模型輸出數(shù)據(jù)的解析方式。到這里大家希望借助OpenVINO 實(shí)現(xiàn)一個(gè)視頻版本的人臉檢測(cè),沒關(guān)系,下一次我們將來完成這樣的事情……
編輯:jq
-
SSD
+關(guān)注
關(guān)注
21文章
2863瀏覽量
117459 -
代碼
+關(guān)注
關(guān)注
30文章
4790瀏覽量
68654 -
人臉檢測(cè)
+關(guān)注
關(guān)注
0文章
80瀏覽量
16464 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5503瀏覽量
121206 -
resnet
+關(guān)注
關(guān)注
0文章
12瀏覽量
3171
原文標(biāo)題:OpenVINO? + SSD 實(shí)時(shí)對(duì)象檢測(cè)
文章出處:【微信號(hào):英特爾物聯(lián)網(wǎng),微信公眾號(hào):英特爾物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論