c++封装yolov4进行目标检测

2023-05-16

yolo4是用c++写的,在工程中的部署特别方便。之前项目中使用yolov4,取得了不错的效果。在这里记录一下。
使用官方接口调用,我们首先得编译darknet动态库,下载yolov4源码

git clone https://github.com/AlexeyAB/darknet.git

编译yolov4为动态库

  1. yolo_cpp_dll.sln,在darknet-master\build\darknet目录下面。
  2. 设置x64和Lease,然后右击项目,生成。
    注意:这里应该配置好环境 CUDA 10.2以及 cuDNN,以及修改了yolo_cpp_dll.vcxproj中的cuda版本。
  3. 然后在darknet-master\build\darknet\x64就会生成yolo_cpp_dll.dll文件。这个文件就是编译好的dll文件,可以直接使用。
    yolo_cpp_dll.dll的接口如下:
struct bbox_t {
    unsigned int x, y, w, h;    // (x,y) - top-left corner, (w, h) - width & height of bounded box
    float prob;                    // confidence - probability that the object was found correctly
    unsigned int obj_id;        // class of object - from range [0, classes-1]
    unsigned int track_id;        // tracking id for video (0 - untracked, 1 - inf - tracked object)
    unsigned int frames_counter;// counter of frames on which the object was detected
};

class Detector {
public:
        Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0);
        ~Detector();

        std::vector<bbox_t> detect(std::string image_filename, float thresh = 0.2, bool use_mean = false);
        std::vector<bbox_t> detect(image_t img, float thresh = 0.2, bool use_mean = false);
        static image_t load_image(std::string image_filename);
        static void free_image(image_t m);

#ifdef OPENCV
        std::vector<bbox_t> detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false);
        std::shared_ptr<image_t> mat_to_image_resize(cv::Mat mat) const;
#endif
};

关于这一部分有疑问的,可以参考官文档:https://github.com/AlexeyAB/darknet#yolo-v4-in-other-frameworks

检测步骤
检测部分需要用到刚刚编译的动态库,以及yolov4源码下的yolo_v2_class.hpp,需要将yolo_v2_class.hpp路径添加到包含目录中。

在这里插入图片描述
使用步骤大致分为以下几步
加载网络模型

string modelConfig = "yolov4/s_yolov4.cfg";
string modelWeights = "yolov4/yolov4.weights"";
string classesFile = "yolov4/s_coco.names";
Detector detector(modelConfig, modelWeights, 0);

调用 detector中的方法detect方法进行检测

std::vector<bbox_t> res = detector.detect(image);

image是Mat类型的

输出结果结构体bbox_t可以在yolo_v2_class.hpp看到,包括检测框左上角坐标,高和宽,置信度,类别等,有了它们画图也很简单了。

struct bbox_t {
    unsigned int x, y, w, h;       // (x,y) - top-left corner, (w, h) - width & height of bounded box
    float prob;                    // confidence - probability that the object was found correctly
    unsigned int obj_id;           // class of object - from range [0, classes-1]
    unsigned int track_id;         // tracking id for video (0 - untracked, 1 - inf - tracked object)
    unsigned int frames_counter;   // counter of frames on which the object was detected
    float x_3d, y_3d, z_3d;        // center of object (in Meters) if ZED 3D Camera is used
};
Drawer(image, res, classes);
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);
	}
}
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);
}

完整的代码如下:

#include <opencv2/opencv.hpp>
#include <yolo_v2_class.hpp>

using namespace std;
using namespace cv;

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() {
	string classesFile = "yolov4/s_coco.names";
	vector<string> classes;
	ifstream ifs(classesFile.c_str());
	string line;
	while (getline(ifs, line)) classes.push_back(line);
	string modelConfig = "yolov4/yolov4.cfg";
	string modelWeights = "yolov4/yolov4.weights";
	Mat image = imread("dog.jpg");
	if (image.empty()) {
		cout << "the image is enpty" << endl;
	}
	else {
		Detector detector(modelConfig, modelWeights, 0);
		std::vector<bbox_t> res = detector.detect(image);
		Drawer(image, res, classes);
		imwrite("dog_result.jpg", image);
	}
	system("pause");
	return 0;
}

C#使用yolov4
由于在我的项目中,需要与C#的界面进行对接,并且需要实时获得检测结果,因此我想到将以上代码进一步封装成动态库。这样做的好处在于避免了C#直接调用yolo_cpp_dll.dll,方便在C++进行进一步的功能扩展。
在封装dll的过程中,不能直接对main方法中的内容进行封装。原因在于,如果对main中的内容都进行封装,每次检测图片都会经历一个模型加载的过程,会花费大量的时间,远远不能达到实时的效果。因此我对main中的内容进行了分解。
解决思路如下:
抽离加载模型的部分,返回模型的指针。

