C#封装YOLOv4算法进行目标检测
C#封装YOLOv4算法进行目标检测
概述
官网:https://pjreddie.com/darknet/
Darknet:【Github】
C#封装代码:【Github】
YOLO: 是实现实时物体检测的系统,Darknet是基于YOLO的框架
采用C#语言对 YOLOv4 目标检测算法封装,将模型在实际应用系统中落地,实现模型在线远程调用。
环境准备
本章只讲解如何对YOLOv4封装进行详解,具体环境安装过程不做介绍
查看你的GPU计算能力是否支持 >= 3.0:【点击查看】
Windows运行要求
- CMake >= 3.12: 【点击下载】
- CUDA >= 10.0: 【点击下载】
- OpenCV >= 2.4: 【点击下载】
- cuDNN >= 7.0: 【点击下载】
- Visual Studio 2017/2019: 【点击下载】
我所使用的环境
- 系统版本:Windows 10 专业版
- 显卡:GTX 1050 Ti
- CMake版本:3.18.2
- CUDA版本:10.1
- OpenCV版本:4.4.0
- cuDNN版本:10.1
- MSVC 2017/2019: Visual Studio 2019
程序代码准备
源代码下载
下载地址:【Darknet】
使用Git
git clone https://github.com/AlexeyAB/darknet
cd darknet
代码结构
将YOLOv4编译为DLL
详细教程:【点击查看】,这个教程描述的很详细。
进入 darknet\build\darknet
目录,打开解决方案 yolo_cpp_dll.sln
设置Windows SDK版本和平台工具集为当前系统安装版本
设置Release和x64
然后执行以下操作:Build-> Build yolo_cpp_dll
已完成生成项目“yolo_cpp_dll.vcxproj”的操作。
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
在打包DLL的过程中可能遇到如下问题
C1041
无法打开程序数据库“D:\代码管理\C\darknet\build\darknet\x64\DLL_Release\vc142.pdb”;如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用 /FS yolo_cpp_dll C:\Users\administrator\AppData\Local\Temp\tmpxft_00005db0_00000000-6_dropout_layer_kernels.compute_75.cudafe1.cpp 1
MSB3721
命令“"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\nvcc.exe" -gencode=arch=compute_30,code=\"sm_30,compute_30\" -gencode=arch=compute_75,code=\"sm_75,compute_75\" --use-local-env -ccbin "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX86\x64" -x cu -IC:\opencv\build\include -IC:\opencv_3.0\opencv\build\include -I..\..\include -I..\..\3rdparty\stb\include -I..\..\3rdparty\pthreads\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include" -I\include -I\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include" --keep-dir x64\Release -maxrregcount=0 --machine 64 --compile -cudart static -DCUDNN_HALF -DCUDNN -DGPU -DLIB_EXPORTS -D_TIMESPEC_DEFINED -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DWIN32 -DNDEBUG -D_CONSOLE -D_LIB -D_WINDLL -D_MBCS -Xcompiler "/EHsc /W3 /nologo /O2 /Fdx64\DLL_Release\vc142.pdb /Zi /MD " -o x64\DLL_Release\dropout_layer_kernels.cu.obj "D:\darknet\src\dropout_layer_kernels.cu"”已退出,返回代码为 2。 yolo_cpp_dll C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\BuildCustomizations\CUDA 10.1.targets 757
解决方法
在VS 2019 工具》选项》项目和解决方案》生成并运行
中最大并行项目生成数设为 1
在VS 2019 项目-》属性-》配置属性-》常规
将Windows SDK版本设置为系统当前版本即可
封装YOLOv4编译后的DLL
- 1、进入
darknet\build\darknet\x64
目录,将pthreadGC2.dll
和pthreadVC2.dll
拷贝到项目Dll
文件夹 - 2、将编译后的YOLOv4 DLL文件拷贝到项目
Dll
文件夹 - 3、进入
darknet\build\darknet\x64\cfg
目录,将yolov4.cfg
拷贝到项目Cfg
文件夹 - 4、进入
darknet\build\darknet\x64\data
目录,将coco.names
拷贝到项目Data
文件夹 - 5、下载 yolov4.weights 权重文件 拷贝到
Weights
文件夹,文件245 MB 【点击下载】
项目文件
代码下载:【Github】
YoloWrapper
- YOLOv4封装项目Cfg
- 配置文件夹Data
- label文件夹Dll
- YOLOv4 编译后的DLL文件夹Weights
- YOLOv4 权重文件夹BboxContainer.cs
BoundingBox.cs
YoloWrapper.cs
- 封装主文件,调用 YOLOv4 的动态链接库
YoloWrapperConsole
- 调用封装DLL控制台程序Program.cs
- 控制台主程序,调用 YOLOv4 封装文件
代码
YOLOv4封装项目
YoloWrapper.cs
- 封装主文件,调用 YOLOv4 的动态链接库
using System;
using System.Runtime.InteropServices;
namespace YoloWrapper
{
public class YoloWrapper : IDisposable
{
private const string YoloLibraryName = @"\Dlls\yolo_cpp_dll.dll";
[DllImport(YoloLibraryName, EntryPoint = "init")]
private static extern int InitializeYolo(string configurationFilename, string weightsFilename, int gpu);
[DllImport(YoloLibraryName, EntryPoint = "detect_image")]
private static extern int DetectImage(string filename, ref BboxContainer container);
[DllImport(YoloLibraryName, EntryPoint = "detect_mat")]
private static extern int DetectImage(IntPtr pArray, int nSize, ref BboxContainer container);
[DllImport(YoloLibraryName, EntryPoint = "dispose")]
private static extern int DisposeYolo();
public YoloWrapper(string configurationFilename, string weightsFilename, int gpu)
{
InitializeYolo(configurationFilename, weightsFilename, gpu);
}
public void Dispose()
{
DisposeYolo();
}
public BoundingBox[] Detect(string filename)
{
var container = new BboxContainer();
var count = DetectImage(filename, ref container);
return container.candidates;
}
public BoundingBox[] Detect(byte[] imageData)
{
var container = new BboxContainer();
var size = Marshal.SizeOf(imageData[0]) * imageData.Length;
var pnt = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(imageData, 0, pnt, imageData.Length);
var count = DetectImage(pnt, imageData.Length, ref container);
if (count == -1)
{
throw new NotSupportedException($"{YoloLibraryName} has no OpenCV support");
}
}
catch (Exception exception)
{
return null;
}
finally
{
Marshal.FreeHGlobal(pnt);
}
return container.candidates;
}
}
}
BboxContainer.cs
using System.Runtime.InteropServices;
namespace YoloWrapper
{
[StructLayout(LayoutKind.Sequential)]
public struct BboxContainer
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
public BoundingBox[] candidates;
}
}
BoundingBox.cs
using System;
using System.Runtime.InteropServices;
namespace YoloWrapper
{
[StructLayout(LayoutKind.Sequential)]
public struct BoundingBox
{
public UInt32 x, y, w, h;
public float prob;
public UInt32 obj_id;
public UInt32 track_id;
public UInt32 frames_counter;
public float x_3d, y_3d, z_3d;
}
}
调用封装DLL控制台程序
BoundingBox.cs
using ConsoleTables;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using YoloWrapper;
namespace YoloWrapperConsole
{
class Program
{
private const string configurationFilename = @".\Cfg\yolov4.cfg";
private const string weightsFilename = @".\Weights\yolov4.weights";
private const string namesFile = @".\Data\coco.names";
private static Dictionary<int, string> _namesDic = new Dictionary<int, string>();
private static YoloWrapper.YoloWrapper _wrapper;
static void Main(string[] args)
{
Initilize();
Console.Write("ImagePath:");
string imagePath = Console.ReadLine();
var bbox = _wrapper.Detect(imagePath);
Convert(bbox);
Console.ReadKey();
}
private static void Initilize()
{
_wrapper = new YoloWrapper.YoloWrapper(configurationFilename, weightsFilename, 0);
var lines = File.ReadAllLines(namesFile);
for (var i = 0; i < lines.Length; i++)
_namesDic.Add(i, lines[i]);
}
private static void Convert(BoundingBox[] bbox)
{
Console.WriteLine("Result:");
var table = new ConsoleTable("Type", "Confidence", "X", "Y", "Width", "Height");
foreach (var item in bbox.Where(o => o.h > 0 || o.w > 0))
{
var type = _namesDic[(int)item.obj_id];
table.AddRow(type, item.prob, item.x, item.y, item.w, item.h);
}
table.Write(Format.MarkDown);
}
}
}
测试返回结果
Type | Confidence | X | Y | Width | Height |
---|---|---|---|---|---|
mouse | 0.25446844 | 1206 | 633 | 78 | 30 |
laptop | 0.5488589 | 907 | 451 | 126 | 148 |
laptop | 0.51734066 | 688 | 455 | 53 | 37 |
laptop | 0.48207012 | 980 | 423 | 113 | 99 |
person | 0.58085686 | 429 | 293 | 241 | 469 |
bottle | 0.22032459 | 796 | 481 | 43 | 48 |
bottle | 0.24873751 | 659 | 491 | 32 | 53 |
cup | 0.5715177 | 868 | 453 | 55 | 70 |
bottle | 0.29916075 | 1264 | 459 | 31 | 89 |
cup | 0.2782725 | 685 | 503 | 35 | 40 |
cup | 0.28154427 | 740 | 539 | 78 | 44 |
person | 0.94347733 | 81 | 199 | 541 | 880 |
person | 0.9496539 | 1187 | 368 | 233 | 155 |
chair | 0.22458112 | 624 | 442 | 45 | 48 |
person | 0.97528315 | 655 | 389 | 86 | 100 |
bottle | 0.9407686 | 1331 | 436 | 33 | 107 |
bottle | 0.9561032 | 1293 | 434 | 37 | 113 |
chair | 0.4784215 | 1 | 347 | 386 | 730 |
cup | 0.8945817 | 822 | 586 | 112 | 69 |
cup | 0.6422996 | 1265 | 472 | 31 | 72 |
laptop | 0.9833646 | 802 | 700 | 639 | 216 |
cup | 0.9216428 | 828 | 521 | 115 | 71 |
chair | 0.88087356 | 1124 | 416 | 111 | 70 |
diningtable | 0.3222557 | 531 | 585 | 951 | 472 |
控制台
C#封装YOLOv4算法进行目标检测的更多相关文章
- 【目标检测】基于传统算法的目标检测方法总结概述 Viola-Jones | HOG+SVM | DPM | NMS
"目标检测"是当前计算机视觉和机器学习领域的研究热点.从Viola-Jones Detector.DPM等冷兵器时代的智慧到当今RCNN.YOLO等深度学习土壤孕育下的GPU暴力美 ...
- 目标检测算法(1)目标检测中的问题描述和R-CNN算法
目标检测(object detection)是计算机视觉中非常具有挑战性的一项工作,一方面它是其他很多后续视觉任务的基础,另一方面目标检测不仅需要预测区域,还要进行分类,因此问题更加复杂.最近的5年使 ...
- 第三十五节,目标检测之YOLO算法详解
Redmon, J., Divvala, S., Girshick, R., Farhadi, A.: You only look once: Unified, real-time object de ...
- Python实现YOLO目标检测
作者:R语言和Python学堂 链接:https://www.jianshu.com/p/35cfc959b37c 1. 什么是目标检测? YOLO目标检测的一个示例 啥是目标检测? 拿上图 (用YO ...
- Faster-rcnn实现目标检测
Faster-rcnn实现目标检测 前言:本文浅谈目标检测的概念,发展过程以及RCNN系列的发展.为了实现基于Faster-RCNN算法的目标检测,初步了解了RCNN和Fast-RCNN实现目标检 ...
- [目标检测]RCNN系列原理
1 RCNN 1.1 训练过程 (1) 训练时采用fine-tune方式: 先用Imagenet(1000类)训练,再用PASCAL VOC(21)类来fine-tune.使用这种方式训练能够提高8个 ...
- [AI开发]目标检测之素材标注
算力和数据是影响深度学习应用效果的两个关键因素,在算力满足条件的情况下,为了到达更好的效果,我们需要将海量.高质量的素材数据喂给神经网络,训练出高精度的网络模型.吴恩达在深度学习公开课中提到,在算力满 ...
- 利用ImageAI库只需几行python代码超简实现目标检测
目录 什么是目标检测 目标检测算法 Two Stages One Stage python实现 依赖 安装 使用 附录 什么是目标检测 目标检测关注图像中特定的物体目标,需要同时解决解决定位(loca ...
- AI佳作解读系列(五) - 目标检测二十年技术综述
计算机视觉中的目标检测,因其在真实世界的大量应用需求,比如自动驾驶.视频监控.机器人视觉等,而被研究学者广泛关注. 上周四,arXiv新出一篇目标检测文献<Object Detection ...
随机推荐
- 2020-05-21:es底层读写原理?倒排索引原理?
福哥答案2020-05-21: es不熟悉,答案仅供参考:es写数据过程1.客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)2.coordinatin ...
- Spring Boot 应用程序启动流程分析
SpringBoot 有两个关键元素: @SpringBootApplicationSpringApplication 以及 run() 方法 SpringApplication 这个类应该算是 Sp ...
- Js~对键值对操作
键值对主要是面向对象语言里的字典,或者叫哈希表,它通过键(key)可以直接访问到值(value),所以它查找的时间复杂度是O(1),即一次查找即可找到目标:在.net里有Dictionary,而在ja ...
- 三、HelloWorld
1.创建Hello.java 文件, 2.输入内容 public class Hello{ //公共类 Hello public static void main(String[] args){ // ...
- 震惊!ConcurrentHashMap里面也有死循环,作者留的“彩蛋”?
JDK BUG 这篇文章,聊一下我最近才知道的一个关于 JDK 8 的 BUG 吧. 首先说一下我是怎么发现这个 BUG 的呢? 大家都知道我对 Dubbo 有一定的关注,前段时间 Dubbo 2.7 ...
- 阿里云体验实验室 教你如何《快速搭建LNMP环境》
## 体验平台简介 面向开发者和中小企业打造的一站式.全云端的开发平台,打开浏览器就可以开发.调试.上线,所测即所得,并结合无服务器的模式,重新定义云原生时代的研发工作方法论.旨在降低开发者上手成本和 ...
- 使用对称加密来加密Spring Cloud Config配置文件
补充 使用Spring Cloud Config加密功能需要下载JCE扩展,用于生成无限长度的密文.链接:http://www.oracle.com/technetwork/java/javase/d ...
- 技术分享丨数据仓库的建模与ETL实践技巧
摘要:如何搭建数据仓库,在这个过程中都应该遵循哪些方法和原则,项目实践中有哪些技巧. 一.数据仓库的“心脏” 首先来谈谈数据模型.模型是现实世界特征的模拟和抽象,比如地图.建筑设计沙盘,飞机模型等等. ...
- 谈谈BUG严重级别(severity)管理
在软件工程理论中,BUG严重级别(severity)是用于指示软件质量问题导致的负面影响的程度.但在大部分实际的软件开发组织中,对BUG严重级别(severity)的定义和使用常常充斥着大量的争议和分 ...
- centos7上借助于xargs快速查询并卸载rpm软件
在centos上卸载某些软件的时候,如果查询的软件包比较多,可以考虑使用xargs,边查询边卸载 如:下面在查询mysql包时候,将查询结果通过管道传送给xargs,然后使用rpm -e --node ...