一、多車輛識別可能和車輛車牌分割;
這樣一張圖,可以識別多車輛和車牌,問題是如何區分並且配對。
0
1
7
8
是否是車牌可以通過圖片的大小進行判斷。而配對是前后順序的。
// --------------------------- 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)//車輛
{
char cbuf[255];
sprintf_s(cbuf, "E:/OpenVINO_modelZoo/car_%d.jpg", i_car);
Mat roi = src(rect);
imwrite(cbuf, roi);
cv::rectangle(src, rect, cv::Scalar(255, 255, 255));
i_car++;
}
else//車牌
{
char cbuf[255];
sprintf_s(cbuf, "E:/OpenVINO_modelZoo/plant_%d.jpg", i_plate);
Mat roi = src(rect);
imwrite(cbuf, roi);
cv::rectangle(src, rect, cv::Scalar(0, 0, 255));
i_plate++;
}
}
}
這種處理的方法,后面應該還是要用的
二、函數化封裝和合並;
以下是原始代碼
#
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();
}
# 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();
}
能夠合並到這種程度是很有價值的,下一步可以思考找到更多的數據集進行訓練,並且將這個結果進行轉換。
從結果上來看,已經實現了級聯問題,從這個層面是沒有問題的;只有在具體的需求面前才可能看出問題。
我需要拓展一下車牌識別的真實需求,也許這個會成為我真正DL4CV的開始。
三、異步機制探索;
一直以來,我都為視頻處理的速度問題所困擾,在“視頻流”的處理過程中,必須首先獲得一幀的數據,然后才能夠處理這一
幀的數據,並且得到增強的結果——那么最后處理的速度必然同時受到視頻采集和圖像處理的限制。
這可能類似於CPU中流的處理,而且據我所知,這方面的研究不僅開始很久,而且效果顯著,但是苦於一直沒有一個可以參考的實現。現在OpenVINO中對於視頻的處理,應該說是解決燃眉之急。
OpenVINO中相關函數
使用
StartAsync和
Wait來實現異步操作
(Do inference by calling the InferenceEngine::InferRequest::StartAsync and InferenceEngine::InferRequest::Wait methods for asynchronous request):
infer_request
-
>
StartAsync();
infer_request.Wait(IInferRequest : : WaitMode : : RESULT_READY);
infer_request.Wait(IInferRequest : : WaitMode : : RESULT_READY);
或者采用
Infer 來實現同步操作(
or by calling the InferenceEngine::InferRequest::Infer method for synchronous request):
sync_infer_request
-
>
Infer();
在同步模式下推斷函數Infer會一直阻塞,直到執行結束;在異步模式下推斷調用函數StartAsync會立即返回,通過檢查。
對於視頻分析、視頻中對象檢測,OpenVINO官方建議通過異步方式可以實現更快的幀率處理.
異步雖然好,但是如果僅是這樣改寫
則價值不大,和同步沒有區分。必須建立相應的機制:
在例子中,是這樣建立的:
首先是創建:
每一個檢測,都包含available和pending兩個部分,在創建的初期,根據FLAGS_nireq這個參數,來設定開幾個available(可以理解開幾個線程)
在每一個推斷的開始,首先判斷available是否還有,如果所有的
available都已經被使用,那么就必須要開始運算
其中的
肯定就是在這個地方等待結果的;
如果avaiable還有,直接將推斷送到下一個avaiable中去:
並且立刻開始推斷。這樣的話,就可以實現多個pending都在推斷的狀況。
在
FLAGS_nireq被設置為1的時候
設置為3的時候
有所提高,但是不明顯。
做一個4宮格
-nireq 3 -i E:/未來項目/煉數成金/(錄制中)端到端/L9/道路監控數據集/1.avi E:/未來項目/煉數成金/(錄制中)端到端/L9/道路監控數據集/2.avi E:/未來項目/煉數成金/(錄制中)端到端/L9/道路監控數據集/1.avi E:/未來項目/煉數成金/(錄制中)端到端/L9/道路監控數據集/2.avi -m E:/OpenVINO_modelZoo/vehicle-license-plate-detection-barrier-0106.xml -m_va E:/OpenVINO_modelZoo/vehicle-attributes-recognition-barrier-0039.xml -m_lpr E:/OpenVINO_modelZoo/license-plate-recognition-barrier-0001.xml
但是為了進一步研究問題,需要具體做例子來實驗。
好吧,還是有所差異的。
四、類的封裝其價值
最終該機制的速度不會快於單個推斷速度,我們至少可以將整個操作分為”數據准備“”數據推斷“和”數據顯示“3個部分。
我們需要的是打開VideoCapture的相關代碼
VideoCapture capture(
"E:/未來項目/煉數成金/(錄制中)端到端/L9/道路監控數據集/2.avi");
Mat src;
while ( true)
{
if ( !capture.read(src))
break;
……
Mat src;
while ( true)
{
if ( !capture.read(src))
break;
……
然后代碼必須經過函數化(過程化無法被集成)和結構化(初始化的東西必須被獨立出來,甚至可能會導致錯誤),參考現有例子是最方便的方式。然后對於生成的結果,我們需要做較為精確的測量。
其中有一個非常重要的“保護機制
”
,一定要注意對這個“機制”的理解,否則很容易出現下圖問題
相比較之下,
正確調用產生的結果
其來源
也就是在我們調用createInferRequest的時候,會首先判斷當前detection的enabled,如果這個enabled為false,則直接退出為空。
而這個定義是被寫死的
它在當前Detection(比如VehicleDetection)被創建的時候產生。由於原代碼中FLAGS_m是作為參數輸入的,則會定義;但是我們將代碼獨立出來,則這個地方是沒有定義的,那么久比需將其規避掉。包括,將這個FLAGS_m直接寫入
和將模型調用的參數直接寫入
現在回顧這里的異步機制,它之所以能夠提高速度,本質上還是較好的架構,我們通過畫圖來說明。
我們將整個處理的時間分為3個部分
是數據采集和輸入的時間,我們稱之為C;
是數據處理的時間(也是最消耗時間的地方),我們稱之為P;
是數據顯示的時間(這個基本可以做到旁路),我們稱之為S。
其中紅、黃、藍分別代表第1、2、3幀
原機制為
時間為C1+P1+C2+P2+C3+P3
使用機制進行了亂序
消耗時間不會大於(一般認為P>>C),C1+P1+P2+P3。能夠將部分時間進行重疊,從而達到提高速度目的。
小結:
1、OpenVINO的推斷操作比較快(最終該機制的速度不會快於單個推斷速度,它只是將數據准備和數據顯示進行重疊);
2、它的原子操作提供了這種“線程獨立安全”的運算;
3、只有在滿足"
原子操作線程獨立“的基礎上,才能夠去做這樣的操作。這種方法,將來要積極運用。
附件列表
