目标检测笔记——基于win10实现用darknet-yolov4结合opencv用C++实现实时检测

目标检测笔记——基于win10实现用darknet-yolov4结合opencv用C++实现实时检测,第1张

所需环境:
环境

win10
VS2017
opencv4.5.4
算法darkmet-yolov4

https://github.com/AlexeyAB/darknet

进入目录

.\darknet-master\darknet-master\build\darknet

根据是否有gpu选择相应.sln文件打开,这里,由于我电脑上么有gpu,所以选择

打开工程 yolo_cpp_dll_no_gpu.sln,把常规属性中的目标平台版本从8改为10,
修改opencv路径,编译。


出现以下错误:
无法解析的外部符号 make_implicit_layer

更改yolo_cpp_dll_no_gpu.vcxproj文件
注意:下面的2条修改,我在测试时,66行的不需要修改,也可以正常编译成功。
163行加入:

<ClCompile Include="..\..\src\representation_layer.c" />


237行加入:

<ClInclude Include="..\..\src\representation_layer.h" />


改完后,重新打开工程,编译成功,得到以下文件。

解决方法也可以参考下面网址:
https://blog.csdn.net/weixin_50521062/article/details/121267907
注意:我在测试时,66行的不需要修改,也可以正常编译成功。

注意:默认yolov4默认字符集是“多字节字符集”,根据需要可以在工程属性中改为unicode,一样可以编译通过。

如果要编译gpu版dll,必须配置好cuda合cudnn的前提下使用
参考:https://blog.csdn.net/stjuliet/article/details/87884976
https://blog.csdn.net/Angeldream123/article/details/123526012
1.修改yolo_cpp_dll.vcxproj中CUDA的版本号,2处,打开yolo_cpp_dll.vcxproj文件,将具有CUDA的版本改成自己使用的版本(默认为11.1),一共有两处,分别在55行和311行:


2、特别注意要将CUDA设备中的Generation改成自己显卡对应的计算能力(默认添加了35和75两项,可能不是你的显卡的计算能力,可以去英伟达显卡官网查询计算能力:https://developer.nvidia.com/cuda-gpus#collapseOne),否则接下来的生成会出错。在前面边编译训练用的工程时,也有本 *** 作。

用VS2017新建一个工程项目yolov4test

调用dll,进入da
.\darknet-master\darknet-master\include\
.\darknet-master\darknet-master\build\darknet\x64
复制以下文件



yolo_cpp_dll.dllyolo_cpp_dll.lib、pthreadGC2.dllpthreadVC2.dllyolo_v2_class.hpp放到工程目录.\yolov4test\yolov4test

引入yolo_cpp_dll.libyolo_v2_class.hpp


注意yolo_v2_class.hpp要加入“ #define OPENCV ”`

具体使用很简单:
//创建检测器
Detector m_YoloDetector(“.cfg",".weights”);
//检测
std::vector vResult = m_YoloDetector.detect(img);

经测试,debug和release都可以正常使用。

注意:
1、cfg和weights文件如果不存在,会是程序闪退,最好先判断是否存在并提示。
2、cfg和weights必须配套,也就是要用训练weights时使用的cfg,否则会检测不出结果。
3、debug和release的dll不能混用,否则会出错。
4、在调用dll的工程中的yolo_v2_class.hpp中,增加“ #define OPENCV ”
因为有一些代码是#ifdef OPENCV控制的,得加上#define OPENCV才会起作用
否则可能会有如下错误:
错误1:无法 从“cv::Mat”转换为“image_t”
错误2:无法从"cv::Mat"转换为“string",这个错误是因为错误1导致的重载函数匹配不上了。
5、gpu识别coco数据集80分类,识别一次dog.jpg的例子图像,花费3100ms。
识别自己做的1分类数据集,需要1500ms,还是很慢啊。
(cpu i7-7700HQ 2.8GHz)
相同条件下,yolov4-tiny的识别速度是yolov4的10倍,coco数据集80分类识别205ms。
6、虽然用不到,但是特殊记录一下,darknet中的图片像素点数据,都是保存的0-1之间的标准化数据。例如,darknet_R = opencv_R/255

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <fstream>
#include "yolo_v2_class.hpp"

using namespace std;
using namespace cv;
//#define GPU

//画出检测框和相关信息
void DrawBoxes(Mat &frame, vector<string> classes, int classId, float conf, int left, int top, int right, int bottom)
{
	//画检测框
	rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
	//该检测框对应的类别和置信度
	string label = format("%.2f", conf);
	if (!classes.empty())
	{
		CV_Assert(classId < (int)classes.size());
		label = classes[classId] + ":" + label;
	}
	//将标签显示在检测框顶部
	int baseLine;
	Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
	top = max(top, labelSize.height);
	rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
	putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
}


//画出检测结果
void Drawer(Mat &frame, vector<bbox_t> outs, vector<string> classes)
{
	//获取所有最佳检测框信息
	for (int i = 0; i < outs.size(); i++)
	{
		DrawBoxes(frame, classes, outs[i].obj_id, outs[i].prob, outs[i].x, outs[i].y,
			outs[i].x + outs[i].w, outs[i].y + outs[i].h);
	}
}


int main(void)
{
	string classesFile = "./yolo/coco.names";
	string modelConfig = "./yolo/yolov4.cfg";
	string modelWeights = "./yolo/yolov4.weights";

	//加载类别名
	vector<string> classes;
	ifstream ifs(classesFile.c_str());
	string line;
	while (getline(ifs, line)) classes.push_back(line);
	//加载网络模型,0是指定第一块GPU
	Detector detector(modelConfig, modelWeights, 0);

	string mode = "video";
	//图像
	if (mode == "image")
	{
		Mat frame = imread("./data/test.jpg");
		//Mat图像转为yolo输入格式
		shared_ptr<image_t> detImg = detector.mat_to_image_resize(frame);
		//前向预测
		vector<bbox_t> outs = detector.detect_resized(*detImg, frame.cols, frame.rows, 0.25);
		//画图
		Drawer(frame, outs, classes);
		imwrite("./data/result.jpg", frame);
	}
	//视频
	else if (mode == "video")
	{
		VideoCapture cap("./data/test.avi");
		Size size(1920, 1080);
		VideoWriter writer("./data/result.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 25, size);
		while (1) 
		{
			Mat frame;
			cap >> frame;
			if (frame.empty()) 
				break;

			//Mat图像转为yolo输入格式
			shared_ptr<image_t> detImg = detector.mat_to_image_resize(frame);
			//前向预测
			vector<bbox_t> outs = detector.detect_resized(*detImg, frame.cols, frame.rows, 0.25);
			//画图
			Drawer(frame, outs, classes);
			writer << frame;
		}
		cap.release();
	}
    return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/3002141.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存