基于颜色的对象检测和计数在工业、农业、医疗等领域有着广泛的应用。借助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)
);
ORB (Oriented FAST and Rotated BRIEF) 是一种快速稳健的局部特征描述子,由 Ethan Rublee 等人在2011年提出。它是FAST关键点检测和BRIEF描述子的结合,并在此基础上做了改进,添加了一些新特性以增强性能。
在OpenCvSharp中,ORB算法主要通过ORB类来实现。下面我们将详细介绍如何使用OpenCvSharp来进行ORB特征检测和匹配。
以下是使用OpenCvSharp进行ORB特征检测的基本步骤:
下面是一个完整的代码示例:
C#public partial class Form7 : Form
{
private Mat originalImage;
public Form7()
{
InitializeComponent();
}
private void btnLoadImage_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp";
if (ofd.ShowDialog() == DialogResult.OK)
{
originalImage = new Mat(ofd.FileName, ImreadModes.Color);
DisplayImage(originalImage);
btnDetectFeatures.Enabled = true;
}
}
}
private void DisplayImage(Mat image)
{
try
{
using (var bitmap = BitmapConverter.ToBitmap(image))
{
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = new Bitmap(bitmap);
}
}
catch (Exception ex)
{
MessageBox.Show($"Error displaying image: {ex.Message}");
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
originalImage?.Dispose();
}
private void btnDetectFeatures_Click(object sender, EventArgs e)
{
if (originalImage == null)
return;
try
{
// 创建ORB对象
using var orb = ORB.Create(500); // 最多检测500个特征点
// 检测关键点
KeyPoint[] keypoints = orb.Detect(originalImage);
// 计算描述子
using var descriptors = new Mat();
orb.Compute(originalImage, ref keypoints, descriptors);
// 创建一个新的Mat来绘制结果
using var result = new Mat();
// 绘制关键点,使用红色圆圈标记特征点
Cv2.DrawKeypoints(originalImage, keypoints, result,
new Scalar(0, 0, 255), // 红色
DrawMatchesFlags.DrawRichKeypoints); // 绘制带有大小和方向的关键点
// 显示结果
DisplayImage(result);
MessageBox.Show($"检测到 {keypoints.Length} 个ORB特征点");
}
catch (Exception ex)
{
MessageBox.Show($"Error detecting features: {ex.Message}");
}
}
}

SURF(Speeded Up Robust Features)是一种计算机视觉中的局部特征检测器和描述符。它于2006年由Herbert Bay等人首次提出,旨在加速SIFT(Scale-Invariant Feature Transform)算法。SURF算法在保持高性能的同时,显著提高了计算速度。
SURF的主要目标是在不同的图像中检测和匹配关键点。这些关键点是图像中独特和稳定的特征,即使在图像发生旋转、缩放或光照变化时也能保持不变。
在OpenCvSharp中使用SURF需要注意,由于专利原因,SURF算法在OpenCV 3.0之后的版本中被移到了opencv_contrib模块。因此,要使用SURF,你需要确保你的OpenCvSharp版本包含了这个额外模块。
以下是在OpenCvSharp中使用SURF的基本步骤:
引入必要的命名空间:
C#using OpenCvSharp;
using OpenCvSharp.XFeatures2D;
创建SURF对象:
C#var surf = SURF.Create(hessianThreshold: 100);
检测关键点:
C#using var image = new Mat("path/to/your/image.jpg", ImreadModes.Grayscale);
KeyPoint[] keypoints = surf.Detect(image);
计算描述符:
C#Mat descriptors = new Mat();
surf.Compute(image, ref keypoints, descriptors);
