SKPath是SkiaSharp中用于创建复杂图形路径的重要类。它可以用来绘制直线、曲线、圆弧等各种图形,并且支持填充和描边操作。本文将详细介绍SKPath的使用方法和常见应用场景。
在WinForms中使用SkiaSharp,首先需要安装以下NuGet包:
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);
}
}
}
}

SkiaSharp 是一个强大的 2D 图形引擎,可以用来绘制各种图形。本文将详细介绍如何使用 SkiaSharp 在 WinForm 应用中绘制多边形。
首先需要通过 NuGet 包管理器安装以下包:
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);
}
}
}
}

基于颜色的对象检测和计数在工业、农业、医疗等领域有着广泛的应用。借助OpenCvSharp,我们可以快速实现这类功能。本文将详细介绍如何使用C#和OpenCvSharp来实现基于颜色的对象检测和计数。
C#// 安装必要的NuGet包
// Install-Package OpenCvSharp4
// Install-Package OpenCvSharp4.runtime.win
using OpenCvSharp;
using System;
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} 条红色线");
}

本文将详细介绍如何使用C#和OpenCvSharp来实现基于轮廓检测的对象计数。我们将通过多个实例来说明不同场景下的轮廓检测和计数方法。
首先需要安装必要的NuGet包:
BashInstall-Package OpenCvSharp4 Install-Package OpenCvSharp4.Windows
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;
}
}

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