编辑
2025-09-26
C#
00

目录

前提条件
代码实现
完整代码
代码分析
结论

在计算机视觉领域,边缘检测是用于识别图像对象边界的一种重要技术。本文将介绍如何使用 OpenCvSharp(OpenCV 在 C# 上的封装库)来识别图像中的对象数量,并将每个对象用不同颜色的框标记出来。

前提条件

在开始之前,请确保你已经安装了以下工具和库:

  1. Visual Studio 或 Rider 等 C# 开发环境
  2. .NET SDK
  3. OpenCvSharp 库

你可以通过 NuGet 包管理器安装 OpenCvSharp:

Bash
Install-Package OpenCvSharp4 Install-Package OpenCvSharp4.runtime.win

代码实现

以下代码演示了如何使用 OpenCvSharp 边缘检测技术来识别图像中的对象数量,并对每个对象用不同颜色的框标记。

完整代码

C#
internal class Program { static void Main(string[] args) { // 读取图像 string imagePath = "4.png"; // 替换为你的图像路径 Mat srcImage = Cv2.ImRead(imagePath, ImreadModes.Color); // 将图像转换为灰度图 Mat grayImage = new Mat(); Cv2.CvtColor(srcImage, grayImage, ColorConversionCodes.BGR2GRAY); // 使用高斯模糊消除噪点 Mat blurredImage = new Mat(); Cv2.GaussianBlur(grayImage, blurredImage, new Size(5, 5), 1.5); // 边缘检测(Canny 算法) Mat edges = new Mat(); Cv2.Canny(blurredImage, edges, 100, 200); // 形态学操作(膨胀与腐蚀) Mat dilatedImage = new Mat(); Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2)); Cv2.Dilate(edges, dilatedImage, kernel); Cv2.Erode(dilatedImage, edges, kernel); // 查找轮廓 Cv2.FindContours(edges, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 绘制每个检测到的轮廓 Random rand = new Random(); Mat resultImage = srcImage.Clone(); int objectCount = 0; for (int i = 0; i < contours.Length; i++) { // 过滤较小的轮廓 if (Cv2.ContourArea(contours[i]) < 300) continue; // 调整阈值以过滤小轮廓 objectCount++; // 随机生成颜色 Scalar color = new Scalar(rand.Next(0, 256), rand.Next(0, 256), rand.Next(0, 256)); // 绘制轮廓 Cv2.DrawContours(resultImage, contours, i, color, 2); // 计算轮廓的边界框 Rect boundingBox = Cv2.BoundingRect(contours[i]); // 绘制边界框 Cv2.Rectangle(resultImage, boundingBox, color, 2); } // 输出检测到的对象数量 Console.WriteLine($"检测到的对象数量: {objectCount}"); // 显示图像 Cv2.ImShow("Detected Objects", resultImage); Cv2.WaitKey(0); Cv2.DestroyAllWindows(); } }

image.png

代码分析

  1. 读取图像
C#
string imagePath = "4.png"; // 替换为你的图像路径 Mat srcImage = Cv2.ImRead(imagePath, ImreadModes.Color);
从指定路径读取图像文件。`ImreadModes.Color` 将图像加载为彩色。

2. 图像转换为灰度图

C#
Mat grayImage = new Mat(); Cv2.CvtColor(srcImage, grayImage, ColorConversionCodes.BGR2GRAY);
将彩色图像转换为灰度图。灰度图减少了颜色通道,只包含一个通道,便于后续处理。

3. 高斯模糊消除噪点

C#
Mat blurredImage = new Mat(); Cv2.GaussianBlur(grayImage, blurredImage, new Size(5, 5), 1.5);
使用高斯模糊对灰度图进行平滑处理,减少噪点。`Size(5, 5)` 是卷积核的大小,`1.5` 是标准差。

4. 边缘检测(Canny 算法)

C#
Mat edges = new Mat(); Cv2.Canny(blurredImage, edges, 100, 200);
应用 Canny 边缘检测算法,检测图像中的边缘。100 和 200 是低阈值和高阈值。

5. 形态学操作(膨胀与腐蚀)

C#
Mat dilatedImage = new Mat(); Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2)); Cv2.Dilate(edges, dilatedImage, kernel); Cv2.Erode(dilatedImage, edges, kernel);
- `Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2))` 创建形态学操作的结构元素。 - `Cv2.Dilate(edges, dilatedImage, kernel)` 应用膨胀操作,使边缘变粗。 - `Cv2.Erode(dilatedImage, edges, kernel)` 应用腐蚀操作,使边缘恢复原始大小,减少噪点影响。

6. 查找轮廓

C#
Cv2.FindContours( edges, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple );
使用 `Cv2.FindContours` 查找边缘图像中的轮廓。`RetrievalModes.External` 只提取最外层轮廓,`ContourApproximationModes.ApproxSimple` 对轮廓进行简化。

7. 绘制每个检测到的轮廓

C#
Random rand = new Random(); Mat resultImage = srcImage.Clone(); int objectCount = 0; for (int i = 0; i < contours.Length; i++) { // 过滤较小的轮廓 if (Cv2.ContourArea(contours[i]) < 300) continue; // 调整阈值以过滤小轮廓 objectCount++; // 随机生成颜色 Scalar color = new Scalar(rand.Next(0, 256), rand.Next(0, 256), rand.Next(0, 256)); // 绘制轮廓 Cv2.DrawContours(resultImage, contours, i, color, 2); // 计算轮廓的边界框 Rect boundingBox = Cv2.BoundingRect(contours[i]); // 绘制边界框 Cv2.Rectangle(resultImage, boundingBox, color, 2); }
- 使用 `Random` 类生成随机颜色。 - 克隆原始图像以绘制结果。 - 通过轮廓的面积过滤掉小轮廓(面积小于 300)。 - 用随机颜色绘制有效的轮廓和其边界框。

8. 输出检测结果

C#
Console.WriteLine($"检测到的对象数量: {objectCount}");
输出图像中检测到的对象数量。

9. 显示结果图像

C#
Cv2.ImShow("Detected Objects", resultImage); Cv2.WaitKey(0); Cv2.DestroyAllWindows();
- 显示包含检测到的对象和绘制轮廓的结果图像。 - 等待用户按下任意键,然后销毁所有窗口并退出。

结论

通过使用 OpenCvSharp 边缘检测技术,我们可以轻松地识别图像中的对象数量,并将每个对象用不同颜色的框标记。这在很多应用场景中非常有用,比如图像分析、机器视觉和自动化检测等。请根据实际需求调整代码中的参数和图像路径,并进一步优化处理过程以达到最佳效果。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!