#
include
<algorithm
>
#
include
<fstream
>
#
include
<iomanip
>
#
include
<vector
>
#
include
<string
>
#
include
<chrono
>
#
include
<memory
>
#
include
<utility
>
#
include
<format_reader_ptr.h
>
#
include
<inference_engine.hpp
>
#
include
<ext_list.hpp
>
#
include
<samples
/slog.hpp
>
#
include
<samples
/ocv_common.hpp
>
#
include
"segmentation_demo.h"
using
namespace InferenceEngine;
using
namespace std;
using
namespace cv;
//從圖片中得到車和車牌(這裏沒有輸出模型的定位結果,若是須要能夠適當修改)
vector
< pair
<Mat, Mat
>
> GetCarAndPlate(Mat src)
{
vector
<pair
<Mat, Mat
>> resultVector;
// 模型準備
InferencePlugin plugin(PluginDispatcher().getSuitablePlugin(TargetDevice
:
:eCPU));
plugin.AddExtension(std
:
:make_shared
<Extensions
:
:Cpu
:
:CpuExtensions
>());
//Extension,useful
//讀取模型(xml和bin
CNNNetReader networkReader;
networkReader.ReadNetwork(
"E:/OpenVINO_modelZoo/vehicle-license-plate-detection-barrier-0106.xml");
networkReader.ReadWeights(
"E:/OpenVINO_modelZoo/vehicle-license-plate-detection-barrier-0106.bin");
CNNNetwork network
= networkReader.getNetwork();
network.setBatchSize(
1);
// 輸入輸出準備
InputsDataMap inputInfo(network.getInputsInfo());
//得到輸入信息
if (inputInfo.size()
!=
1)
throw std
:
:logic_error(
"錯誤,該模型應該爲單輸入");
string inputName
= inputInfo.begin()
-
>first;
OutputsDataMap outputInfo(network.getOutputsInfo());
//得到輸出信息
DataPtr
& _output
= outputInfo.begin()
-
>second;
const SizeVector outputDims
= _output
-
>getTensorDesc().getDims();
string firstOutputName
= outputInfo.begin()
-
>first;
int maxProposalCount
= outputDims[
2];
int objectSize
= outputDims[
3];
if (objectSize
!=
7) {
throw std
:
:logic_error(
"Output should have 7 as a last dimension");
}
if (outputDims.size()
!=
4) {
throw std
:
:logic_error(
"Incorrect output dimensions for SSD");
}
_output
-
>setPrecision(Precision
:
:FP32);
_output
-
>setLayout(Layout
:
:NCHW);
// 模型讀取和推斷
ExecutableNetwork executableNetwork
= plugin.LoadNetwork(network, {});
InferRequest infer_request
= executableNetwork.CreateInferRequest();
Blob
:
:Ptr lrInputBlob
= infer_request.GetBlob(inputName);
//data這個名字是我看出來的,實際上這裏能夠更統一一些
matU8ToBlob
<float_t
>(src, lrInputBlob,
0);
//重要的轉換函數,第3個參數是batchSize,應該是本身+1的
infer_request.Infer();
// --------------------------- 8. 處理結果-------------------------------------------------------
const
float
*detections
= infer_request.GetBlob(firstOutputName)
-
>buffer().as
<
float
*
>();
int i_car
=
0;
int i_plate
=
0;
for (
int i
=
0; i
<
200; i
++)
{
float confidence
= detections[i
* objectSize
+
2];
float x_min
=
static_cast
<
int
>(detections[i
* objectSize
+
3]
* src.cols);
float y_min
=
static_cast
<
int
>(detections[i
* objectSize
+
4]
* src.rows);
float x_max
=
static_cast
<
int
>(detections[i
* objectSize
+
5]
* src.cols);
float y_max
=
static_cast
<
int
>(detections[i
* objectSize
+
6]
* src.rows);
Rect rect
= cv
:
:Rect(cv
:
:Point(x_min, y_min), cv
:
:Point(x_max, y_max));
if (confidence
>
0.
5)
{
if (rect.width
>
150)
//車輛
{
Mat roi
= src(rect);
pair
<Mat, Mat
> aPair;
aPair.first
= roi.clone();
resultVector.push_back(aPair);
i_car
++;
}
else
//車牌
{
Mat roi
= src(rect);
resultVector[i_plate].second
= roi.clone();
i_plate
++;
}
}
}
return resultVector;
}
//從車的圖片中識別車型
pair
<string,string
> GetCarAttributes(Mat src)
{
pair
<string, string
> resultPair;
// --------------------------- 1.爲IE準備插件-------------------------------------
InferencePlugin plugin(PluginDispatcher().getSuitablePlugin(TargetDevice
:
:eCPU));
printPluginVersion(plugin, std
:
:cout);
//正確回顯表示成功
plugin.AddExtension(std
:
:make_shared
<Extensions
:
:Cpu
:
:CpuExtensions
>());
//Extension,useful
// --------------------------- 2.讀取IR模型(xml和bin)---------------------------------
CNNNetReader networkReader;
networkReader.ReadNetwork(
"E:/OpenVINO_modelZoo/vehicle-attributes-recognition-barrier-0039.xml");
networkReader.ReadWeights(
"E:/OpenVINO_modelZoo/vehicle-attributes-recognition-barrier-0039.bin");
CNNNetwork network
= networkReader.getNetwork();
// --------------------------- 3. 準備輸入輸出的------------------------------------------
InputsDataMap inputInfo(network.getInputsInfo());
//得到輸入信息
BlobMap inputBlobs;
//保持全部輸入的blob數據
if (inputInfo.size()
!=
1)
throw std
:
:logic_error(
"錯誤,該模型應該爲單輸入");
auto lrInputInfoItem
=
*inputInfo.begin();
//開始讀入
int w
=
static_cast
<
int
>(lrInputInfoItem.second
-
>getTensorDesc().getDims()[
3]);
//這種寫法也是能夠的,它的first就是data
int h
=
static_cast
<
int
>(lrInputInfoItem.second
-
>getTensorDesc().getDims()[
2]);
network.setBatchSize(
1);
//只有1副圖片,故BatchSize = 1
// --------------------------- 4. 讀取模型 ------------------------------------------(後面這些操做應該能夠合併了)
ExecutableNetwork executableNetwork
= plugin.LoadNetwork(network, {});
// --------------------------- 5. 建立推斷 -------------------------------------------------
InferRequest infer_request
= executableNetwork.CreateInferRequest();
// --------------------------- 6. 將數據塞入模型 -------------------------------------------------
Blob
:
:Ptr lrInputBlob
= infer_request.GetBlob(
"input");
//data這個名字是我看出來的,實際上這裏能夠更統一一些
matU8ToBlob
<float_t
>(src, lrInputBlob,
0);
//重要的轉換函數,第3個參數是batchSize,應該是本身+1的
// --------------------------- 7. 推斷結果 -------------------------------------------------
infer_request.Infer();
//多張圖片屢次推斷
// --------------------------- 8. 處理結果-------------------------------------------------------
// 7 possible colors for each vehicle and we should select the one with the maximum probability
auto colorsValues
= infer_request.GetBlob(
"color")
-
>buffer().as
<
float
*
>();
// 4 possible types for each vehicle and we should select the one with the maximum probability
auto typesValues
= infer_request.GetBlob(
"type")
-
>buffer().as
<
float
*
>();
const
auto color_id
= std
:
:max_element(colorsValues, colorsValues
+
7)
- colorsValues;
const
auto type_id
= std
:
:max_element(typesValues, typesValues
+
4)
- typesValues;
static
const std
:
:string colors[]
= {
"white",
"gray",
"yellow",
"red",
"green",
"blue",
"black"
};
static
const std
:
:string types[]
= {
"car",
"bus",
"truck",
"van"
};
resultPair.first
= colors[color_id];
resultPair.second
= types[type_id];
return resultPair;
}
//識別車牌
string GetPlateNumber(Mat src)
{
// --------------------------- 1.爲IE準備插件-------------------------------------
InferencePlugin plugin(PluginDispatcher().getSuitablePlugin(TargetDevice
:
:eCPU));
plugin.AddExtension(std
:
:make_shared
<Extensions
:
:Cpu
:
:CpuExtensions
>());
//Extension,useful
// --------------------------- 2.讀取IR模型(xml和bin)---------------------------------
CNNNetReader networkReader;
networkReader.ReadNetwork(
"E:/OpenVINO_modelZoo/license-plate-recognition-barrier-0001.xml");
networkReader.ReadWeights(
"E:/OpenVINO_modelZoo/license-plate-recognition-barrier-0001.bin");
CNNNetwork network
= networkReader.getNetwork();
network.setBatchSize(
1);
//只有1副圖片,故BatchSize = 1
// --------------------------- 3. 準備輸入輸出的------------------------------------------
InputsDataMap inputInfo(network.getInputsInfo());
//得到輸入信息
BlobMap inputBlobs;
//保持全部輸入的blob數據
string inputSeqName;
if (inputInfo.size()
==
2) {
auto sequenceInput
= (
++inputInfo.begin());
inputSeqName
= sequenceInput
-
>first;
}
else
if (inputInfo.size()
==
1) {
inputSeqName
=
"";
}
else {
throw std
:
:logic_error(
"LPR should have 1 or 2 inputs");
}
InputInfo
:
:Ptr
& inputInfoFirst
= inputInfo.begin()
-
>second;
inputInfoFirst
-
>setInputPrecision(Precision
:
:U8);
string inputName
= inputInfo.begin()
-
>first;
//準備輸出數據
OutputsDataMap outputInfo(network.getOutputsInfo());
//得到輸出信息
if (outputInfo.size()
!=
1) {
throw std
:
:logic_error(
"LPR should have 1 output");
}
string firstOutputName
= outputInfo.begin()
-
>first;
DataPtr
& _output
= outputInfo.begin()
-
>second;
const SizeVector outputDims
= _output
-
>getTensorDesc().getDims();
// --------------------------- 4. 讀取模型 ------------------------------------------(後面這些操做應該能夠合併了)
ExecutableNetwork executableNetwork
= plugin.LoadNetwork(network, {});
// --------------------------- 5. 建立推斷 -------------------------------------------------
InferRequest infer_request
= executableNetwork.CreateInferRequest();
// --------------------------- 6. 將數據塞入模型 -------------------------------------------------
Blob
:
:Ptr lrInputBlob
= infer_request.GetBlob(inputName);
//data這個名字是我看出來的,實際上這裏能夠更統一一些
matU8ToBlob
<uint8_t
>(src, lrInputBlob,
0);
//重要的轉換函數,第3個參數是batchSize,應該是本身+1的
// --------------------------- 7. 推斷結果 -------------------------------------------------
infer_request.Infer();
//多張圖片屢次推斷
// --------------------------- 8. 處理結果-------------------------------------------------------
static std
:
:vector
<std
:
:string
> items
= {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"<Anhui>",
"<Beijing>",
"<Chongqing>",
"<Fujian>",
"<Gansu>",
"<Guangdong>",
"<Guangxi>",
"<Guizhou>",
"<Hainan>",
"<Hebei>",
"<Heilongjiang>",
"<Henan>",
"<HongKong>",
"<Hubei>",
"<Hunan>",
"<InnerMongolia>",
"<Jiangsu>",
"<Jiangxi>",
"<Jilin>",
"<Liaoning>",
"<Macau>",
"<Ningxia>",
"<Qinghai>",
"<Shaanxi>",
"<Shandong>",
"<Shanghai>",
"<Shanxi>",
"<Sichuan>",
"<Tianjin>",
"<Tibet>",
"<Xinjiang>",
"<Yunnan>",
"<Zhejiang>",
"<police>",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
};
const
auto data
= infer_request.GetBlob(firstOutputName)
-
>buffer().as
<
float
*
>();
std
:
:string result;
for (size_t i
=
0; i
<
88; i
++) {
if (data[i]
==
-
1)
break;
result
+= items[
static_cast
<size_t
>(data[i])];
}
return result;
}
void main()
{
string imageNames
=
"E:/OpenVINO_modelZoo/滬A51V39.jpg";
Mat src
= imread(imageNames);
if (src.empty())
return;
vector
<pair
<Mat, Mat
>> CarAndPlateVector
= GetCarAndPlate(src);
for (
int i
=
0;i
<CarAndPlateVector.size();i
++)
{
pair
<Mat, Mat
> aPair
= CarAndPlateVector[i];
pair
<string, string
> ColorAndType
= GetCarAttributes(aPair.first);
string PlateNumber
= GetPlateNumber(aPair.second);
cout
<< ColorAndType.first
<<
" "
<<ColorAndType.second
<<
" "
<< PlateNumber
<< endl;
}
cv
:
:waitKey();
}