.net 多个dll 封装成一个dll_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

代码结构

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第1张图片

将YOLOv4编译为DLL

详细教程:【点击查看】,这个教程描述的很详细。

进入 darknetbuilddarknet 目录,打开解决方案 yolo_cpp_dll.sln

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第2张图片

设置Windows SDK版本和平台工具集为当前系统安装版本

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第3张图片

设置Release和x64

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第4张图片

然后执行以下操作:Build-> Build yolo_cpp_dll

已完成生成项目“yolo_cpp_dll.vcxproj”的操作。
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

在打包DLL的过程中可能遇到如下问题

C1041
无法打开程序数据库“D:代码管理Cdarknetbuilddarknetx64DLL_Releasevc142.pdb”;如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用 /FS    yolo_cpp_dll    C:UsersadministratorAppDataLocalTemptmpxft_00005db0_00000000-6_dropout_layer_kernels.compute_75.cudafe1.cpp   1
MSB3721 
命令“"C:Program FilesNVIDIA GPU Computing ToolkitCUDAv10.1binnvcc.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 Studio2019CommunityVCToolsMSVC14.27.29110binHostX86x64" -x cu  -IC:opencvbuildinclude -IC:opencv_3.0opencvbuildinclude -I....include -I....3rdpartystbinclude -I....3rdpartypthreadsinclude -I"C:Program FilesNVIDIA GPU Computing ToolkitCUDAv10.1include" -I"C:Program FilesNVIDIA GPU Computing ToolkitCUDAv10.1include" -Iinclude -Iinclude -I"C:Program FilesNVIDIA GPU Computing ToolkitCUDAv10.1include"     --keep-dir x64Release -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 /Fdx64DLL_Releasevc142.pdb  /Zi  /MD " -o x64DLL_Releasedropout_layer_kernels.cu.obj "D:darknetsrcdropout_layer_kernels.cu"”已退出,返回代码为 2。   yolo_cpp_dll    C:Program Files (x86)Microsoft Visual Studio2019CommunityMSBuildMicrosoftVCv160BuildCustomizationsCUDA 10.1.targets   757

解决方法

在VS 2019 工具》选项》项目和解决方案》生成并运行 中最大并行项目生成数设为 1

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第5张图片

在VS 2019 项目-》属性-》配置属性-》常规 将Windows SDK版本设置为系统当前版本即可

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第6张图片

封装YOLOv4编译后的DLL

  • 1、进入 darknetbuilddarknetx64 目录,将 pthreadGC2.dllpthreadVC2.dll 拷贝到项目 Dll 文件夹
  • 2、将编译后的YOLOv4 DLL文件拷贝到项目 Dll 文件夹
  • 3、进入 darknetbuilddarknetx64cfg 目录,将 yolov4.cfg 拷贝到项目 Cfg 文件夹
  • 4、进入 darknetbuilddarknetx64data 目录,将 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 封装文件

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第7张图片

代码

YOLOv4封装项目

YoloWrapper.cs - 封装主文件,调用 YOLOv4 的动态链接库

using System;
using System.Runtime.InteropServices;

namespace YoloWrapper
{

    public class YoloWrapper : IDisposable
    {
        private const string YoloLibraryName = @"Dllsyolo_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 = @".Cfgyolov4.cfg";
        private const string weightsFilename = @".Weightsyolov4.weights";
        private const string namesFile = @".Datacoco.names";

        private static Dictionary _namesDic = new Dictionary();

        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);
        }
    }
}

测试返回结果

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第8张图片

控制台

.net 多个dll 封装成一个dll_C#封装YOLOv4算法进行目标检测_第9张图片

你可能感兴趣的:(.net,多个dll,封装成一个dll,c#,c++6.0,图标封装dll,c++封装exe,qt如何把dll封装到exe中)