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

所需环境:
环境

win10
VS2017
opencv4.5.4
算法darkmet-yolov4

https://github.com/AlexeyAB/darknet

进入目录

.\darknet-master\darknet-master\build\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<bbox_t> 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;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪迹天涯@wxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值