OpenCVSharp 使用 Yolo V3 模型进行视频目标检测和分类

首先下载 Yolo 训练好的模型:https://pjreddie.com/media/files/yolov3.weights

 共3个文件:yolov3.cfg,yolov3.weights,coco.names

using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenCvSharp;
using OpenCvSharp.Dnn;

namespace OpenCvSharpYolo3
{
    class Program
    {

        static string[] Labels;
        static void Main()
        {
            const string Cfg = @"h:\csharp\yolov3\yolov3.cfg";
            const string Weight = @"h:\csharp\yolov3\yolov3.weights";
            const string Names = @"h:\csharp\yolov3\coco.names";

            const float threshold = 0.5f;       //置信度阈值
            const float nmsThreshold = 0.3f;    //nms 阈值

            //读入标签
            Labels = File.ReadAllLines(Names).ToArray();

            string videofile = @"h:\csharp\videos\vtest.avi";

            var net = CvDnn.ReadNetFromDarknet(Cfg, Weight);
            //读入模型和设置
            net.SetPreferableBackend(3); // 3:DNN_BACKEND_OPENCV 
            net.SetPreferableTarget(0); //dnn target cpu

            Cv2.NamedWindow("Result", WindowMode.Normal);
            VideoCapture capture = new VideoCapture(videofile);
            while (true)
            {
                Mat org = new Mat();
                capture.Read(org);
                if (org.Empty())
                    break;
                //生成blob, 块尺寸可以是320/416/608
                var blob = CvDnn.BlobFromImage(org, 1.0 / 255, new Size(320, 320), new Scalar(), true, false);

                // 输入数据
                net.SetInput(blob);

                //获得输出层名
                var outNames = net.GetUnconnectedOutLayersNames();

                //转换成 Mat[]
                var outs = outNames.Select(_ => new Mat()).ToArray();

                net.Forward(outs, outNames);

                //从输出中获得最佳的结果
                //GetBestResult(outs, org, threshold, nmsThreshold);
                //for nms
                var classIds = new List<int>();
                var confidences = new List<float>();
                var probabilities = new List<float>();
                var boxes = new List<Rect2d>();

                var w = org.Width;
                var h = org.Height;
                const int prefix = 5;   //分类概率

                foreach (var prob in outs)
                {
                    for (var i = 0; i < prob.Rows; i++)
                    {
                        var confidence = prob.At<float>(i, 4);
                        if (confidence > threshold) //置信度大于阈值
                        {
                            //获得识别概率
                            Cv2.MinMaxLoc(prob.Row[i].ColRange(prefix, prob.Cols), out _, out Point max);
                            var classes = max.X;
                            var probability = prob.At<float>(i, classes + prefix);

                            if (probability > threshold) //概率大于阈值
                            {
                                var centerX = prob.At<float>(i, 0) * w;
                                var centerY = prob.At<float>(i, 1) * h;
                                var width = prob.At<float>(i, 2) * w;
                                var height = prob.At<float>(i, 3) * h;

                                //准备nms(非极大值抑制)数据
                                classIds.Add(classes);
                                confidences.Add(confidence);
                                probabilities.Add(probability);
                                boxes.Add(new Rect2d(centerX, centerY, width, height));
                            }
                        }
                    }
                }

                //nms(非极大值抑制)提取分数最高的
                //去除重叠和低置信度的目标框
                CvDnn.NMSBoxes(boxes, confidences, threshold, nmsThreshold, out int[] indices);

                foreach (var i in indices)
                {
                    //画出目标方框并标注置信度和分类标签
                    var box = boxes[i];
                    //Draw(image, classIds[i], confidences[i], probabilities[i], box.X, box.Y, box.Width, box.Height);
                    //标签字符串
                    int classes = classIds[i];

                    var label = string.Format("{0} {1:0.0}%", Labels[classIds[i]], probabilities[i] * 100);
                    var x1 = (box.X - box.Width / 2) < 0 ? 0 : box.X - box.Width / 2;
                    //画方框
                    org.Rectangle(new Point(x1, box.Y - box.Height / 2), new Point(box.X + box.Width / 2, box.Y + box.Height / 2), Scalar.Red, 1);

                    //标签字符大小
                    var textSize = Cv2.GetTextSize(label, HersheyFonts.HersheyTriplex, 0.5, 1, out var baseline);
                    //画标签背景框
                    Cv2.Rectangle(org, new Rect(new Point(x1, box.Y - box.Height / 2 - textSize.Height - baseline),
                        new Size(textSize.Width, textSize.Height + baseline)), Scalar.Red, Cv2.FILLED);
                    Cv2.PutText(org, label, new Point(x1, box.Y - box.Height / 2 - baseline), HersheyFonts.HersheyTriplex, 0.5, Scalar.White);
                }
                //显示结果
                Cv2.ImShow("Result", org);
                int key = Cv2.WaitKey(10);
                if (key == 27)
                    break;
            }
        }

    }
}

 

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是用OpenCV和Yolo V5模型进行推理,并输出带矩形检测框的图片的示例代码: ```c++ #include <iostream> #include <opencv2/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/dnn.hpp> using namespace cv; using namespace cv::dnn; using namespace std; int main() { // 加载模型和权重文件 String model_file = "/path/to/yolov5s.onnx"; Net net = readNetFromONNX(model_file); // 加载图片 Mat img = imread("/path/to/image.jpg"); // 调整图片尺寸,使其符合模型输入要求 Mat input_blob; int input_width = net.getLayer(0).getInputShape()[3]; int input_height = net.getLayer(0).getInputShape()[2]; resize(img, input_blob, Size(input_width,input_height)); // 将图片输入模型 blobFromImage(input_blob, input_blob, 1/255.0, Size(input_width,input_height), Scalar(0,0,0), true, false); net.setInput(input_blob); // 进行推理 Mat detection = net.forward(); // 解析检测结果 vector<float> confidence; vector<int> class_id; vector<Rect> bbox; float* data = (float*)detection.data; for(int i=0; i<detection.rows; ++i, data+=detection.cols) { Point class_id_point; double max_val=0; for(int j=0; j<num_classes; ++j) { if(data[j]>max_val) { max_val = data[j]; class_id_point.x = j; } } if(max_val>confidence_threshold) { int center_x = (int)(data[num_classes]*img.cols); int center_y = (int)(data[num_classes+1]*img.rows); int width = (int)(data[num_classes+2]*img.cols); int height = (int)(data[num_classes+3]*img.rows); int left = center_x - width/2; int top = center_y - height/2; confidence.push_back(data[class_id_point.x]*100); class_id.push_back(class_id_point.x); bbox.push_back(Rect(left, top, width, height)); } } // 绘制检测框和标签 for(int i=0; i<bbox.size(); ++i) { rectangle(img, bbox[i], Scalar(0,0,255), 2); String label = format("%.2f %%", confidence[i]); putText(img, label, Point(bbox[i].x, bbox[i].y-5), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,0,255), 2); } // 显示图片 namedWindow("detections", WINDOW_NORMAL); resizeWindow("detections", 800, 600); imshow("detections", img); waitKey(0); return 0; } ``` 此代码中,我们首先加载了Yolo V5模型和权重文件,在内存中构建了神经网络。然后,我们加载要进行检测的图像,并缩放到适合模型输入的尺寸。接下来,我们调用`net.setInput()`方法将缩放后的图像输入给模型进行推理,并获取检测结果。最后,我们解析检测结果,绘制矩形和标签,在原图上显示检测结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值