在计算机视觉领域,边缘检测是用于识别图像对象边界的一种重要技术。本文将介绍如何使用 OpenCvSharp(OpenCV 在 C# 上的封装库)来识别图像中的对象数量,并将每个对象用不同颜色的框标记出来。
在开始之前,请确保你已经安装了以下工具和库:
你可以通过 NuGet 包管理器安装 OpenCvSharp:
BashInstall-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();
}
}
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 许可协议。转载请注明出处!