C#封装YOLOv4算法进行目标检测

概述

官网:https://pjreddie.com/darknet/

Darknet:【Github】

C#封装代码:【Github】

YOLO: 是实现实时物体检测的系统,Darknet是基于YOLO的框架

采用C#语言对 YOLOv4 目标检测算法封装,将模型在实际应用系统中落地,实现模型在线远程调用。

环境准备

本章只讲解如何对YOLOv4封装进行详解,具体环境安装过程不做介绍

查看你的GPU计算能力是否支持 >= 3.0:【点击查看】

Windows运行要求

我所使用的环境

  • 系统版本: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.dllpthreadVC2.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算法进行目标检测的更多相关文章

  1. 【目标检测】基于传统算法的目标检测方法总结概述 Viola-Jones | HOG+SVM | DPM | NMS

    "目标检测"是当前计算机视觉和机器学习领域的研究热点.从Viola-Jones Detector.DPM等冷兵器时代的智慧到当今RCNN.YOLO等深度学习土壤孕育下的GPU暴力美 ...

  2. 目标检测算法(1)目标检测中的问题描述和R-CNN算法

    目标检测(object detection)是计算机视觉中非常具有挑战性的一项工作,一方面它是其他很多后续视觉任务的基础,另一方面目标检测不仅需要预测区域,还要进行分类,因此问题更加复杂.最近的5年使 ...

  3. 第三十五节,目标检测之YOLO算法详解

    Redmon, J., Divvala, S., Girshick, R., Farhadi, A.: You only look once: Unified, real-time object de ...

  4. Python实现YOLO目标检测

    作者:R语言和Python学堂 链接:https://www.jianshu.com/p/35cfc959b37c 1. 什么是目标检测? YOLO目标检测的一个示例 啥是目标检测? 拿上图 (用YO ...

  5. Faster-rcnn实现目标检测

      Faster-rcnn实现目标检测 前言:本文浅谈目标检测的概念,发展过程以及RCNN系列的发展.为了实现基于Faster-RCNN算法的目标检测,初步了解了RCNN和Fast-RCNN实现目标检 ...

  6. [目标检测]RCNN系列原理

    1 RCNN 1.1 训练过程 (1) 训练时采用fine-tune方式: 先用Imagenet(1000类)训练,再用PASCAL VOC(21)类来fine-tune.使用这种方式训练能够提高8个 ...

  7. [AI开发]目标检测之素材标注

    算力和数据是影响深度学习应用效果的两个关键因素,在算力满足条件的情况下,为了到达更好的效果,我们需要将海量.高质量的素材数据喂给神经网络,训练出高精度的网络模型.吴恩达在深度学习公开课中提到,在算力满 ...

  8. 利用ImageAI库只需几行python代码超简实现目标检测

    目录 什么是目标检测 目标检测算法 Two Stages One Stage python实现 依赖 安装 使用 附录 什么是目标检测 目标检测关注图像中特定的物体目标,需要同时解决解决定位(loca ...

  9. AI佳作解读系列(五) - 目标检测二十年技术综述

    计算机视觉中的目标检测,因其在真实世界的大量应用需求,比如自动驾驶.视频监控.机器人视觉等,而被研究学者广泛关注.   上周四,arXiv新出一篇目标检测文献<Object Detection ...

随机推荐

  1. 解读闭包,这次从ECMAScript词法环境,执行上下文说起

    对于x年经验的前端仔来说,项目也做了好些个了,各个场景也接触过一些.但是假设真的要跟面试官敞开来撕原理,还是有点慌的.看到很多大神都在手撕各种框架原理还是有点羡慕他们的技术实力,羡慕不如行动,先踏踏实 ...

  2. 思维导图概览SpringCloud

    @ 目录 1.什么是微服务 1.1.架构演进 1.2.微服务架构 1.3.微服务解决方案 2.SpringCloud概览 2.1.什么是SpringCloud 2.1.SpringCloud主要组件 ...

  3. HTML基础-01

    HTML:超文本标记语言,是一种使用结构化Web网页(标准制定者:W3C)及其内容的标记语言. 发展过程:XHTML5,HTML5,XHTML1.0,HTML4.01,HTML3.2 HTML5特性: ...

  4. nodejs版本RSA算法封装(SHA1)

    故事背景 看到没写过代码的人聊算法细节装X,真的感觉非常逗,又不好意思戳破人家的表演. 这个世界好奇妙,总有那种看了一些周边普及性书籍就开始好为人师.指点江山,乖乖,放到古代很可能就是赵括,能代替廉颇 ...

  5. 用java编程在10000到99999中的数字中找到aabcc类型的数字

    package com.diyo.offer; public class FindNum { public static void main(String[] args) { int count = ...

  6. 封装Vue Element的form表单组件

    前两天封装了一个基于vue和Element的table表格组件,阅读的人还是很多的,看来大家都是很认同组件化.高复用这种开发模式的,毕竟开发效率高,代码优雅,逼格高嘛.虽然这两天我的心情很糟糕,就像& ...

  7. Java小菜求职记-以前在Dubbo踩的坑,这次全被问到了,这下舒服了

    前传 小林求职记(五)上来就一连串的分布式缓存提问,我有点上头.... 终于,在小林的努力下,获得了王哥公司那边的offer,但是因为薪水没有谈妥,小林又重新进入了求职的旅途,在经历了多次求职过程之后 ...

  8. 区块链入门到实战(24)之以太坊(Ethereum) – 网络节点

    用途: 全节点:用于区块和交易的校验 轻节点:电子钱包 以太坊(Ethereum)网络是一个公共的区块链网络,网络中包含2种网络节点: 全节点 轻节点 全节点 包含了从初始区块开始的全部区块,这些区块 ...

  9. LG P6788 「EZEC-3」四月樱花

    Description 在樱花盛开的四月,Muxii 望着满天飘落的樱花,向身旁的 ZZH 问道: “究竟有多少朵樱花在这个四月飘落?” ZZH 答道:“樱花飘落的朵数  $s$与时间 $t$ 有如下 ...

  10. Helix QAC/QAC++—代码静态测试工具介绍—符合功能安全标准MISRA ISO26262

    Helix QAC是静态代码分析工具,依据C和C++编码规则自动扫描代码对规则的违背.开发团队在开发过程的早期就可以用它来检测缺陷,因为此时修改代码是最方便也最经济的.Helix QAC因此自动化强制 ...