C#封裝YOLOv4算法進行目標檢測

C#封裝YOLOv4算法進行目標檢測

概述

官網:https://pjreddie.com/darknet/
Darknet:【Github】
C#封裝代碼:【Github】git

YOLO: 是實現實時物體檢測的系統,Darknet是基於YOLO的框架
採用C#語言對 YOLOv4 目標檢測算法封裝,將模型在實際應用系統中落地,實現模型在線遠程調用。github

環境準備

本章只講解如何對YOLOv4封裝進行詳解,具體環境安裝過程不作介紹
查看你的GPU計算能力是否支持 >= 3.0:【點擊查看】算法

Windows運行要求數據庫

我所使用的環境app

  • 系統版本: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】框架

使用Gitide

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

代碼結構

將YOLOv4編譯爲DLL

詳細教程:【點擊查看】,這個教程描述的很詳細。工具

進入 darknet\build\darknet 目錄,打開解決方案 yolo_cpp_dll.slnvisual-studio

設置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

  • 一、進入 darknet\build\darknet\x64 目錄,將 pthreadGC2.dllpthreadVC2.dll 拷貝到項目 Dll 文件夾
  • 二、將編譯後的YOLOv4 DLL文件拷貝到項目 Dll 文件夾
  • 三、進入 darknet\build\darknet\x64\cfg 目錄,將 yolov4.cfg 拷貝到項目 Cfg 文件夾
  • 四、進入 darknet\build\darknet\x64\data 目錄,將 coco.names 拷貝到項目 Data 文件夾
  • 五、下載 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

控制檯

相關文章
相關標籤/搜索