extern "C" __declspec(dllexport)
void* __stdcall model()
{
	string modelConfig = "yolov4/yolov4.cfg";
	string modelWeights = "yolov4/yolov4.weights";
	Detector* model = new Detector(modelConfig, modelWeights, 0);加载模型,只运行一遍
	return	(void*)model;
}

因为C#是可以接受C++的指针的,C#就可以将这个指针作为参数返回给C++的检测方法,对图片进行检测。
封装检测的部分代码如下:有两个参数,一个是图片指针,另一个是模型的指针。可以返回检测结果的指针,根据需要进行修改。

extern "C" __declspec(dllexport)
void* __stdcall Detect(const char* imagefile, void* p_model)
{
	Detector* model = (Detector*)p_model;
	string fileimage;
	fileimage = imagefile;
	Mat image = imread(fileimage);
	if (image.empty())
	{
		cout << "the image is enpty" << endl;
		return NULL;
	}
	std::vector<bbox_t> res = model->detect(image);
}

为了避免造成内存泄漏,C#需要调用C++的函数,将模型进行删除,删除模型的代码如下。

extern "C" __declspec(dllexport)
void __stdcall stop_model(void* p_model)
{
	Detector* model = (Detector*)p_model;
	delete(model);
	int* res_ar = (int*)res_arr;
}

