C# YoloV8 OpenVINO 视频抽帧 自动标注 预标注工具

效果

3447c892493922adb9ae253f1b1e5488.png

项目

60c99680ab96b8540884aada751eb0ca.png

代码

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace yolov8_OpenVINO_Demo
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
 
        YoloV8 yoloV8;
        YoloV8Async yoloV8Async;
 
        string model_path;
 
        string video_path = "";
        string video_name = "";
        string videoFilter = "*.mp4|*.mp4;";
        VideoCapture vcapture;
 
        string output_path = "";
        string images_path = "";
        string labels_path = "";
 
 
        StringBuilder sb = new StringBuilder();
 
        /// <summary>
        /// 窗体加载,初始化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            model_path = "model/yolov8n.onnx";
            yoloV8 = new YoloV8(model_path, "model/lable.txt");
 
            yoloV8Async = new YoloV8Async(model_path, "model/lable.txt");
        }
 
        /// <summary>
        /// 选择输出目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            output_path = "";
            using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
            {
                folderBrowserDialog.Description = "选择目录";
                DialogResult dialogResult = folderBrowserDialog.ShowDialog();
                if (dialogResult == DialogResult.OK)
                {
                    output_path = folderBrowserDialog.SelectedPath;
 
                }
            }
        }
 
        /// <summary>
        /// 选择视频
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = videoFilter;
            ofd.InitialDirectory = Application.StartupPath + "\\test";
            if (ofd.ShowDialog() != DialogResult.OK) return;
 
            video_path = ofd.FileName;
            video_name = System.IO.Path.GetFileNameWithoutExtension(video_path);
            textBox1.Text = "";
 
        }
 
        /// <summary>
        /// 同步接口-视频推理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            if (video_path == "")
            {
                MessageBox.Show("请先选择视频!");
                return;
            }
 
            if (output_path == "")
            {
                MessageBox.Show("请先选择输出目录!");
                return;
            }
 
            images_path = output_path + "\\output\\images";
            labels_path = output_path + "\\output\\labels";
 
            if (!Directory.Exists(images_path))
            {
                Directory.CreateDirectory(images_path);
            }
 
            if (!Directory.Exists(labels_path))
            {
                Directory.CreateDirectory(labels_path);
            }
 
            sb.Clear();
            sb.AppendLine($"images path:{images_path}");
            sb.AppendLine($"labels path:{labels_path}");
 
            textBox1.Text = sb.ToString();
 
            Application.DoEvents();
 
            Thread thread = new Thread(new ThreadStart(VideoDetection));
 
            thread.Start();
            thread.Join();
 
            textBox1.Text = "检测完成!";
        }
 
        void VideoDetection()
        {
            vcapture = new VideoCapture(video_path);
            if (!vcapture.IsOpened())
            {
                MessageBox.Show("打开视频文件失败");
                return;
            }
 
            Mat frame = new Mat();
            List<DetectionResult> detResults;
 
            // 获取视频的fps
            double videoFps = vcapture.Get(VideoCaptureProperties.Fps);
            // 计算等待时间(毫秒)
            int delay = (int)(1000 / videoFps);
            Stopwatch _stopwatch = new Stopwatch();
 
            int frameCount = (int)vcapture.Get(VideoCaptureProperties.FrameCount);
 
            Cv2.NamedWindow("DetectionResult 按下ESC,退出", WindowFlags.Normal);
            Cv2.ResizeWindow("DetectionResult 按下ESC,退出", vcapture.FrameWidth / 2, vcapture.FrameHeight / 2);
 
            int FrameWidth = vcapture.FrameWidth;
            int FrameHeight = vcapture.FrameHeight;
            int index = 0;
 
            while (vcapture.Read(frame))
            {
                if (frame.Empty())
                {
                    MessageBox.Show("读取失败");
                    return;
                }
 
                _stopwatch.Restart();
 
                delay = (int)(1000 / videoFps);
 
                detResults = yoloV8.Detect(frame);
 
                //输出图片
                Task.Factory.StartNew(() =>
                {
                    Cv2.ImWrite(images_path + "\\" + video_name + "_" + index.ToString() + ".jpg", frame);
                });
 
                StringBuilder sbLabels = new StringBuilder();
                //绘制结果
                foreach (DetectionResult r in detResults)
                {
                    Cv2.PutText(frame, $"{r.Class}:{r.Confidence:P0}", new OpenCvSharp.Point(r.Rect.TopLeft.X, r.Rect.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                    Cv2.Rectangle(frame, r.Rect, Scalar.Red, thickness: 2);
 
                    //class, x_center, y_center, width, height
                    double width = Math.Round(r.Rect.Width / (double)FrameWidth, 6);
                    double height = Math.Round(r.Rect.Height / (double)FrameHeight, 6);
                    double x_center = Math.Round((r.Rect.Right - (r.Rect.Width / 2)) / (double)FrameWidth, 6);
                    double y_center = Math.Round((r.Rect.Bottom - (r.Rect.Height / 2)) / (double)FrameHeight, 6);
 
                    sbLabels.Append($"{r.ClassId} {x_center} {y_center} {width} {height}\n");
                }
 
                //生成不带BOM格式
                using (FileStream fs = new FileStream(labels_path + "\\" + video_name + "_" + index.ToString() + ".txt", FileMode.Create))
                {
                    using (StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)))
                    {
                        sw.Write(sbLabels.ToString());
                    }
                }
                //Cv2.ImWrite(images_path + "\\" + index.ToString() + ".jpg", frame);
                index++;
 
                Cv2.PutText(frame, "preprocessTime:" + yoloV8.preprocessTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 30), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "inferTime:" + yoloV8.inferTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 70), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "postprocessTime:" + yoloV8.postprocessTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 110), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "totalTime:" + yoloV8.totalTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 150), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "video fps:" + videoFps.ToString("F2"), new OpenCvSharp.Point(10, 190), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "det fps:" + yoloV8.detFps.ToString("F2"), new OpenCvSharp.Point(10, 230), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "progress:" + index.ToString() + "/" + frameCount.ToString(), new OpenCvSharp.Point(10, 270), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
 
                Cv2.ImShow("DetectionResult 按下ESC,退出", frame);
 
                //for test
                delay = 1;
                //delay = (int)(delay - _stopwatch.ElapsedMilliseconds);
                //if (delay <= 0)
                //{
                //    delay = 1;
                //}
                //Console.WriteLine("delay:" + delay.ToString()) ;
                if (Cv2.WaitKey(delay) == 27 || Cv2.GetWindowProperty("DetectionResult 按下ESC,退出", WindowPropertyFlags.Visible) < 1.0)
                {
                    Cv2.DestroyAllWindows();
                    vcapture.Release();
                    break; // 如果按下ESC,退出循环
                }
            }
 
            Cv2.DestroyAllWindows();
            vcapture.Release();
        }
 
        /// <summary>
        /// 异步接口-视频推理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            if (video_path == "")
            {
                MessageBox.Show("请先选择视频!");
                return;
            }
 
            if (output_path == "")
            {
                MessageBox.Show("请先选择输出目录!");
                return;
            }
 
            images_path = output_path + "\\output\\images";
            labels_path = output_path + "\\output\\labels";
 
            if (!Directory.Exists(images_path))
            {
                Directory.CreateDirectory(images_path);
            }
 
            if (!Directory.Exists(labels_path))
            {
                Directory.CreateDirectory(labels_path);
            }
 
            textBox1.Text = "开始异步推理检测";
 
            Application.DoEvents();
 
            Thread thread = new Thread(new ThreadStart(VideoDetectionAsync));
 
            thread.Start();
            thread.Join();
 
            textBox1.Text = "异步推理检测完成!";
        }
 
        void VideoDetectionAsync()
        {
            vcapture = new VideoCapture(video_path);
            if (!vcapture.IsOpened())
            {
                MessageBox.Show("打开视频文件失败");
                return;
            }
 
            Mat frame = new Mat();
            List<DetectionResult> detResults;
 
            // 获取视频的fps
            double videoFps = vcapture.Get(VideoCaptureProperties.Fps);
            // 计算等待时间(毫秒)
            int delay = (int)(1000 / videoFps);
            Stopwatch _stopwatch = new Stopwatch();
 
            int frameCount = (int)vcapture.Get(VideoCaptureProperties.FrameCount);
 
            Cv2.NamedWindow("DetectionResult 按下ESC,退出", WindowFlags.Normal);
            Cv2.ResizeWindow("DetectionResult 按下ESC,退出", vcapture.FrameWidth / 2, vcapture.FrameHeight / 2);
 
            int FrameWidth = vcapture.FrameWidth;
            int FrameHeight = vcapture.FrameHeight;
            int index = 0;
 
            while (vcapture.Read(frame))
            {
                if (frame.Empty())
                {
                    MessageBox.Show("读取失败");
                    return;
                }
 
                //输出图片
                Task.Factory.StartNew(() =>
                {
                    Cv2.ImWrite(images_path + "\\" + video_name + "_" + index.ToString() + ".jpg", frame);
                });
 
                detResults = yoloV8Async.Detect(frame);
 
                StringBuilder sbLabels = new StringBuilder();
                //绘制结果
                foreach (DetectionResult r in detResults)
                {
                    Cv2.PutText(frame, $"{r.Class}:{r.Confidence:P0}", new OpenCvSharp.Point(r.Rect.TopLeft.X, r.Rect.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                    Cv2.Rectangle(frame, r.Rect, Scalar.Red, thickness: 2);
 
                    //class, x_center, y_center, width, height
                    double width = Math.Round(r.Rect.Width / (double)FrameWidth, 6);
                    double height = Math.Round(r.Rect.Height / (double)FrameHeight, 6);
                    double x_center = Math.Round((r.Rect.Right - (r.Rect.Width / 2)) / (double)FrameWidth, 6);
                    double y_center = Math.Round((r.Rect.Bottom - (r.Rect.Height / 2)) / (double)FrameHeight, 6);
 
                    sbLabels.Append($"{r.ClassId} {x_center} {y_center} {width} {height}\n");
                }
 
                //生成不带BOM格式
                using (FileStream fs = new FileStream(labels_path + "\\" + video_name + "_" + index.ToString() + ".txt", FileMode.Create))
                {
                    using (StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)))
                    {
                        sw.Write(sbLabels.ToString());
                    }
                }
                //Cv2.ImWrite(images_path + "\\" + index.ToString() + ".jpg", frame);
                index++;
 
                Cv2.PutText(frame, "preprocessTime:" + yoloV8Async.preprocessTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 30), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "inferTime:" + yoloV8Async.inferTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 70), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "postprocessTime:" + yoloV8Async.postprocessTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 110), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "totalTime:" + yoloV8Async.totalTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 150), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "video fps:" + videoFps.ToString("F2"), new OpenCvSharp.Point(10, 190), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "det fps:" + yoloV8Async.detFps.ToString("F2"), new OpenCvSharp.Point(10, 230), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "progress:" + index.ToString() + "/" + frameCount.ToString(), new OpenCvSharp.Point(10, 270), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
 
                //Cv2.ImWrite(images_path + "\\" + index.ToString() + ".jpg", frame);
 
                Cv2.ImShow("DetectionResult 按下ESC,退出", frame);
 
                // for test
                delay = 1;
                //delay = (int)(delay - _stopwatch.ElapsedMilliseconds);
                //if (delay <= 0)
                //{
                //    delay = 1;
                //}
                //Console.WriteLine("delay:" + delay.ToString()) ;
                if (Cv2.WaitKey(delay) == 27 || Cv2.GetWindowProperty("DetectionResult 按下ESC,退出", WindowPropertyFlags.Visible) < 1.0)
                {
                    Cv2.DestroyAllWindows();
                    vcapture.Release();
                    break; // 如果按下ESC,退出循环
                }
            }
            Cv2.DestroyAllWindows();
            vcapture.Release();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值