C#调用YOLOv3算法dll动态链接库(YOLO算法落地)

C#调用YOLOv3算法dll动态链接库

前段时间在搞一个软件,目标是实现细胞计数的功能,当时我细胞计数的算法用到的是YOLOv3目标检测算法,所以就涉及到怎么实现模型落地的问题。当时有个同学在帮老师做项目,他比较懂,我于是向他寻求帮助,但是…可能涉及到了商业机密吧,于是我就自己研究。
我看了很多博客,感觉讲的也不是很到位,或者说没有给出一些干货,今天我来给大家带点干货,当然我是用**C#**调用的YOLOv3动态链接库,如果有需要的小伙伴就拿去吧。

yolov3编译成动态库

大家按照这个链接去GitHub下载YOLOv3的源码:https://github.com/AlexeyAB/darknet?tdsourcetag=s_pcqq_aiomsg.我是按照这个教程做的:https://zhuanlan.zhihu.com/p/97605980,这个教程还是很详细的,我就不讲了。

C#调用YOLOv3动态链接库

我已经将软件打包到GitHub上了:https://github.com/NameZth/AICounter-master.git,由于YOLOv3的权重文件和配置文件太大就没有上传,所以需要小伙伴自己训练一下模型. 当然我也是参考别人做的:https://github.com/RaminAbbaszadi/YoloWrapper-WPF,下面是文件的分布:
在这里插入图片描述在***DeepLearningWrapper***这个文件中调用的YOLOv3的动态链接库:

using System;
using System.IO;
using System.Text;
using System.Linq;
using DeepLearning.Base;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace DeepLearning
{
    public class DeepLearningWrapper : IDisposable
    {
        #region Const

        public const int MAX_OBJECTS_NUMBER = 1000;
        private const string DEEP_LEARNING_LIBRARY_DLL_CPU_VERSION = @"\x64\yolo_cpp_dll.dll";
        private const string DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION = @"\x64\yolo_cpp_gpu.dll";

        #endregion

        #region Fields

        private static Dictionary<int, string> m_ObjectType = new Dictionary<int, string>();
        private static NetConfigaration m_NetConf;

        #endregion

        #region Initilizing

        public DeepLearningWrapper()
        {
        }

        #endregion

        #region DllImport Cpu

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_CPU_VERSION, EntryPoint = "init")]
        public static extern int InitializeNetInCpu(string configrationFilenamr, string weightFileanme, int gpu);

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_CPU_VERSION, EntryPoint = "detect_image")]
        internal static extern int DetectImageInCpu(string filename, ref BoundingBoxContainer container);

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_CPU_VERSION, EntryPoint = "detect_mat")]
        internal static extern int DetectImageInCpu(IntPtr pArray, int nSize, ref BoundingBoxContainer container);

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_CPU_VERSION, EntryPoint = "dispose")]
        internal static extern int DisposeNetInCpu();

        #endregion

        #region DllImport Gpu

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION, EntryPoint = "init")]
        internal static extern int InitializeNetInGpu(string configurationFilename, string weightsFilename, int gpu);

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION, EntryPoint = "detect_image")]
        internal static extern int DetectImageInGpu(string filename, ref BoundingBoxContainer container);

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION, EntryPoint = "detect_mat")]
        internal static extern int DetectImageInGpu(IntPtr pArray, int nSize, ref BoundingBoxContainer container);

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION, EntryPoint = "dispose")]
        internal static extern int DisposeNetInGpu();

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION, EntryPoint = "get_device_count")]
        internal static extern int GetDeviceCount();

        [DllImport(DEEP_LEARNING_LIBRARY_DLL_GPU_VERSION, EntryPoint = "get_device_name")]
        internal static extern int GetDeviceName(int gpu, StringBuilder deviceName);

        #endregion

        #region Dispose

        public void Dispose()
        {
            switch (DetectionHardware)
            {
                case DetectionHardwares.CPU:
                    DisposeNetInCpu();
                    break;
                case DetectionHardwares.GPU:
                    DisposeNetInGpu();
                    break;
            }
        }

        #endregion

        #region Wrapper

        public void InitilizeDeepLearningNetwork(int gpu = 0)
        {
            if (m_NetConf == null)
                m_NetConf = new NetConfigaration();

            HardwareReport = new HardwareReports();

            DetectionHardware = DetectionHardwares.CPU;
            if (HardwareReport.IsCudaExists && HardwareReport.IsCudnnExists)
                DetectionHardware = DetectionHardwares.GPU;

            switch (DetectionHardware)
            {
                case DetectionHardwares.CPU:
                    InitializeNetInCpu(m_NetConf.ConfigFile, m_NetConf.Weightfile, 0);
                    break;
                case DetectionHardwares.GPU:
                    var deviceCount = GetDeviceCount();
                    if (gpu > (deviceCount - 1))
                        throw new IndexOutOfRangeException("Graphic device index is out of range");
                    var deviceName = new StringBuilder();
                    GetDeviceName(gpu, deviceName);
                    HardwareReport.GraphicDeviceName = deviceName.ToString();
                    InitializeNetInGpu(m_NetConf.ConfigFile, m_NetConf.Weightfile, gpu);
                    break;
                default:
                    break;
            }

            var lines = File.ReadAllLines(m_NetConf.NamesFile);
            for (var i = 0; i < lines.Length; i++)
                m_ObjectType.Add(i, lines[i]);
        }


        public IEnumerable<DetectedItemInfo> Detect(string imageFilePath)
        {
            if (!File.Exists(imageFilePath))
                throw new FileNotFoundException("Cannot find the file", imageFilePath);

            var container = new BoundingBoxContainer();
            var count = 0;
            switch (DetectionHardware)
            {
                case DetectionHardwares.CPU:
                    count = DetectImageInCpu(imageFilePath, ref container);
                    break;
                case DetectionHardwares.GPU:
                    count = DetectImageInGpu(imageFilePath, ref container);
                    break;
            }

            return Convert(container);
        }

        public IEnumerable<DetectedItemInfo> Detect(byte[] imageData)
        {
            var container = new BoundingBoxContainer();

            var size = Marshal.SizeOf(imageData[0]) * imageData.Length;
            var pnt = Marshal.AllocHGlobal(size);

            try
            {
                // Copy the array to unmanaged memory.
                Marshal.Copy(imageData, 0, pnt, imageData.Length);
                var count = 0;
                switch (DetectionHardware)
                {
                    case DetectionHardwares.CPU:
                        count = DetectImageInCpu(pnt, imageData.Length, ref container);
                        break;
                    case DetectionHardwares.GPU:
                        count = DetectImageInGpu(pnt, imageData.Length, ref container);
                        break;
                }
            }
            catch (Exception exception)
            {
                return null;
            }
            finally
            {
                // Free the unmanaged memory.
                Marshal.FreeHGlobal(pnt);
            }

            return Convert(container);
        }

        #endregion

        #region Utilities

        private IEnumerable<DetectedItemInfo> Convert(BoundingBoxContainer container)
        {
            var netItems = new List<DetectedItemInfo>();
            foreach (var item in container.candidates.Where(o => o.height > 0 || o.width > 0))
            {
                var objectType = m_ObjectType[(int)item.obj_id];
                var netItem = new DetectedItemInfo() { X = (int)item.leftTopX, Y = (int)item.leftTopY, Height = (int)item.height, Width = (int)item.width, Confidence = item.prob, Type = objectType };
                netItems.Add(netItem);
            }

            return netItems;
        }

        #endregion

        #region Properties

        public DetectionHardwares DetectionHardware = DetectionHardwares.Unknown;
        public HardwareReports HardwareReport { get; private set; }

        #endregion
    }
}