最后:菜鸟一枚,欢迎各位大佬指正!!!!!!!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++封装yolov4进行目标检测 的相关文章

  • opencv使用MobileNetSSD进行目标检测

    这里我们使用MobileNetSSD进行目标检测 xff0c 模型文件是下载的这个 xff1a https github com PINTO0309 MobileNet SSD RealSense tree master caffemode
  • c++调用yolov4模型进行目标检测-使用opencv4.4.0

    前言 最近刚出的opencv4 4 0也支持了yolov4 xff0c 便尝试用opencv调用yolov4进行检测 xff0c 做个记录 当然 xff0c yolov3 yolov4 tiny等也能调用 xff0c 只需修改加载的cfg和
  • YOLOV4与YOLOV3的区别

    YOLOV4与YOLOV3的区别 A big bliss的博客 CSDN博客 yolov3和yolov4的区别 首先 xff0c 先大概的说下二者之间的差别 xff1a 1 特征提取网络的不同 2 激活函数的不同 3 loss的不同 4 数
  • YOLOv4代码学习笔记一

    YOLOV4代码学习笔记一 YOLOV4简介CSPdarknet py学习 本文是对另一个博主的 睿智的目标检测30 Pytorch搭建YoloV4目标检测平台代码的学习 xff0c 由于我是cv新手 xff0c 很多东西不懂 xff0c
  • 从配置环境开始,跑通YOLOv4模型,测试成功!

    Windows10下跑通YOLOv4模型 xff0c 从配置环境开始 xff0c 测试成功 xff01 成功配置环境并跑通代码 xff0c 快乐记录ing xff08 参考来源 xff1a 博客地址 xff09 1 配置环境 1 1安装VS
  • YOLOv4:ubuntu18下使用darknet训练自己的模型

    首先 xff0c 如果使用GPU xff0c 确认你电脑的有关环境是否符合以下要求 xff1a CMake gt 61 3 12CUDA gt 61 10 0OpenCV gt 61 2 4cuDNN gt 61 7 0GPU with C
  • YOLOv4在ROS-Melodic上的部署-libtorch(附源码,非Darknet)

    有关YOLOv4 LibTorch的部署可以看我的这篇博客 然后移植到ROS Melodic上就相对简单了 直接上GitHub链接吧 初版可能有点乱 xff0c 但是注释挺详细 xff0c 欢迎交流经验哈 2020 12 16 更新 YOL
  • yolov4-tiny使用jetson nano进行目标检测+tensorrt+CSI+USB摄像头检测

    软硬件版本 Jetson Nano 4G ubuntu 18 04 JP 4 5 1 CUDA 10 2 TensorRT 7 1 3 0 Python 3 6 一 下载源码 git clone https github com Alexe
  • PyTorch版YOLOv4训练自己的数据集---基于Google Colab

    colab简介 Google Colaboratory是谷歌开放的一款研究工具 xff0c 主要用于机器学习的开发和研究 工具优势 xff1a Google Colab最大的好处是给广大的AI开发者提供了免费的GPU使用 你可以在上面轻松地
  • YOLOv4剪枝【附代码】

    本项目只是负责把框架搭建起来 xff0c 没有进行重训练的微调或者去研究应该剪哪里比较好 xff0c 需要自己去研究 YOLOv4代码参考 xff1a Pytorch 搭建自己的YoloV4目标检测平台 xff08 Bubbliiiing
  • 一文读懂YOLOv5 与 YOLOv4

    作者 xff1a William 来源 xff1a 自动驾驶全栈工程师知乎专栏 链接 xff1a https www zhihu com people william hyin columns YOLO之父Joseph Redmon在今年年
  • 无人机目标检测:使用YOLOv4在VisDrone数据集上进行目标检测任务

    在本篇博客中 我们将探讨如何使用YOLOv4在VisDrone数据集上进行无人机目标检测任务 目标检测是计算机视觉中的一个重要任务 可以用于自动驾驶汽车 无人机监测和视频分析等多种应用 YOLOv4是一种实时目标检测算法 以其速度和准确性而
  • 使用 YOLO 进行目标检测

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 自从世界了解人工智能以来 xff0c 有一个特别的用例已经被讨论了很多 它们是自动驾驶汽车 我们经常在科幻电影中听到 读到甚至看到这些
  • 【YOLOv4】详细讲解全过程

    目录 1 YoloV4核心基础内容 1 1 网络结构可视化 1 2 网络结构图 1 3 核心基础内容 1 3 1 输入端创新 xff08 1 xff09 Mosaic数据增强 1 3 2 BackBone创新 xff08 1 xff09 C
  • Jetson Nano( 五) TensorRT yolov4 yolov4-tiny yolov5 实测

    TensorRT yolov4 yolov4 tiny yolov5 长期更新 文章目录 TensorRT yolov4 yolov4 tiny yolov5 长期更新软硬件环境参考大佬项目简要流程注意要点操作流程记录遇坑推理速度记录 软硬
  • Darknet YoloV4编译+训练(避免踩坑)

    AlexAB darknet yolov4编译 43 训练 时间间隔好几天今天来更新一下yolov4的训练 训练篇 在训练之前需要对大佬的源码进行编译本本机编译 xff0c 编译过程可查看下述链接 xff1a https blog csdn
  • c++封装yolov4进行目标检测

    yolo4是用c 43 43 写的 xff0c 在工程中的部署特别方便 之前项目中使用yolov4 xff0c 取得了不错的效果 在这里记录一下 使用官方接口调用 xff0c 我们首先得编译darknet动态库 xff0c 下载yolov4
  • 睿智的目标检测29——Keras搭建YoloV4目标检测平台

    睿智的目标检测29 Keras搭建YoloV4目标检测平台 学习前言 什么是YOLOV4 代码下载 YOLOV4改进的部分 不完全 YOLOV4结构解析 1 主干特征提取网络Backbone 2 特征金字塔 3 YoloHead利用获得到的
  • 【深度学习】基于Tensorflow的YOLOV4,已跑通程序,效果不错

    完整的程序放在这里了 已经跑通no bug 完整程序 实现效果 自己在colab上训练模型后得到的权重预测 试了几个场景 B站视频链接 识别校门口一号路 识别海盗狗 截图 部分代码如下 voc annotation py import os
  • yolov4训练自己的数据模型

    看了下yolov4的作者给的操作说明 链接如下 https github com AlexeyAB darknet how to compile on linux using make 有兴趣的可以去看看 总结起来 跟yolov3的操作方式

