Intel OpenVINO sample基于命令行的,做UI不便,移植到MFC:
1、按照https://blog.csdn.net/qq_36556893/article/details/81385008安装OpenVINO并确保sample正常运行。
2、打开VS2017,新建MFC Prj
3、拷贝OpenVINO sample文件到MFC 项目目录
4、把拷贝的文件添加进项目
5、打开对话框,删除原按钮,添加button1,添加Picture Control控件,拉至大致16:9比例合适大小,修改控件名称IDC_VIEW:
6、从OpenVINO目录拷贝需要的头文件文件夹,添加头文件
7、配置头文件包含目录和库文件
7、添加的detectors.cpp不使用预编译头。
8、修改源码并build
void COpenVINOdemoDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
cv::VideoCapture cap;
cap.open(0);
//默认是VGA的,设置为720P
cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
const size_t width = (size_t) cap.get(cv::CAP_PROP_FRAME_WIDTH);
const size_t height = (size_t) cap.get(cv::CAP_PROP_FRAME_HEIGHT);
// read input (video) frame
cv::Mat frame;
if (!cap.read(frame)) {
AfxMessageBox("Failed to get frame from cv::VideoCapture");
return;
}
FLAGS_l = "";
FLAGS_c = "";
FLAGS_m = "E:\\OpenVINO_MFC\\module\\FP32\\face-detection-adas-0001.xml";
FLAGS_d = "CPU";
FLAGS_async = true;
FLAGS_t = 0.5;
FLAGS_r = 0;
FLAGS_m_ag = "E:\\OpenVINO_MFC\\module\\FP32\\age-gender-recognition-retail-0013.xml";
FLAGS_d_ag = "GPU";
FLAGS_n_ag = 4;
FLAGS_dyn_ag = true;
FLAGS_m_hp = "E:\\OpenVINO_MFC\\module\\FP32\\head-pose-estimation-adas-0001.xml";
FLAGS_d_hp = "CPU";
FLAGS_n_hp = 4;
FLAGS_dyn_hp = false;
FLAGS_m_em = "E:\\OpenVINO_MFC\\module\\FP32\\emotions-recognition-retail-0003.xml";
FLAGS_d_em = "CPU";
FLAGS_n_em = 4;
FLAGS_dyn_em = true;
FLAGS_m_lm = "E:\\OpenVINO_MFC\\module\\FP32\\facial-landmarks-35-adas-0001.xml";
FLAGS_d_lm = "CPU";
FLAGS_n_lm = 4;
FLAGS_dyn_lm = true;
FLAGS_async = true;
FLAGS_pc = 1;
// ---------------------------------------------------------------------------------------------------
// --------------------------- 1. Loading plugin to the Inference Engine -----------------------------
std::map pluginsForDevices;
std::vector> cmdOptions = {
{FLAGS_d, FLAGS_m}, {FLAGS_d_ag, FLAGS_m_ag}, {FLAGS_d_hp, FLAGS_m_hp},
{FLAGS_d_em, FLAGS_m_em}, {FLAGS_d_lm, FLAGS_m_lm}
};
FaceDetection faceDetector(FLAGS_m, FLAGS_d, 1, false, FLAGS_async, FLAGS_t, FLAGS_r);
AgeGenderDetection ageGenderDetector(FLAGS_m_ag, FLAGS_d_ag, FLAGS_n_ag, FLAGS_dyn_ag, FLAGS_async);
HeadPoseDetection headPoseDetector(FLAGS_m_hp, FLAGS_d_hp, FLAGS_n_hp, FLAGS_dyn_hp, FLAGS_async);
EmotionsDetection emotionsDetector(FLAGS_m_em, FLAGS_d_em, FLAGS_n_em, FLAGS_dyn_em, FLAGS_async);
FacialLandmarksDetection facialLandmarksDetector(FLAGS_m_lm, FLAGS_d_lm, FLAGS_n_lm, FLAGS_dyn_lm, FLAGS_async);
for (auto && option : cmdOptions) {
auto deviceName = option.first;
auto networkName = option.second;
if (deviceName == "" || networkName == "") {
continue;
}
if (pluginsForDevices.find(deviceName) != pluginsForDevices.end()) {
continue;
}
InferencePlugin plugin = PluginDispatcher({"../../../lib/intel64", ""}).getPluginByDevice(deviceName);
/** Printing plugin version **/
printPluginVersion(plugin, std::cout);
/** Loading extensions for the CPU plugin **/
if ((deviceName.find("CPU") != std::string::npos)) {
plugin.AddExtension(std::make_shared());
if (!FLAGS_l.empty()) {
// CPU(MKLDNN) extensions are loaded as a shared library and passed as a pointer to base extension
auto extension_ptr = make_so_pointer(FLAGS_l);
plugin.AddExtension(extension_ptr);
slog::info << "CPU Extension loaded: " << " " << FLAGS_l << slog::endl;
}
} else if (!FLAGS_c.empty()) {
// Loading extensions for other plugins not CPU
plugin.SetConfig({{PluginConfigParams::KEY_CONFIG_FILE, FLAGS_c}});
}
pluginsForDevices[deviceName] = plugin;
}
/** Per-layer metrics **/
if (FLAGS_pc) {
for (auto && plugin : pluginsForDevices) {
plugin.second.SetConfig({{PluginConfigParams::KEY_PERF_COUNT, PluginConfigParams::YES}});
}
}
// ---------------------------------------------------------------------------------------------------
// --------------------------- 2. Reading IR models and loading them to plugins ----------------------
// Disable dynamic batching for face detector as it processes one image at a time
Load(faceDetector).into(pluginsForDevices[FLAGS_d], false);
Load(ageGenderDetector).into(pluginsForDevices[FLAGS_d_ag], FLAGS_dyn_ag);
Load(headPoseDetector).into(pluginsForDevices[FLAGS_d_hp], FLAGS_dyn_hp);
Load(emotionsDetector).into(pluginsForDevices[FLAGS_d_em], FLAGS_dyn_em);
Load(facialLandmarksDetector).into(pluginsForDevices[FLAGS_d_lm], FLAGS_dyn_lm);
// ----------------------------------------------------------------------------------------------------
// --------------------------- 3. Doing inference -----------------------------------------------------
// Starting inference & calculating performance
if (!FLAGS_no_show) {
std::cout << "Press any key to stop" << std::endl;
}
bool isFaceAnalyticsEnabled = ageGenderDetector.enabled() || headPoseDetector.enabled() ||
emotionsDetector.enabled() || facialLandmarksDetector.enabled();
Timer timer;
timer.start("total");
std::ostringstream out;
size_t framesCounter = 0;
bool frameReadStatus;
bool isLastFrame;
cv::Mat prev_frame, next_frame;
// Detecting all faces on the first frame and reading the next one
timer.start("detection");
faceDetector.enqueue(frame);
faceDetector.submitRequest();
timer.finish("detection");
prev_frame = frame.clone();
// Reading the next frame
timer.start("video frame decoding");
frameReadStatus = cap.read(frame);
timer.finish("video frame decoding");
while (true) {
framesCounter++;
isLastFrame = !frameReadStatus;
timer.start("detection");
// Retrieving face detection results for the previous frame
faceDetector.wait();
faceDetector.fetchResults();
auto prev_detection_results = faceDetector.results;
// No valid frame to infer if previous frame is the last
if (!isLastFrame) {
faceDetector.enqueue(frame);
faceDetector.submitRequest();
}
timer.finish("detection");
timer.start("data preprocessing");
// Filling inputs of face analytics networks
for (auto &&face : prev_detection_results) {
if (isFaceAnalyticsEnabled) {
auto clippedRect = face.location & cv::Rect(0, 0, width, height);
cv::Mat face = prev_frame(clippedRect);
ageGenderDetector.enqueue(face);
headPoseDetector.enqueue(face);
emotionsDetector.enqueue(face);
facialLandmarksDetector.enqueue(face);
}
}
timer.finish("data preprocessing");
// Running Age/Gender Recognition, Head Pose Estimation, Emotions Recognition, and Facial Landmarks Estimation networks simultaneously
timer.start("face analytics call");
if (isFaceAnalyticsEnabled) {
ageGenderDetector.submitRequest();
headPoseDetector.submitRequest();
emotionsDetector.submitRequest();
facialLandmarksDetector.submitRequest();
}
timer.finish("face analytics call");
// Reading the next frame if the current one is not the last
if (!isLastFrame) {
timer.start("video frame decoding");
frameReadStatus = cap.read(next_frame);
timer.finish("video frame decoding");
}
timer.start("face analytics wait");
if (isFaceAnalyticsEnabled) {
ageGenderDetector.wait();
headPoseDetector.wait();
emotionsDetector.wait();
facialLandmarksDetector.wait();
}
timer.finish("face analytics wait");
// Visualizing results
if (!FLAGS_no_show) {
timer.start("visualization");
out.str("");
out << "OpenCV cap/render time: " << std::fixed << std::setprecision(2)
<< (timer["video frame decoding"].getSmoothedDuration() +
timer["visualization"].getSmoothedDuration())
<< " ms";
cv::putText(prev_frame, out.str(), cv::Point2f(0, 25), cv::FONT_HERSHEY_TRIPLEX, 0.5,
cv::Scalar(255, 0, 0));
out.str("");
out << "Face detection time: " << std::fixed << std::setprecision(2)
<< timer["detection"].getSmoothedDuration()
<< " ms ("
<< 1000.f / (timer["detection"].getSmoothedDuration())
<< " fps)";
cv::putText(prev_frame, out.str(), cv::Point2f(0, 45), cv::FONT_HERSHEY_TRIPLEX, 0.5,
cv::Scalar(255, 0, 0));
if (isFaceAnalyticsEnabled) {
out.str("");
out << "Face Analysics Networks "
<< "time: " << std::fixed << std::setprecision(2)
<< timer["face analytics call"].getSmoothedDuration() +
timer["face analytics wait"].getSmoothedDuration()
<< " ms ";
if (!prev_detection_results.empty()) {
out << "("
<< 1000.f / (timer["face analytics call"].getSmoothedDuration() +
timer["face analytics wait"].getSmoothedDuration())
<< " fps)";
}
cv::putText(prev_frame, out.str(), cv::Point2f(0, 65), cv::FONT_HERSHEY_TRIPLEX, 0.5,
cv::Scalar(255, 0, 0));
}
// For every detected face
int i = 0;
for (auto &result : prev_detection_results) {
cv::Rect rect = result.location;
out.str("");
if (ageGenderDetector.enabled() && i < ageGenderDetector.maxBatch) {
out << (ageGenderDetector[i].maleProb > 0.5 ? "M" : "F");
out << std::fixed << std::setprecision(0) << "," << ageGenderDetector[i].age;
if (FLAGS_r) {
std::cout << "Predicted gender, age = " << out.str() << std::endl;
}
} else {
out << (result.label < faceDetector.labels.size() ? faceDetector.labels[result.label] :
std::string("label #") + std::to_string(result.label))
<< ": " << std::fixed << std::setprecision(3) << result.confidence;
}
if (emotionsDetector.enabled() && i < emotionsDetector.maxBatch) {
std::string emotion = emotionsDetector[i];
if (FLAGS_r) {
std::cout << "Predicted emotion = " << emotion << std::endl;
}
out << "," << emotion;
}
cv::putText(prev_frame,
out.str(),
cv::Point2f(result.location.x, result.location.y - 15),
cv::FONT_HERSHEY_COMPLEX_SMALL,
0.8,
cv::Scalar(0, 0, 255));
if (headPoseDetector.enabled() && i < headPoseDetector.maxBatch) {
if (FLAGS_r) {
std::cout << "Head pose results: yaw, pitch, roll = "
<< headPoseDetector[i].angle_y << ";"
<< headPoseDetector[i].angle_p << ";"
<< headPoseDetector[i].angle_r << std::endl;
}
cv::Point3f center(rect.x + rect.width / 2, rect.y + rect.height / 2, 0);
headPoseDetector.drawAxes(prev_frame, center, headPoseDetector[i], 50);
}
if (facialLandmarksDetector.enabled() && i < facialLandmarksDetector.maxBatch) {
auto normed_landmarks = facialLandmarksDetector[i];
auto n_lm = normed_landmarks.size();
if (FLAGS_r)
std::cout << "Normed Facial Landmarks coordinates (x, y):" << std::endl;
for (auto i_lm = 0UL; i_lm < n_lm / 2; ++i_lm) {
float normed_x = normed_landmarks[2 * i_lm];
float normed_y = normed_landmarks[2 * i_lm + 1];
if (FLAGS_r) {
std::cout << normed_x << ", "
<< normed_y << std::endl;
}
int x_lm = rect.x + rect.width * normed_x;
int y_lm = rect.y + rect.height * normed_y;
// Drawing facial landmarks on the frame
cv::circle(prev_frame, cv::Point(x_lm, y_lm), 1 + static_cast(0.012 * rect.width), cv::Scalar(0, 255, 255), -1);
}
}
auto genderColor = (ageGenderDetector.enabled() && (i < ageGenderDetector.maxBatch)) ?
((ageGenderDetector[i].maleProb < 0.5) ? cv::Scalar(147, 20, 255) : cv::Scalar(255, 0,
0))
: cv::Scalar(100, 100, 100);
cv::rectangle(prev_frame, result.location, genderColor, 1);
i++;
}
/// cv::imshow(WINDOW_NAME, prev_frame);
DrawMat(prev_frame, IDC_VIEW);
timer.finish("visualization");
} else if (FLAGS_r) {
// For every detected face
for (int i = 0; i < prev_detection_results.size(); i++) {
if (ageGenderDetector.enabled() && i < ageGenderDetector.maxBatch) {
out.str("");
out << (ageGenderDetector[i].maleProb > 0.5 ? "M" : "F");
out << std::fixed << std::setprecision(0) << "," << ageGenderDetector[i].age;
std::cout << "Predicted gender, age = " << out.str() << std::endl;
}
if (emotionsDetector.enabled() && i < emotionsDetector.maxBatch) {
std::cout << "Predicted emotion = " << emotionsDetector[i] << std::endl;
}
if (headPoseDetector.enabled() && i < headPoseDetector.maxBatch) {
std::cout << "Head pose results: yaw, pitch, roll = "
<< headPoseDetector[i].angle_y << ";"
<< headPoseDetector[i].angle_p << ";"
<< headPoseDetector[i].angle_r << std::endl;
}
if (facialLandmarksDetector.enabled() && i < facialLandmarksDetector.maxBatch) {
auto normed_landmarks = facialLandmarksDetector[i];
auto n_lm = normed_landmarks.size();
std::cout << "Normed Facial Landmarks coordinates (x, y):" << std::endl;
for (auto i_lm = 0UL; i_lm < n_lm / 2; ++i_lm) {
float normed_x = normed_landmarks[2 * i_lm];
float normed_y = normed_landmarks[2 * i_lm + 1];
std::cout << normed_x << ", "
<< normed_y << std::endl;
}
}
}
}
prev_frame = frame;
frame = next_frame;
next_frame = cv::Mat();
}
cap.release();
}
9、把dll拷贝到exe文件夹
10、运行效果,借用马爸爸图:
代码下载:OpenVINO MFC Demo。