VS2015图形界面YOLO3应用程序

前言

下载的YOLO3源码及其应用程序都是基于命令行的,很多需要把YOLO3集成到图形界面应用里,YOLO作者已经做了YOLO3的DLL,即yolo_cpp_dll,编译方法见我的上一篇文章“Win10+VS2015安装配置YOLO3(CPU/GPU)”,编译后,如果需要图形界面,调用这个DLL就可以了。
作者在源码里附带了yolo_console_dll示例程序,其中涵盖了对视频、图像等的应用,仿照这个程序就可以编制自己的各类应用了。

1 步骤

1.1 新建工程

新建项目-MFC-MFC 应用程序,我这里取名YOLO3Test
应用程序类型-基于对话框,完成
删除资源对话框中确定取消按钮和Static控件
放两个按钮(IDC_LOAD和IDC_CALCULATE)和一个编辑框控件(IDC_EDIT1)
配置选择Release,X64。
然后工程右键-属性-配置属性
C/C++-常规-附加包含目录:加入两个项目,一个是opencv的include路径;一个是yolo3源码yolo_v2_class.hpp所在路径;
链接器-常规-附加库目录:加入两个项目,一个是opencv的lib路径;一个是yolo3源码编译出的yolo_cpp_dll.lib所在路径;
链接器-输入-附加依赖项:加入两个项目,yolo_cpp_dll.lib和opencv_world340.lib
然后在YOLO3源码目录找到yolo_cpp_dll.dll所在路径,拷贝这个路径,回到桌面-此电脑-右键-属性-高级系统设置-环境变量-系统变量-双击变量Path,在最后加上一行粘贴刚才拷贝的路径。

1.2 添加代码

1.2.1 添加头文件和预编译代码

打开YOLO3TestDlg.h,在前面加上

#include "opencv2/opencv.hpp"

在CYOLO3TestDlg类中添加一个成员

cv::Mat mat_img;

打开YOLO3TestDlg.cpp
在前面加上以下代码

#define OPENCV
#define GPU
#include <mutex>
#include "yolo_v2_class.hpp"

注意这个#define OPENCV一定要加在yolo_v2_class.hpp前面,这样才能使能opencv

1.2.2 添加两个按钮的处理程序

1.2.2.1 装入图像(IDC_LOAD)

void CYOLO3TestDlg::OnBnClickedLoad()
{
	// TODO: 在此添加控件通知处理程序代码
	CFileDialog dlg(TRUE, _T("*.jpg;*.jpeg"), 0, 6UL, _T("Image(*.jpg;*.jpeg)|*.jpg;*.jpeg||"));
	if (dlg.DoModal() != IDOK)return;
	std::string filename = CT2A(dlg.GetPathName());
	mat_img = cv::imread(filename);
	cv::imshow("window name", mat_img);
}

1.2.2.2 处理(IDC_CALCULATE)

void CYOLO3TestDlg::OnBnClickedCalculate()
{
	// TODO: 在此添加控件通知处理程序代码
	std::string  names_file = "E:/DeepLearning/YOLO3/darknet-master/build/darknet/x64/data/coco.names";
	std::string  cfg_file = "E:/DeepLearning/YOLO3/darknet-master/build/darknet/x64/cfg/yolov3.cfg";
	std::string  weights_file = "E:/DeepLearning/YOLO3/darknet-master/build/darknet/x64/yolov3.weights";
	auto obj_names = objects_names_from_file(names_file);
	Detector detector(cfg_file, weights_file);
	auto start = std::chrono::steady_clock::now();
	std::vector<bbox_t> result_vec = detector.detect(mat_img);
	auto end = std::chrono::steady_clock::now();
	std::chrono::duration<double> spent = end - start;
	CString msg;
	msg.Format(_T("%lf sec"), spent.count());
	SetDlgItemText(IDC_EDIT1, msg);
	draw_boxes(mat_img, result_vec, obj_names);
	cv::imshow("window name", mat_img);
}

上面代码中的三个文件名根据实际位置来写。

1.2.2.3 拷贝两个函数

以上用到两个函数,可以直接从yolo_console_dll示例程序拷贝,或者从下面代码拷贝也可以

1) 一个是从文件中取物体名称列表的函数,用于把结果框上标识上物体名称
std::vector<std::string> objects_names_from_file(std::string const filename) {
	std::ifstream file(filename);
	std::vector<std::string> file_lines;
	if (!file.is_open()) return file_lines;
	for (std::string line; getline(file, line);) file_lines.push_back(line);
	std::cout << "object names loaded \n";
	return file_lines;
}
2) 还一个是往图像上画结果框的函数
void draw_boxes(cv::Mat mat_img, std::vector<bbox_t> result_vec, std::vector<std::string> obj_names,
	int current_det_fps = -1, int current_cap_fps = -1)
{
	int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } };

	for (auto &i : result_vec) {
		cv::Scalar color = obj_id_to_color(i.obj_id);
		cv::rectangle(mat_img, cv::Rect(i.x, i.y, i.w, i.h), color, 2);
		if (obj_names.size() > i.obj_id) {
			std::string obj_name = obj_names[i.obj_id];
			if (i.track_id > 0) obj_name += " - " + std::to_string(i.track_id);
			cv::Size const text_size = getTextSize(obj_name, cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, 2, 0);
			int const max_width = (text_size.width > i.w + 2) ? text_size.width : (i.w + 2);
			cv::rectangle(mat_img, cv::Point2f(std::max((int)i.x - 1, 0), std::max((int)i.y - 30, 0)),
				cv::Point2f(std::min((int)i.x + max_width, mat_img.cols - 1), std::min((int)i.y, mat_img.rows - 1)),
				color, CV_FILLED, 8, 0);
			putText(mat_img, obj_name, cv::Point2f(i.x, i.y - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(0, 0, 0), 2);
		}
	}
	if (current_det_fps >= 0 && current_cap_fps >= 0) {
		std::string fps_str = "FPS detection: " + std::to_string(current_det_fps) + "   FPS capture: " + std::to_string(current_cap_fps);
		putText(mat_img, fps_str, cv::Point2f(10, 20), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(50, 255, 0), 2);
	}
}

2 程序结果

编译,运行,点Load按钮选择一个图像文件,图像显示出来,然后点Calc按钮,即可看到运算结果和运算花费时间。
在这里插入图片描述
这里是用opencv的imshow弹出窗口显示图像,如果需要可以自己编码把mat_img图像嵌入显示在程序界面上。
以上程序编译了个X64的Debug版,运行到detector的构造函数即出错闪退,所以暂时只能在x64 Release下运行,这个问题事后找了一下,是因为Debug版程序使用了Release版的yolo_cpp_dll.dll,我又编译了Debug版的yolo_cpp_dll.dll,这样各自使用,就没有问题了。
全部程序附在后面:VS2015图形界面YOLO3应用程序

猜你喜欢

转载自blog.csdn.net/hangl_ciom/article/details/88925817
今日推荐