yolov3和yolov4检测效果对比

时间:2022-07-23
本文章向大家介绍yolov3和yolov4检测效果对比,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private const string YoloLibraryName = "yolo_cpp_dll.dll";
        private const int MaxObjects = 1000;
        object ThreadLock = new object();

        [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);
        private static extern int DetectImage(uint width, uint height, IntPtr pArray, int nSize, ref BboxContainer container);

        [DllImport(YoloLibraryName, EntryPoint = "dispose")]
        private static extern int DisposeYolo();



        [StructLayout(LayoutKind.Sequential)]
        public struct BboxContainer
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxObjects)]
            public bbox_t[] candidates;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct bbox_t
        {
            public UInt32 x, y, w, h;    // (x,y) - top-left corner, (w, h) - width & height of bounded box
            public float prob;                 // confidence - probability that the object was found correctly
            public UInt32 obj_id;        // class of object - from range [0, classes-1]
            public UInt32 track_id;      // tracking id for video (0 - untracked, 1 - inf - tracked object)
            public UInt32 frames_counter;
            float x_3d, y_3d, z_3d;        // center of object (in Meters) if ZED 3D Camera is used   必须和yolo_cpp_dll.dll中的定义一一对应
        };
        public Form1()
        {
            InitializeComponent();
            //CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Task.Run(() => InitYolo());
            InitYolo();
        }
        public static void InitYolo()
        {
           InitializeYolo(
                      Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "yolov3.cfg"),
                      Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "yolov3.weights"),
                      0);

        }

        [HandleProcessCorruptedStateExceptions]
        [SecurityCritical]
        public List<bbox_t> Detect(int Width, int Height, 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((uint)Width, (uint)Height, pnt, imageData.Length, ref container);
                if (count == -1)
                {
                    throw new NotSupportedException(" has no OpenCV support");
                }

                List<bbox_t> result = new List<bbox_t>();
                for (int i = 0; i < count; i++)
                {
                    result.Add(container.candidates[i]);
                }
                return result;
            }

            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
                return new List<bbox_t>();
            }
            finally
            {
                // Free the unmanaged memory.
                Marshal.FreeHGlobal(pnt); //不释放内存会报错
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            string[] str = new string[10] { "Camera20200312154951725.jpg" , "Camera20200312155912410.jpg", "Camera20200312155923659.jpg",
                                           "Camera20200312162258694.jpg","Camera20200313100654338.jpg","Camera20200313155526143.jpg",
                                        "Camera20200313161231227.jpg","Camera20200319102951733.jpg","Camera20200319111317754.jpg",
                                          "Camera20200320135659163.jpg"};
            long timeCount = 0;
            object locker = new object();
            for (int i = 0; i < 10; i++)
            {
                //Image<Bgr, byte> img = new Image<Bgr, byte>(@"C:UsersadminsourcereposWindowsFormsApp1WindowsFormsApp1binx64DebugCamera20200421194241118.jpg");
                Image<Bgr, byte> img1 = new Image<Bgr, byte>(@"C:UsersadminDesktop512" + str[i]);
                //Image<Gray, byte> img1 = new Image<Gray, byte>(@"C:UsersadminsourcereposWindowsFormsApp1WindowsFormsApp1binx64DebugDevice20200426191227506.jpg");

                //Mat img2 = CvInvoke.Imread(@"C:UsersadminsourcereposWindowsFormsApp1WindowsFormsApp1binx64DebugCamera20200421194241118.jpg", Emgu.CV.CvEnum.LoadImageType.Grayscale);

                int Width, Height;
                Width = img1.Width;
                Height = img1.Height;
                while (Width % 4 != 0)
                {
                    Width++;
                }
                CvInvoke.Resize(img1, img1, new Size(Width, Height), 0, 0, Inter.Lanczos4);
                //Matrix<byte> showImage = new Matrix<byte>(img1.Height, img1.Width, 3);
                //Matrix<byte> showImage = new Matrix<byte>(img1.Height, img1.Width, img1.Bytes[img1.Height* img1.Width*]);
                //CvInvoke.CvtColor(img1, showImage, ColorConversion.Gray2Bgr);

                List<bbox_t> bboxes = new List<bbox_t>();

                lock (ThreadLock)                       //锁线程  
                {
                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    bboxes = Detect(img1.Height, img1.Width, img1.Bytes);
                    sw.Stop();
                    //MessageBox.Show(sw.ElapsedMilliseconds.ToString() + "毫秒");
                    timeCount += sw.ElapsedMilliseconds;
                }
                if (bboxes.ToArray().Length != 0)
                {
                    //MessageBox.Show("1111");
                }

                foreach (var bbox in bboxes)
                {
                    //detectobject newobj = new detectobject();
                    var color_red = new MCvScalar(0, 0, 255); // BGR
                    var color_green = new MCvScalar(0, 255, 0);
                    var color_yellow = new MCvScalar(0, 255, 255);
                    Rectangle rect = new Rectangle((int)bbox.x, (int)bbox.y, (int)bbox.w, (int)bbox.h);
                    if (bbox.obj_id == 0)
                    {
                        // IsWarning = true;
                        CvInvoke.Rectangle(img1, rect, color_yellow);
                        //string hiddenMsg = labels[(int)bbox.obj_id] + "," + bbox.prob.ToString("0.00");
                        //CvInvoke.PutText(showImage, hiddenMsg, rect.Location, FontFace.HersheyComplex, 0.8, color_red);
                    }
                    else if (bbox.obj_id == 1)
                    {
                        //IsWarning = true;
                        CvInvoke.Rectangle(img1, rect, color_green);
                        //string hiddenMsg = labels[(int)bbox.obj_id] + "," + bbox.prob.ToString("0.00");
                        //CvInvoke.PutText(showImage, hiddenMsg, rect.Location, FontFace.HersheyComplex, 0.8, color_green);
                    }
                    else
                    {
                        //IsWarning = true;
                        CvInvoke.Rectangle(img1, rect, color_red);
                        //string hiddenMsg = labels[(int)bbox.obj_id] + "," + bbox.prob.ToString("0.00");
                        //CvInvoke.PutText(showImage, hiddenMsg, rect.Location, FontFace.HersheyComplex, 0.8, color_green);

                    }
                }
                Task.Run(() =>
                 {
                     lock (locker)
                     {
                         Thread.Sleep(1000);
                         pictureBox1.Image = img1.Mat.Bitmap;
                         //this.BeginInvoke(new Action(() => { pictureBox1.Image = showImage.Mat.Bitmap; }));
                     }
            });
            }
            label1.Text = (timeCount / 10).ToString() + "毫秒";
        }
    }
}

结果:

结论:

测试10张图片,计算平均耗时: yolo_cpp_dll.dll 自己编译生成的 yolov3 18ms 100% yolov3-tiny 5ms 检出率60% 比较节省gup资源 yolov4 35ms 检出率90%

yolo_cpp_dll_gpu.dll--旧版的dll,以前同事留下的 yolov3 19ms 70% yolov3-tiny 6ms 检出率40% yolov4 34ms 检出率0%

结论:dll对测试效果也有影响,yolov3-tiny检出速度快但是检出率不高,yolov4虽然做了优化,但是在耗时和检出率上反而下降了 ,原因不详!