编辑
2025-11-18
C#
00

SKPath是SkiaSharp中用于创建复杂图形路径的重要类。它可以用来绘制直线、曲线、圆弧等各种图形,并且支持填充和描边操作。本文将详细介绍SKPath的使用方法和常见应用场景。

基础知识

在WinForms中使用SkiaSharp,首先需要安装以下NuGet包:

  • SkiaSharp
  • SkiaSharp.Views
  • SkiaSharp.Views.WindowsForms

完整示例代码

C#
using SkiaSharp.Views.Desktop; using SkiaSharp; namespace AppSKPath { public partial class Form1 : Form { private SKControl skControl; public Form1() { InitializeComponent(); // 创建SKControl控件 skControl = new SKControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += OnPaintSurface; this.Controls.Add(skControl); } private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 获取绘图表面 SKSurface surface = e.Surface; SKCanvas canvas = surface.Canvas; // 清空画布 canvas.Clear(SKColors.White); // 1. 基础路径绘制 using (var path = new SKPath()) using (var paint = new SKPaint()) { // 设置画笔属性 paint.Style = SKPaintStyle.Stroke; paint.Color = SKColors.Blue; paint.StrokeWidth = 2; paint.IsAntialias= true; // 移动到起始点 path.MoveTo(50, 50); // 绘制直线 path.LineTo(150, 50); path.LineTo(150, 150); path.LineTo(50, 150); // 闭合路径 path.Close(); // 绘制路径 canvas.DrawPath(path, paint); } // 2. 曲线路径示例 using (var path = new SKPath()) using (var paint = new SKPaint()) { paint.Style = SKPaintStyle.Stroke; paint.Color = SKColors.Red; paint.StrokeWidth = 2; paint.IsAntialias = true; // 二次贝塞尔曲线 path.MoveTo(200, 50); path.QuadTo(250, 0, 300, 50); // 三次贝塞尔曲线 path.MoveTo(200, 100); path.CubicTo(225, 75, 275, 125, 300, 100); canvas.DrawPath(path, paint); } // 3. 圆弧路径示例 using (var path = new SKPath()) using (var paint = new SKPaint()) { paint.Style = SKPaintStyle.Stroke; paint.Color = SKColors.Green; paint.StrokeWidth = 2; paint.IsAntialias = true; // 绘制圆弧 var rect = new SKRect(350, 50, 450, 150); path.AddArc(rect, 0, 180); // 从0度开始,绘制180度的圆弧 canvas.DrawPath(path, paint); } // 4. 复合路径示例(填充) using (var path = new SKPath()) using (var paint = new SKPaint()) { paint.Style = SKPaintStyle.Fill; paint.Color = SKColors.Orange; paint.IsAntialias = true; // 创建一个五角星 float centerX = 500; float centerY = 100; float radius = 50; for (int i = 0; i < 5; i++) { double angle = i * 4 * Math.PI / 5 - Math.PI / 2; float x = centerX + radius * (float)Math.Cos(angle); float y = centerY + radius * (float)Math.Sin(angle); if (i == 0) path.MoveTo(x, y); else path.LineTo(x, y); } path.Close(); canvas.DrawPath(path, paint); } } } }

image.png

编辑
2025-11-18
C#
00

SkiaSharp 是一个强大的 2D 图形引擎,可以用来绘制各种图形。本文将详细介绍如何使用 SkiaSharp 在 WinForm 应用中绘制多边形。

环境准备

首先需要通过 NuGet 包管理器安装以下包:

  • SkiaSharp
  • SkiaSharp.Views
  • SkiaSharp.Views.WindowsForms

完整示例代码

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; using System; using System.Windows.Forms; namespace SkiaSharpDemo { public partial class Form1 : Form { private SKControl skControl; public Form1() { InitializeComponent(); InitializeSkiaSharp(); } private void InitializeSkiaSharp() { // 创建 SKControl 控件 skControl = new SKControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += OnPaintSurface; this.Controls.Add(skControl); } private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 获取绘图表面 SKSurface surface = e.Surface; SKCanvas canvas = surface.Canvas; // 清空画布 canvas.Clear(SKColors.White); // 创建画笔 using (SKPaint paint = new SKPaint()) { paint.Style = SKPaintStyle.Stroke; // 设置为描边模式 paint.Color = SKColors.Blue; // 设置颜色为蓝色 paint.StrokeWidth = 2; // 设置线宽为2像素 paint.IsAntialias = true; // 启用抗锯齿 // 1. 绘制三角形 DrawTriangle(canvas, paint); // 2. 绘制正方形 paint.Color = SKColors.Red; DrawSquare(canvas, paint); // 3. 绘制五边形 paint.Color = SKColors.Green; DrawPentagon(canvas, paint); // 4. 绘制六边形 paint.Color = SKColors.Purple; DrawHexagon(canvas, paint); // 5. 绘制自定义多边形 paint.Color = SKColors.Orange; DrawCustomPolygon(canvas, paint); } } // 绘制三角形 private void DrawTriangle(SKCanvas canvas, SKPaint paint) { // 创建路径 using (SKPath path = new SKPath()) { // 定义三角形的三个顶点 path.MoveTo(50, 50); // 起始点 path.LineTo(150, 50); // 第二个点 path.LineTo(100, 150); // 第三个点 path.Close(); // 闭合路径 // 绘制路径 canvas.DrawPath(path, paint); } } // 绘制正方形 private void DrawSquare(SKCanvas canvas, SKPaint paint) { using (SKPath path = new SKPath()) { path.MoveTo(200, 50); path.LineTo(300, 50); path.LineTo(300, 150); path.LineTo(200, 150); path.Close(); canvas.DrawPath(path, paint); } } // 绘制五边形 private void DrawPentagon(SKCanvas canvas, SKPaint paint) { float centerX = 400; float centerY = 100; float radius = 50; int sides = 5; DrawRegularPolygon(canvas, paint, centerX, centerY, radius, sides); } // 绘制六边形 private void DrawHexagon(SKCanvas canvas, SKPaint paint) { float centerX = 550; float centerY = 100; float radius = 50; int sides = 6; DrawRegularPolygon(canvas, paint, centerX, centerY, radius, sides); } // 绘制自定义多边形 private void DrawCustomPolygon(SKCanvas canvas, SKPaint paint) { using (SKPath path = new SKPath()) { // 定义多边形的顶点 SKPoint[] points = new SKPoint[] { new SKPoint(50, 200), // 第一个点 new SKPoint(150, 200), // 第二个点 new SKPoint(200, 300), // 第三个点 new SKPoint(100, 350), // 第四个点 new SKPoint(25, 300) // 第五个点 }; // 移动到第一个点 path.MoveTo(points[0]); // 连接所有点 for (int i = 1; i < points.Length; i++) { path.LineTo(points[i]); } path.Close(); // 闭合路径 canvas.DrawPath(path, paint); } } // 通用方法:绘制正多边形 private void DrawRegularPolygon(SKCanvas canvas, SKPaint paint, float centerX, float centerY, float radius, int sides) { using (SKPath path = new SKPath()) { // 计算每个角的弧度 float angleStep = 2 * (float)Math.PI / sides; // 移动到第一个点 float firstX = centerX + radius * (float)Math.Cos(0); float firstY = centerY + radius * (float)Math.Sin(0); path.MoveTo(firstX, firstY); // 绘制其余的点 for (int i = 1; i <= sides; i++) { float angle = i * angleStep; float x = centerX + radius * (float)Math.Cos(angle); float y = centerY + radius * (float)Math.Sin(angle); path.LineTo(x, y); } path.Close(); canvas.DrawPath(path, paint); } } } }

image.png

编辑
2025-11-18
C#
00
编辑
2025-11-17
C#
00

1. 引言

基于颜色的对象检测和计数在工业、农业、医疗等领域有着广泛的应用。借助OpenCvSharp,我们可以快速实现这类功能。本文将详细介绍如何使用C#和OpenCvSharp来实现基于颜色的对象检测和计数。

2. 应用场景

  • 工业生产线上的产品计数(如不同颜色的瓶盖)
  • 农业领域的水果分选计数
  • 医疗领域的细胞计数
  • 质量控制中的缺陷检测
  • 交通监控中的车辆计数
  • 零售业中的商品库存统计

3. 环境准备

C#
// 安装必要的NuGet包 // Install-Package OpenCvSharp4 // Install-Package OpenCvSharp4.runtime.win using OpenCvSharp; using System;

4. 基本实现流程

4.1 基础代码框架

C#
public class ColorObjectCounter { private Scalar lowerBound; private Scalar upperBound; public ColorObjectCounter(Scalar lower, Scalar upper) { lowerBound = lower; upperBound = upper; } public int CountObjects(string imagePath) { using (var src = Cv2.ImRead(imagePath)) { return CountObjects(src); } } public int CountObjects(Mat image) { if (image == null) throw new ArgumentNullException(nameof(image)); // 1. 转换颜色空间 using var hsvImage = new Mat(); Cv2.CvtColor(image, hsvImage, ColorConversionCodes.BGR2HSV); // 2. 创建掩码 using var mask = new Mat(); Cv2.InRange(hsvImage, lowerBound, upperBound, mask); // 3. 形态学操作 using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(5, 5)); using var processedMask = new Mat(); Cv2.MorphologyEx(mask, processedMask, MorphTypes.Open, kernel); // 4. 查找轮廓 Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours( processedMask, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 5. 过滤和计数 return FilterAndCountContours(contours); } private int FilterAndCountContours(Point[][] contours) { int count = 0; foreach (var contour in contours) { double area = Cv2.ContourArea(contour); if (area > 100) // 面积阈值,需要根据实际情况调整 { count++; } } return count; } }
C#
static void Main(string[] args) { // 调整HSV范围以更好地检测红色缝线 Scalar lowerRed1 = new Scalar(0, 50, 50); // 降低饱和度和亮度的最小值 Scalar upperRed1 = new Scalar(10, 255, 255); // 创建检测器实例 ColorObjectCounter counter1 = new ColorObjectCounter(lowerRed1, upperRed1); string imagePath = "output_cropped2.jpg"; // 调用检测方法 int redObjects = counter1.CountObjects(imagePath); Console.WriteLine($"检测到 {redObjects} 条红色线"); }

image.png

编辑
2025-11-17
C#
00

1. 简介

本文将详细介绍如何使用C#和OpenCvSharp来实现基于轮廓检测的对象计数。我们将通过多个实例来说明不同场景下的轮廓检测和计数方法。

2. 环境准备

首先需要安装必要的NuGet包:

Bash
Install-Package OpenCvSharp4 Install-Package OpenCvSharp4.Windows

4. 简单对象计数示例

4.1 基础计数

C#
static void Main(string[] args) { CountClips("clip.png"); Cv2.WaitKey(0); Cv2.DestroyAllWindows(); } public static int CountClips(string imagePath) { using (var src = new Mat(imagePath)) using (var gray = new Mat()) using (var blur = new Mat()) using (var binary = new Mat()) { // 转换为灰度图 Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY); // 高斯模糊 Cv2.GaussianBlur(gray, blur, new Size(5, 5), 0); // 使用自适应阈值 Cv2.AdaptiveThreshold( blur, binary, 255, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 11, // 邻域大小 2 // 常数差值 ); // 查找轮廓,包括内部轮廓 Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours( binary, out contours, out hierarchy, RetrievalModes.Tree, // 改用Tree模式 ContourApproximationModes.ApproxSimple); // 过滤轮廓 int clipCount = 0; for (int i = 0; i < contours.Length; i++) { // 计算轮廓周长 double perimeter = Cv2.ArcLength(contours[i], true); Cv2.DrawContours( src, contours, i, Scalar.Red, 2); clipCount++; } Cv2.ImShow("Result", src); return clipCount; } }

image.png

Python
Cv2.AdaptiveThreshold( blur, // 输入图像(通常是灰度图或经过模糊处理的图像) binary, // 输出图像(二值化结果) 255, // 最大值(像素被判定为白色时的值) AdaptiveThresholdTypes.GaussianC, // 自适应方法类型 ThresholdTypes.Binary, // 阈值类型 11, // 邻域大小(块大小) 2 // 常数差值(C) );