然后就是在其他软件中类的定义:
***BoundingBox***文件:

using System;

namespace DeepLearning
{
    internal struct BoundingBox
    {
        #region Fields

        internal UInt32 leftTopX, leftTopY, width, height;
        internal float prob;
        internal UInt32 obj_id;
        internal UInt32 track_id;
        internal UInt32 frames_counter;
        
        #endregion
    }
}

***BoundingBoxContainer***文件:

using System.Runtime.InteropServices;

namespace DeepLearning
{
    [StructLayout(LayoutKind.Sequential)]
    internal struct BoundingBoxContainer
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = DeepLearningWrapper.MAX_OBJECTS_NUMBER)]
        internal BoundingBox[] candidates;
    }
}

***DetectedItemInfo***文件:

namespace DeepLearning
{
    public class DetectedItemInfo
    {
        #region Properties

        public string Type { get; set; }
        public double Confidence { get; set; }
        public int X { get; set; }
        public int Y { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }

        #endregion

        #region Utilities

        public bool Compare(DetectedItemInfo newItem)
        {
            bool result = false;
            if (newItem != null)
            {
                if (newItem.Type == this.Type && newItem.Confidence == this.Confidence &&
                    newItem.X == this.X && newItem.Y == this.Y && newItem.Width == this.Width &&
                    newItem.Height == this.Height)
                {
                    result = true;
                }
            }
            return result;
        }

        #endregion
    }
}
HardwareReports文件:
using System;
using System.IO;

namespace DeepLearning
{
    public class HardwareReports
    {
        #region Initilizing

        public HardwareReports()
        {
            Init();
        }

        private void Init()
        {
            if (File.Exists(@"x64\cudnn64_7.dll"))
               IsCudnnExists = true;

            var envirormentVariables = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
            if (envirormentVariables.Contains("CUDA_PATH"))
                IsCudaExists = true;

        }

        #endregion

        #region Properties

        public bool IsCudaExists { get; set; }
        public bool IsCudnnExists { get; set; }
        public string GraphicDeviceName { get; set; }

        #endregion
    }
}

NetConfigaration文件:

namespace DeepLearning
{
    public class NetConfigaration
    {
        #region Const

        private const string CONFIG_FILE_PATH = @"Assets\Aalskidhytd.cfg";
        private const string WEIGHT_FILE_PATH = @"Assets\Aalskidhytd.weights";
        private const string NAMES_FILE_PATH  = @"Assets\Aalskidhytd.names";

        #endregion

        #region Initilizing

        public NetConfigaration()
        {
            Init();
        }

        private void Init()
        {
            ConfigFile = CONFIG_FILE_PATH;
            Weightfile = WEIGHT_FILE_PATH;
            NamesFile  = NAMES_FILE_PATH;
        }

        #endregion

        #region Properties

        public string ConfigFile { get; set; }
        public string Weightfile { get; set; }
        public string NamesFile { get; set; }

        #endregion
    }
}

软件界面展示(检测的精度不是很高):
在这里插入图片描述

  • 12
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 29
    评论
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值