随机推荐

  • c# Post请求实例

    server span class token comment 服务器 span span class token keyword using span span class token namespace System span span
  • STM32 串口通讯及实现

    目录 一 串口通讯概述1 广义的串口2 狭义的串口3 串口数据定义4 串口通讯应用 二 STM32串口工程标准库实现1 串口的初始化2 串口数据发送 3 串口的数据接收 一 串口通讯概述 1 广义的串口 广义的串口是针对并口来说的 串口是指
  • STM32串口接受和发送数据的程序(USART/UART)

    本实验中 STM32通过串口1和串口2上位机对话 xff0c STM32通过串口1在收到上位机发过来的字符串 以回车换行结束 后 xff0c 通过串口2原原本本的返回给上位机 串口 xff08 USART UART xff09 通信配置详解
  • CMakeLists.txt中第三方库编写思考

    编写ROS时经常需要自己构建第三方库或者引用别人的第三方库 xff0c 对于第三方库的调用主要有以下两种方式 xff1a 1 引用现成的第三方库 xff1a find package PCL 1 7 REQUIRED xff1a 添加依赖
  • vscode运行卡顿解决方案

    卡顿原因 主要是rg exe扩展程序占用CPU过高 xff0c 那么只需要禁用它即可 解决方案 打开 vs code xff0c 文件 gt 首选项 gt 设置 gt 搜索 search followSymlinks 取消勾选即可
  • 优象光流模块助力无人机之使用效果分享

    优象光流模块助力无人机之使用效果分享 我是一名无人机爱好者 xff0c 一直以来对无人机就有一种慕名的喜好 xff0c 只要有时间就会与队友们在实验室研究探讨 当然 xff0c 刚开始玩无人机悬停时会遇到种种问题 xff0c 例如飞机一开始
  • 如何使用光流芯片U30实现四轴无人机悬停

    如何使用光流芯片U30实现四轴无人机悬停 在没有GPS的环境下 xff0c 比如室内环境 xff0c 四轴无人机在水平方向会不断漂移 如何让无人机实现稳定的自主悬停呢 xff1f 光流芯片可以感知无人机在水平方向的运动信息 xff08 速度
  • (CMake) 库的生成和链接

    文章目录 前言前置准备当前项目的库静态库动态库 外部项目的库静态库动态库 库的总结总code函数add subdirectory 添加源文件目录add library 指定的源文件生成库target link libraries 为目标链接
  • vscode配置C++编译环境(windows环境下)

    vscode配置C 43 43 编译环境 xff08 windows环境下 xff09 记录下自己在vscode中配置C 43 43 编译环境的过程 xff0c 仅供参考 一 VSCODE MinGW编译器 cMake跨平台编译工具下载 1
  • STL标准库详解

    STL标准库 主要由容器 迭代器 算法组成 STL主要头文件 lt algorithm gt lt deque gt lt functional gt lt iterator gt lt vector gt lt list gt lt ma
  • Mask R-CNN详解(图文并茂)

    Mask R CNN Mask R CNN是一个实例分割 xff08 Instance segmentation xff09 算法 xff0c 主要是在目标检测的基础上再进行分割 Mask R CNN算法主要是Faster R CNN 43
  • python-roslaunch : 依赖: python-roslib 但是它将不会被安装

    在配置环境中将python配置删除类 xff0c 导致ROS系统的好多依赖都没了 安装配置ROS时遇到问题 xff1a 1 先按ROS WIKI上进行安装 xff0c 之后进行测试看是否安装上 2 测试代码 xff1a 第一个终端 xff1
  • pycharm函数调用关系可视化(Graphviz + pycallgraph画图)

    文章目录 介绍Graphviz 安装pycallgraph安装实践 介绍 一个 python project 中往往包含很多 py 文件 python文件中又会包含很多函数 xff0c 函数之间相互传参和调用 如果遇到代码行数很多的情况 x
  • Linux下的UDP通信

    socket 函数 函数说明 xff1a 建立新的socket通信 头文件 xff1a include lt sys socket h gt include lt sys types h gt 函数定义 xff1a int socket i
  • error: array type has incomplete element type ‘int[]‘

    项目场景 xff1a 数组作为函数的形参 问题描述 xff1a error array type has incomplete element type 39 int 39 原因分析 xff1a 多维数组做为函数参数时 xff0c 只可以省
  • 【stm32F1_GPIO初始化函数的参数含义】

    文章目录 前言一 LED 点灯实验二 疑问记录1 问题描述2 问题解决 总结 前言 之前学习过51 xff0c 现在转学32 xff0c 由于课题组需要 xff0c 我需要尽量短的时间内掌握stm32的用法以及Freertos的操作系统 从
  • 使用 curl 命令发送 POST 请求的几种方式

    使用 curl 命令发送 POST 请求的几种方式 HTTP 的 POST 请求通常是用于提交数据 xff0c 可以通过这篇文章来了解各种提交方式 xff1a 常见的 POST 提交数据方式 做 Web 后端开发时 xff0c 不可避免地要
  • Linux环境下GCC以及ELF的初步使用

    Linux环境下可执行程序的安装和GCC以及ELF的初步使用 xff0c 熟悉第三方函数库及游戏程序介绍 一 可执行程序的安装过程1 使用用gcc生成 a静态库与 so动态库文件2 静态库文件的使用3 动态库文件使用 二 gcc编译工具集中
  • 动态库和静态库

    前言 xff1a 库是已写好的 供使用的 可复用代码 xff0c 每个程序都要依赖很多基础的底层库 从本质上 xff0c 库是一种可执行代码的二进制形式 可以被操作系统载入内存执行 库分为两种 xff1a 静态库 xff08 a lib x
  • c++封装yolov4进行目标检测

    yolo4是用c 43 43 写的 xff0c 在工程中的部署特别方便 之前项目中使用yolov4 xff0c 取得了不错的效果 在这里记录一下 使用官方接口调用 xff0c 我们首先得编译darknet动态库 xff0c 下载yolov4