最近AB大神yolov7出来了,我们使用c# 调用yolov7-tiny,使用openchsharp加载.weights 和.cfg文件,进行推理。i5 10400 的 total时间 在25ms左右。还是很快的。跟yolov4一样,对于opencv很友好。yolov4-tiny 也在25ms左右,c#调用代码都通用。
首先在nuget程序包里搜索,opencvsharp
完整demo程序下载
yolov7-tiny的c#调用,vs2022使用opencvsharp推理-C#文档类资源-CSDN文库https://download.csdn.net/download/vokxchh/85993605
其中调用代码如下。
using OpenCvSharp;
using OpenCvSharp.Dnn;
using System.Diagnostics;
using System.Drawing.Drawing2D;
namespace WinFormsApp5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private const string configurationFilename = @".\Cfg\yolov7-tiny.cfg";
private const string weightsFilename = @".\Weights\yolov7-tiny_last.weights";
private const string namesFile = @".\Data\vocTR.names";
private static Dictionary _namesDic = new Dictionary();
Net? net;
const float threshold = 0.5f;
const float nmsThreshold = 0.3f;
static BoundingBox[] bbox = new BoundingBox[1000];
///
/// 画图
///
public static Bitmap? DrawRectangleInPicture(Bitmap bmp, int id, float prob, int x, int y, int width, int height, Color RectColor, int LineWidth, DashStyle ds)
{
try
{
if (bmp == null) return null;
Graphics g = Graphics.FromImage(bmp);
Brush brush = new SolidBrush(RectColor);
Pen pen = new Pen(brush, LineWidth);
pen.DashStyle = ds;
SolidBrush drawBush = new SolidBrush(Color.Red);
Font drawFont = new Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Millimeter);
g.DrawString(_namesDic[(int)id] + " " + prob.ToString("F2"), drawFont, drawBush, 1, 1);
var x1 = (x - width / 2) < 0 ? 0 : x - width / 2; //avoid left side over edge
var y1 = (y - height / 2) < 0 ? 0 : y - height / 2; //avoid left side over edge
Rectangle rect = new Rectangle(x1, y1, width, height);
g.DrawRectangle(pen, rect);
System.Drawing.Color Mycolor = System.Drawing.Color.FromArgb(60, Color.Yellow);//透明度1-255
System.Drawing.SolidBrush SB1 = new System.Drawing.SolidBrush(Mycolor);
g.FillRectangle(SB1, rect);
g.Dispose();
return bmp;
}
catch (Exception ) { return null; }
}
///
/// 获取yolov7输出
///
private static void GetResult(IEnumerable output, Mat image, float threshold, float nmsThreshold, bool nms = true)
{
Array.Clear(bbox, 0, 1000);
var classIds = new List();
var confidences = new List();
var probabilities = new List();
var boxes = new List();
var w = image.Width;
var h = image.Height;
const int prefix = 5;
foreach (var prob in output)
{
for (var i = 0; i < prob.Rows; i++)
{
var confidence = prob.At(i, 4);
if (confidence > threshold)
{
Cv2.MinMaxLoc(prob.Row(i).ColRange(prefix, prob.Cols), out _, out OpenCvSharp.Point max);
var classes = max.X;
var probability = prob.At(i, classes + prefix);
if (probability > threshold)
{
var centerX = prob.At(i, 0) * w;
var centerY = prob.At(i, 1) * h;
var width = prob.At(i, 2) * w;
var height = prob.At(i, 3) * h;
if (!nms)
{
continue;
}
classIds.Add(classes);
confidences.Add(confidence);
probabilities.Add(probability);
boxes.Add(new Rect2d(centerX, centerY, width, height));
}
}
}
}
if (!nms) return;
CvDnn.NMSBoxes(boxes, confidences, threshold, nmsThreshold, out int[] indices);
foreach (var i in indices)
{
var box = boxes[i];
if (box.X >= 0 && box.Y >= 0)
{
bbox[i].w = box.Width; bbox[i].x = box.X; bbox[i].y = box.Y; bbox[i].h = box.Height;
bbox[i].prob = probabilities[i];
bbox[i].obj_id = classIds[i];
}
}
}
public struct BoundingBox
{
public double x, y, w, h;
public float prob;
public Int32 obj_id;
}
///
/// 检测
///
void detectR(string filename)
{
try
{
Stopwatch swR = new Stopwatch();
swR.Start();
Bitmap img =(Bitmap) Image.FromFile(filename);
var org = OpenCvSharp.Extensions.BitmapConverter.ToMat(img);
var blob = CvDnn.BlobFromImage(org, 1.0 / 255, new OpenCvSharp.Size(416, 416), new Scalar(), true, false);
net.SetInput(blob);
var outNames = net.GetUnconnectedOutLayersNames();
var outs = outNames.Select(_ => new Mat()).ToArray();
net.Forward(outs, outNames);
GetResult(outs, org, threshold, nmsThreshold);
swR.Stop();
string TotalTime = swR.ElapsedMilliseconds.ToString(); //i5 10400 25ms
if (bbox != null)
{
foreach (var i in bbox)
{
if (i.prob >= 0.70 && i.w <= 100)
{
DrawRectangleInPicture(img, (int)i.obj_id, i.prob, (int)i.x, (int)i.y, (int)i.w, (int)i.h, Color.Red, 3, DashStyle.Solid);
}
}
}
pictureBox1.BeginInvoke(new MethodInvoker(delegate () { pictureBox1.Image = img; }));
label1.BeginInvoke(new MethodInvoker(delegate () { label1.Text = TotalTime+" ms"; }));
}
catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); }
}
private void Initilize()
{
try
{
net = CvDnn.ReadNetFromDarknet(configurationFilename, weightsFilename);
net.SetPreferableBackend((Backend)3);
net.SetPreferableTarget(0);
var lines = File.ReadAllLines(namesFile);
for (var i = 0; i < lines.Length; i++)
_namesDic.Add(i, lines[i]);
}
catch (Exception ex) { MessageBox.Show( ex.Message.ToString()); }
}
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Image = null;
detectR("1.jpg");
}
private void Form1_Load(object sender, EventArgs e)
{
Initilize();
}
private void button2_Click(object sender, EventArgs e)
{
pictureBox1.Image = null;
detectR("2.jpg");
}
}
}
--------------------------------------------------------------------------------------------------------------------------------
原始80分类权重demo程序下载
yolov7darknet80分类原始权重的C#调用,使用opencvsharp载入weight和cfg文件。-C#文档类资源-CSDN文库