OpencvSharp 算子学习教案之 - Cv2.GetStructuringElement 重载1

📅 2026/7/6 14:07:58 👁️ 阅读次数 📝 编程学习
OpencvSharp 算子学习教案之 - Cv2.GetStructuringElement 重载1

OpencvSharp 算子学习教案之 - Cv2.GetStructuringElement 重载1

大家好,Opencv在很多工程项目中都会用到,而OpencvSharp则是以C#开发与实现的Opencv操作库,对.NET开发人员友好,但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳,因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案,供大家参考学习。

Cv2.GetStructuringElement

  • 教案版本:V1.0
  • 面向对象:OpenCvSharp 初学者
  • 所属模块:imgproc
  • 源码位置:OpenCvSharp/Cv2/Cv2_imgproc.cs:96

摘要:GetStructuringElement 会生成用于腐蚀、膨胀和形态学变换的结构元素。本文用 Rect、Cross、Ellipse 三种形状对比,帮助初学者先看懂 shape 和 ksize 如何决定矩阵外形,再把这个概念和后续的形态学运算联系起来。

1. 函数名称(带参数签名)

publicstaticMatGetStructuringElement(MorphShapesshape,Sizeksize)

2. 函数用途

Cv2.GetStructuringElement的作用,是生成一个结构元素矩阵。

这个函数最常见的用途有:

  1. 作为erode的 kernel。
  2. 作为dilate的 kernel。
  3. 作为morphologyEx的 kernel。
  4. 在教学中直观观察不同形状的邻域支持范围。

它返回的不是图像处理结果,而是一个会参与后续形态学运算的二值矩阵。

3. 函数公式

结构元素可以理解成一个二值支持矩阵:

K(x,y)={1,如果位置属于所选形状0,如果位置不属于所选形状 K(x, y) = \begin{cases} 1, & \text{如果位置属于所选形状} \\ 0, & \text{如果位置不属于所选形状} \end{cases}K(x,y)={1,0,如果位置属于所选形状如果位置不属于所选形状

在后续的腐蚀和膨胀里,OpenCV 会根据这个矩阵里非零元素的位置来决定参与计算的邻域。

4. 函数原理说明

这个函数会根据shapeksize生成一个矩阵。

  1. shape决定结构元素的轮廓。
  2. ksize决定结构元素占多大范围。
  3. 返回值通常是单通道矩阵,便于直接传给形态学函数。
  4. 如果后续做腐蚀或膨胀,这个矩阵就会变成真正的运算邻域。

在 OpenCvSharp 里,MorphShapes.RectMorphShapes.CrossMorphShapes.Ellipse是当前最常用的三种形状。

5. 参数含义解析

参数名类型必填含义
shapeMorphShapes结构元素形状
ksizeSize结构元素大小,宽和高都应为正数

补充说明:

  1. Rect是最基础的矩形结构元素。
  2. Cross适合看清横竖支撑点。
  3. Ellipse更接近圆形邻域。
  4. 返回值可以直接传给erodedilatemorphologyEx

6. 应用场景列表

场景名场景说明典型用途
场景A:基础结构元素观察三种 shape 的矩阵差异形态学入门
场景B:腐蚀运算准备先生成 kernel 再做 erode去噪和缩小目标
场景C:膨胀运算准备先生成 kernel 再做 dilate填补小孔和连接断裂
场景D:教学对比让初学者看懂邻域形状初学者入门

7. 函数使用示例

下面的 Console 程序演示Cv2.GetStructuringElement(MorphShapes shape, Size ksize)。示例会把 Rect、Cross、Ellipse 三种结构元素打印出来,并计算每个矩阵里有多少个非零元素。

usingSystem;usingSystem.Text;usingOpenCvSharp;internalstaticclassProgram{privatereadonlyrecordstructKernelCase(stringLabel,MorphShapesShape,SizeKSize,stringComment);privatestaticreadonlyKernelCase[]Cases={new("Rect 矩形核",MorphShapes.Rect,newSize(5,5),"最基础的矩形结构元素,适合先理解形态学邻域。"),new("Cross 十字核",MorphShapes.Cross,newSize(5,5),"只保留横竖方向的支撑点。"),new("Ellipse 椭圆核",MorphShapes.Ellipse,newSize(5,5),"更接近圆形邻域。"),};/// <summary>/// 程序入口。/// </summary>privatestaticvoidMain(){// 先把控制台编码切成 UTF-8,避免中文说明出现乱码。Console.OutputEncoding=Encoding.UTF8;// 运行演示,观察不同 shape 和 ksize 对结构元素矩阵的影响。RunDemo();}/// <summary>/// 演示结构元素的生成结果。/// </summary>privatestaticvoidRunDemo(){Console.WriteLine("场景A:GetStructuringElement(MorphShapes shape, Size ksize)");Console.WriteLine("GetStructuringElement 会返回一个可直接用于形态学运算的矩阵。\n");foreach(variteminCases){// 这里直接用 OpenCV 生成结构元素,然后把矩阵按 0/1 打印出来。usingvarkernel=Cv2.GetStructuringElement(item.Shape,item.KSize);Console.WriteLine($"[{item.Label}] shape={item.Shape}, ksize={item.KSize.Width}x{item.KSize.Height}");Console.WriteLine(item.Comment);Console.WriteLine($"非零元素数量:{Cv2.CountNonZero(kernel)}");Console.WriteLine(FormatKernel(kernel));Console.WriteLine();}Console.WriteLine("教学结论:shape 决定矩阵轮廓,ksize 决定矩阵范围。这个矩阵会被后续腐蚀和膨胀直接使用。\n");}/// <summary>/// 把结构元素矩阵格式化成易读文本。/// </summary>/// <param name="kernel">结构元素矩阵。</param>/// <returns>矩阵文本。</returns>privatestaticstringFormatKernel(Matkernel){varsb=newStringBuilder();for(varrow=0;row<kernel.Rows;row++){sb.Append("[");for(varcol=0;col<kernel.Cols;col++){sb.Append(kernel.At<byte>(row,col));if(col<kernel.Cols-1){sb.Append(", ");}}sb.AppendLine("]");}returnsb.ToString();}}

8. 注意事项

  1. ksize应该是正数尺寸。
  2. shape只建议使用RectCrossEllipse这三种常用枚举值。
  3. 返回值是结构元素,不是最终图像处理结果。
  4. 后续腐蚀和膨胀时,这个矩阵会决定邻域的形状。

9. 调优建议

  1. 先用Rect看懂结构元素是什么,再看CrossEllipse
  2. 如果你只是入门形态学,先从5x5这种短核开始。
  3. 想保留更多细节时,可以把结构元素做得小一些。
  4. 想让形态学效果更强时,可以逐步增大ksize

10. 运行说明

  1. 如果你在控制台工程里运行本文示例,直接把代码放进Program.cs即可。
  2. 如果你在本仓库里学习,请打开 WPF 控件Cv2.GetStructuringElement,切换到“场景A”,点击按钮后查看右侧文本框和预览图。
  3. WPF 示例会把三种结构元素放在一起对比,适合初学者建立直觉。

11. 常见错误排查

  1. ksize写成 0 或负数。
  2. 误以为返回值是滤波后的图像,而不是结构元素矩阵。
  3. 不知道RectCrossEllipse的差别。
  4. 生成了 kernel 却忘了把它传给erodedilatemorphologyEx