
OpenCV官方的开发包至今还不支持C#语言SDK,但是C#有个著名的开源OpenCV Wapper库支持- opencvsharp,github地址如下:
https://github.com/shimat/opencvsharp用 opencvsharp 就可以跟Python、C++一样轻松在C#语言中使用OpenCV SDK完成各种图像处理与深度学习模型推理部署。
YOLO11姿态评估模型
YOLO11是YOLOv5跟YOLOv8作者推出最新升级版本模型,支持分类、检测、分割、姿态评估、OBB。这里以YOLO11姿态评估模型为例,演示OpenCV C#如何运行,YOLO11-pose模型的输入与输出。

OpenCVSharp的官方管DNN部分的参考代码几乎没有,我就是把C++的代码转成C#的方式,然后发现只需要稍微改动即可正确使用:
string onnx_file = "D:/python/yolov5-7.0/yolo11n-pose.onnx";
var model = CvDnn.ReadNetFromOnnx(onnx_file);
string imagePath = "D:/mmc.png";
Mat frame = Cv2.ImRead(imagePath); // BGR
int w = frame.Cols;
int h = frame.Rows;
int max_s = Math.Max(w, h);
Mat blank = Mat.Zeros(new Size(max_s, max_s), frame.Type());
frame.CopyTo(blank[new Rect(0, 0, w, h)]);
Mat blob = CvDnn.BlobFromImage(blank, 1.0 / 255.0, new Size(640, 640), new Scalar(), true, false);
model.SetInput(blob);
Mat prob = model.Forward();
postProcess(frame, prob);
Cv2.ImShow("OpenCV学堂 - YOLO11姿态评估演示", frame);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();运行结果如下:

后处理关键点绘制

最后得到17个关键点的绘制代码如下:
Cv2.Line(frame, new Point(kypt.At<float>(0, 0), kypt.At<float>(0, 1)), new Point(kypt.At<float>(1, 0), kypt.At<float>(1, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(1, 0), kypt.At<float>(1, 1)), new Point(kypt.At<float>(3, 0), kypt.At<float>(3, 1)), Scalar.RandomColor(), 2);
// nose->right_eye->right_ear.(0, 2), (2, 4)
Cv2.Line(frame, new Point(kypt.At<float>(0, 0), kypt.At<float>(0, 1)), new Point(kypt.At<float>(2, 0), kypt.At<float>(2, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(2, 0), kypt.At<float>(2, 1)), new Point(kypt.At<float>(4, 0), kypt.At<float>(4, 1)), Scalar.RandomColor(), 2);
// nose->left_shoulder->left_elbow->left_wrist.(0, 5), (5, 7), (7, 9)
Cv2.Line(frame, new Point(kypt.At<float>(0, 0), kypt.At<float>(0, 1)), new Point(kypt.At<float>(5, 0), kypt.At<float>(5, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(5, 0), kypt.At<float>(5, 1)), new Point(kypt.At<float>(7, 0), kypt.At<float>(7, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(7, 0), kypt.At<float>(7, 1)), new Point(kypt.At<float>(9, 0), kypt.At<float>(9, 1)), Scalar.DeepPink, 2);
// nose->right_shoulder->right_elbow->right_wrist.(0, 6), (6, 8), (8, 10)
Cv2.Line(frame, new Point(kypt.At<float>(0, 0), kypt.At<float>(0, 1)), new Point(kypt.At<float>(6, 0), kypt.At<float>(6, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(6, 0), kypt.At<float>(6, 1)), new Point(kypt.At<float>(8, 0), kypt.At<float>(8, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(8, 0), kypt.At<float>(8, 1)), new Point(kypt.At<float>(10, 0), kypt.At<float>(10, 1)), Scalar.Blue, 2);
// left_shoulder->left_hip->left_knee->left_ankle.(5, 11), (11, 13), (13, 15)
Cv2.Line(frame, new Point(kypt.At<float>(5, 0), kypt.At<float>(5, 1)), new Point(kypt.At<float>(11, 0), kypt.At<float>(11, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(11, 0), kypt.At<float>(11, 1)), new Point(kypt.At<float>(13, 0), kypt.At<float>(13, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(13, 0), kypt.At<float>(13, 1)), new Point(kypt.At<float>(15, 0), kypt.At<float>(15, 1)), Scalar.Green, 2);
// right_shoulder->right_hip->right_knee->right_ankle.(6, 12), (12, 14), (14, 16)
Cv2.Line(frame, new Point(kypt.At<float>(6, 0), kypt.At<float>(6, 1)), new Point(kypt.At<float>(12, 0), kypt.At<float>(12, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(12, 0), kypt.At<float>(12, 1)), new Point(kypt.At<float>(14, 0), kypt.At<float>(14, 1)), Scalar.RandomColor(), 2);
Cv2.Line(frame, new Point(kypt.At<float>(14, 0), kypt.At<float>(14, 1)), new Point(kypt.At<float>(16, 0), kypt.At<float>(16, 1)), Scalar.Red, 2);
for (int row = 0; row < kypt.Rows; row++)
{
int x = (int)(kypt.At<float>(row, 0));
int y = (int)(kypt.At<float>(row, 1));
Cv2.Circle(frame, new Point(x, y), 3, Scalar.Blue, 3);
}
玩转YOLOv8通杀YOLO系列所有模型!