图像处理(7) : 边缘检测

    边缘检测是图形图像处理、计算机视觉和机器视觉中的一个基本工具,通常用于特征提取和特征检测,旨在检测一张数字图像中有明显变化的边缘或者不连续的区域,在一维空间中,类似的操作被称作步长检测(step detection)。边缘是一幅图像中不同屈原之间的边界线,通常一个边缘图像是一个二值图像。边缘检测的目的是捕捉亮度急剧变化的区域,而这些区域通常是我们关注的。

一、常规边缘检测

    颜色边缘检测方法是使用边缘滤波器,这些滤波器通过寻找较亮和较暗的区域边界像素点的方式提取边缘,滤波器寻找图像中梯度变化明显的部分。这些梯度一般描述为边缘的振幅和方向。将边缘振幅高的所有像素选择出来,就完成了区域的边缘轮廓提取。

    Halcon提供了许多标准的边缘滤波器,如 Sobel、Roberts、Robinson和Frei滤波器。此外,还提供了非极大值抑制算子,用于进行提取边缘后的处理。

    1.1 常用算子

    1. Sobel算子

    Sobel算子结合了高斯平滑和微分求导。它是一阶导数的边缘检测算子,使用卷积核对图像中的每个像素点做卷积和运算,然后采用合适的阈值提取边缘。Soble算子有两个卷积核,分别对应x与y两个方向。其计算过程如下。

  • 分别在x和y两个方向求导。

  • 在图像的每一个像素点上,结合以上两个结果求出近似梯度。

    2. Laplace算子

    Laplace算子是一种二阶导数算子。在图像的边缘区域,像素值会发生比较大的变化,对这些像素求导会出现极值。在这些极值位置,其二阶导数为0,所以也可以用二阶导数来检测图像边缘。

    3.Canny算子

    Canny算子的基本思想是寻找梯度的局部最大值。首先使用高斯平滑滤波器卷积降噪,再用一对卷积阵列计算边缘梯度和方向,然后使用非极大值抑制移除非边缘线条,最后使用滞后阈值(高阈值和低阈值)检测并连接边缘。

 

    对比上述3种算子:

  1. Sobel算子在边缘检测的同时尽量减少了噪声的影响,比较容易实现。它对像素位置的影响进行了加权,因此效果比较好,是很常用的边缘检测方法。

  2. Laplace算子是一种各向同性算子,比较适用于只关心边缘的位置而不考虑其周围像素的灰度差值的情况。Laplace算子对孤立像素的响应要比对边缘或线的响应更强烈,因此只适用于无噪声图像。存在噪声的情况下,使用Laplace算子进行边缘检测之前需要先进行低通滤波处理。

  3. Canny算子是目前理论上相对最完善的一种边缘检测算法,但其也存在不足之处。为了得到较好的边缘检测结果,它通常需要使用较大的滤波尺度,这样容易丢失一些细节。

 

1.2边缘检测处理流程

    边缘检测的一般处理流程如下。

    (1)获取图像。

    (2)用ROI裁剪图像。

    (3)图像滤波。对输入图像使用边缘滤波器是采集后的一个关键步骤,为了获取图像的边缘部分,在读取了输入图像之后,可以使用边缘滤波器获取边缘的梯度和方向。对于像素级边缘,Halcon中提供了常用算子,如 sobel amp、sobel_dir、edges_image、derivate_gauss、edges_color等。

    (4)提取边缘。将符合条件的边缘提取出来,应用滤波器之后,可以使用阈值处理将图像中的高亮边缘提取出来。这里可以使用前文介绍的threshold算子,也可以使用 hysteresis_threshold算子减少非关键的边缘,将符合条件的边缘提取出来。还可以进一步对结果进行非极大值抑制,然后使用skelcton算子将边缘绘制出来。

    (5)边缘处理。根据检测的需要对提取出的边缘进行处理,有时得到的边缘可能会比较粗略,往往大于1个像素,需要进行一些细化;有时得到的边缘并不连续,因此还需要对边缘做一些处理,如生成轮廓、合并非连续的边缘、分离背景等。

    (6)显示结果。将结果绘制在窗口中,以表现直观的边缘提取效果。

 

    1.3 sobel_amp算子

    Halcon提供了大量的边缘滤波器,最常用的是Sobel滤波器。它是一种经典的边缘检测算子,速度和效率都非常令人满意。其在Halcon中对应的算子为sobel_amp算子和 sobel_dir算子,二者都是使用Sobel算子进行边缘检测。前者用于计算边缘的梯度,后者除了能表示梯度外,还能表示边缘的方向。

    下面是一个实例:

read_image(Image,'test1.bmp')
sobel_amp(Image,Amp,'sum_abs',3)
threshold(Amp,Edg,100,255)
skeleton (Edg, Skeleton)

    该例子使用sobel_amp算子对灰度图像进行了边缘检测,选择了sum_abs类型的滤波器,并将带有边缘梯度的图像Amp输出。通过threshold阈值处理去除一些非关键的轮廓点和线。使用skeleton提取区域的框架。

    sobel_amp算子是一种常用的边缘滤波器,该算子是一阶导数的边缘检测算子,使用一个卷积核对图像中的每个像素点做卷积运算,然后采用合适的阈值提取边缘。根据滤波器的不同,卷积核的运算方式也不同。该算子的原型如下:

sobel_amp(Image : EdgeAmplitude : FilterType, Size : )

    其各参数含义如下。

  • Image:为输入的图像,这里是单通道图像。

  • EdgeAmplitude:为输出参数,是带有边缘梯度的图像。

  • FilterType:为输入参数,表示卷积核或滤波器的类型。

  • Size:为输入参数,表示滤波器的尺寸。该参数值越大,得到的边缘线条会越粗,细节越少。这个值一般为单数,默认为3,也可以根据图像的检测需要选择合适的奇数。

    这里的FilterType是基于两种滤波器掩膜的,它决定了卷积的计算方式。假设两个卷积的滤波掩膜矩阵是A和B,矩阵如下:

1.4 edges_image算子

    它使用递归实现的滤波器(如Deriche、Lanser和Shen)检测边缘,也可以使用高斯导数滤波器检测边缘。此外,edges_image算子也提供了非极大值抑制和滞后阈值,使提取出的边缘更细化。edges image算子同样能返回精确的边缘梯度和方向,这一点比 Sobel滤波器要好一些,但是相应地所花的时间也长一些。对一些强调精度而不注重运算时间的场合,可以使用edges _image算子来提高检测效率。此外,也可以结合使用sobel_ fast滤波器,

以提高检测的速度。

    该算子的原型如下:

edges_image(Image : ImaAmp, ImaDir : Filter, Alpha, 
            NMS, Low, High : )

其各参数含义如下。

  • Image:为输入的单通道图像。

  • ImaAmp:为输出的边缘梯度图像。

  • ImaDir:为输出的边缘方向图像。

  • Filter:为输入参数,表示选择的滤波算子。默认为canny,也可以选择derichel .derichel_int4、deriche2、deriche2_int4、lanser1、lanser2、mshen、shen、sobel_fast。

  • Alpha:为输入参数,表示平滑的程度。值越小,表示平滑的程度越大。默认是0,也可以取0.1到1.1之间的值。

  • NMS:表示非极大值抑制。默认为nms,表示使用非极大值抑制;也可以设为none,表示不使用非极大值抑制。使用非极大值抑制可以使模糊的边界变得清晰,因为这步操作只留下边缘上梯度强度最大的点。

  • Low和High:分别表示滞后阈值的低阈值和高阙值。边缘梯度比高阈值大的部分是可以被接受的;低于低阈值的部分将被排除;介于两者之间的,要看该像素是否与边缘点相连,相连的可以认为是边缘。

    下面是一个实例:


 

dev_close_window ()
read_image(Image,'C:/Users/Administrator/Desktop/test1.jpg')
rgb1_to_gray (Image, GrayImage)
gen_image_proto (Image, ImageCleared, 1)
dev_open_window (0, 0, 256, 256, 'black', WindowHandle1)
dev_open_window (0, 256, 256, 256, 'black', WindowHandle2)
dev_open_window (256, 0, 256, 256, 'black', WindowHandle3)
dev_open_window (256, 256, 256, 256, 'black', WindowHandle4)
edges_image (GrayImage, ImaAmpGray, ImaDirGray, 'canny', 1, 'none', -1, -1)
edges_image (GrayImage, ImaAmpGrayNMS, ImaDirGrayHyst, 'canny', 1, 'nms',20, 40) 
*对非极大值抑制后的边缘梯度图像进行了阈值处理
threshold (ImaAmpGrayNMS, RegionGray, 1, 255) 
*提取边缘轮廓
skeleton (RegionGray, EdgesGray) 
*用于结果显示和对比
dev_set_window (WindowHandle1)
dev_display (Image) 
dev_set_window (WindowHandle2)
dev_display (ImageCleared) 
dev_display (ImaAmpGray) 
dev_set_window (WindowHandle3)
dev_display (ImageCleared) 
dev_display (ImaAmpGrayNMS) 
dev_set_window (WindowHandle4)
dev_display (ImageCleared) 
dev_display (EdgesGray)

    这里使用了3种边缘提取方法进行对比。右上图使用canny滤波器提取的,没有使用非极大值抑制的边缘梯度图像。左下图为使用canny滤波器提取的,使用了非极大值抑制的边缘梯度图像。右下图在左下图的基础上加入了灰度阈值处理,并描绘出了经阈值处理的框架图像。

    非极大值抑制(Non-MaximumSuppression,NMS)。经非极大值抑制后,边缘仅剩下梯度最大的像素,所以经阈值处理提取出的像素就是图像的边缘。而如果使用未经非极大值抑制的图像,可能阈值处理会提取过多的像素,无法理想地表现出边缘信息。

    与edges_image算子类似的还有edges_color算子,该算子可以用干提取彩色图像的边缘,其原型如下:

edges_color(Image : ImaAmp, ImaDir : Filter, Alpha, NMS, 
            Low, High : )

1.5其他滤波器

    除了前面介绍的两个算子外,还可以使用其他方法提取图像边缘。

    1. derivate_gauss算子

    derivate_gauss算子不仅可以提取图像边缘,还有以下功能。

  • 平滑图像。

  • 边缘检测,提取图像的边缘。

  • 角点检测,检测图像上的角点。

derivate_gauss(Image : DerivGauss : Sigma, Component : )

其各参数的含义如下。

  • Image:为输入的灰度图像。

  • DerivGauss:为输出的滤波后的图像。参数3 :Sigma为输入的高斯导数的 sigma值。

  • Component:为输入的要计算的导数或者特征。这里有以下几种类型可以选择。

  1. none:仅对图像进行平滑处理。

  2. x:沿着x轴方向求导。

  3. y:沿着y轴方向求导。

  4. gradient :求梯度的绝对值。

  5. gradient_dir:求梯度的方向。

  6. xx:沿着x轴方向二阶求导。

  7. yy:沿着y轴方向二阶求导。

  8. laplace:使用Laplace算子求导。

 

    2.laplace算子

    使用laplace算子对图像进行二次求导,会在边缘产生零点,因此该算子常常与zero_crossing算子配合使用。求出这些零点,也就得到了图像的边缘。同时,由于 laplace算子对孤立像素的响应要比对边缘或线的响应更强烈,因此在检测之前应先进行去噪处理。

    该算子的原型如下:

laplace(Image : ImageLaplace : ResultType, MaskSize, FilterMask : )

其各参数含义如下。

  • Image:为输入的多通道图像。

  • ImagcLaplace:为输出的 laplacc图像。

  • ResultType:为输入的图像的类型。

  • MaskSize:为输入的滤波器的核的尺寸。

  • FilterMask:为输入参数,表示laplace算子使用的滤波核或掩膜的类型。

    以下是一个实例:

read_image(Image,'C:/Users/Administrator/Desktop/test1.jpg')
rgb1_to_gray (Image, GrayImage)
laplace (GrayImage, ImageLaplace, 'signed', 11, 'n_8_isotropic')
zero_crossing (ImageLaplace, RegionCrossing)

    laplace滤波图像然后给zero_crossing算子进行过零点检测,通过检测图像的二阶导数的零交点,可以得到边缘的位置。检测出来的就是二阶导数为0的点,即边缘的点。

    3. laplace_of _gauss算子

    由于图像中一般会存在噪声,而laplace算子对噪声比较敏感,因此需要配合使用图像的平滑操作。高斯–拉普拉斯算法将高斯的低通滤波器和 laplace算子进行了结合,简化成单一的 laplace_of_gauss算子,只需要填入简单的参数,就能得到比较理想的结果。该算子的原型如下:

laplace_of_gauss(Image : ImageLaplace : Sigma : )

其各参数的含义如下。

  • Image:为输入的图像,可以是多通道的。

  • ImageLaplace:为输出的经过高斯–拉普拉斯滤波后的图像。

  • Sigma:为高斯平滑参数。这个值越大,平滑力度越大,图像越模糊。

    以下是一个实例:

    laplace_of _gauss算子进行边缘的滤波计算,并使用zero_crossing算子进行二阶导数的过零点检测,检测得到的二阶导数为0的点,就是边缘的点。

二、亚像素级边缘检测

    亚像素(Sub-Pixel),一般描述图像的最基本的单位是像素,相机的分辨率也是以像素数量来计算的,像素越高,分辨率越大,图像越清晰。点与点之间的最小距离就是一个像素的宽度,但实际工程中可能会需要比一个像素宽度更小的精度,因此就有了亚像素级精度的概念,用于提高分辨率。Halcon中用XLD (eXtended Line Descriptions)表示亚像素的轮廓和多边形。

    在检测过程中,受光照、噪声等因素的影响,有些边缘可能是断裂的,所以需要先进行轮廓合并。Halcon同样提供了许多高效的算子,可以一步完成边缘提取、轮廓合并以及XLD轮廓输出。因此,只需要调用一次算子就可以完成诸多工作,省去了很多计算环节,非常易于使用。除此之外,算子的准确率和稳定性也非常理想。

    2.1 edges_sub_pix算子

    最常用的提取亚像素轮廓的算子是edges_sub_pix算子,该算子同样提供了大量的提取方法,只需要在Filter参数中设置方法的名字,就可以完成边缘的提取。该算子的输入是灰度图像,输出是XLD轮廓,其原型如下:

edges_sub_pix(Image : Edges : Filter, Alpha, Low, High : )

其各参数含义如下。

  • Image:为输入的单通道图像。

  • Edges:为输出的XLD轮廓。

  • Filter:为输入参数,与edges_image算子中的Filter参数类似,表示选择的滤波算子。默认的是canny,可选的有canny、deriche1、derichel_int4、deriche2、deriche2_int4、lanserl、lanser2.mshen、shen、sobel_fast,还有一些以“_junctions”结尾的滤波器,适用于一些非连接的边缘。最常见的滤波器有canny和 lanser2。使用lanser2滤波器的一个优点是,它是一个递归的实现,当加大平滑的力度时,计算时间却不会因此增加。如果图像质量比较好,噪声也比较小,但对速度有要求,可以选择sobel_fast算子,因为它速度比较快,但缺点是对噪声敏感。

  • Alpha:为输入参数,表示平滑的程度。其值越小,表示平滑的程度越大。默认是0可以取0.1到1.1之间的值。

  • Low和 High:分别表示滞后阈值的低阈值和高阈值。低阈值越低,图像的细节会越丰富。高阈值用于将边缘与背景区分开来,高于高阈值的像素可以确定是边缘,这些边缘是强过缘,但往往是不连续的,因此需要用一些弱边缘进行补充。低于低阈值的像素可以被认为一定不是边缘。高于低阈值又低于高阈值的部分像素是弱边缘,需要进行判断。如果该像素的相邻像素是达缘,则该像素被认为是边缘,否则就不是。

    以下是一个实例:

read_image(Image,'C:/Users/Administrator/Desktop/test1.jpg')
rgb1_to_gray (Image, GrayImage)
*进行亚像素边缘提取。分别使用了不同的滞后阈值以便进行对比
edges_sub_pix (GrayImage, Edges1, 'lanser2', 0.5, 5, 50) 
edges_sub_pix (GrayImage, Edges2, 'lanser2', 0.5, 25, 50) 
edges_sub_pix (GrayImage, Edges3, 'lanser2', 0.5, 5, 25)

    2.2 edges_color_sub_pix算子

    如要要提取彩色多通道图像的亚像素边缘,可以使用edges_color_sub_pix算子。该算子与edges_sub_pix算子的参数十分相似,但又有所区别。首先从名称上看,edges_color_sub_pix算子多了一个color,表示它接受彩色多通道图像的输入,它使用Canny等滤波器提取亚像素精度的彩色边缘。另一个区别是,滤波器可选的类型不同。edges_color_sub_pix算子支持Deriche、Shen.Canny 3个大类的滤波器和一个sobel_fast滤波器,而edges_sub pix算子支持的滤波器类型更丰富一些。

    但也有许多地方是相似的,如 edges_color_sub_pix算子也包括一些以“_junctions”结尾的滤波器,这些特殊的滤波器更适用于一些断开的边缘,同时也使用了滞后阈值对滤波器提取出的边缘进行判断。

    以下是一个实例:

read_image(Image,'C:/Users/Administrator/Desktop/test1.jpg')
*使用canny算子进行亚像素边缘提取
edges_color_sub_pix (Image, Edges1, 'canny', 0.5, 5, 50)
*使用canny算子进行亚像素边缘提取
edges_color_sub_pix (Image, Edges2, 'sobel_fast', 0.5, 40, 70)

2.3 lines_gauss 算子

    该算子也可以用于提取边缘线段,它的鲁棒性非常好,提取出的线段类型是亚像素精度的XLD轮廓。其原型如下:

lines_gauss(Image : Lines : Sigma, Low, High, LightDark, 
            ExtractWidth, LineModel, CompleteJunctions : )

其各参数含义如下。

  • Image:为输入的单通道图像。

  • Lines:为输出的一组亚像素精度的XLD轮廓线条。

  • Sigma:为输入的高斯平滑的值。较大的平滑值会使图像平滑的力度更大,但过度平滑也可能导致提取的线条位置有偏差。默认为1.5。在需要提取线条宽度时,Sigma的值应根据要提取的线条宽度进行调节,最小值应不小于wl/3(w为线条宽度,即线条直径的一半)。例如,对于宽度为4的线条,Sigma值应不小于2.3。

  • Low和High:为输入参数,分别表示滞后阈值的低阈值和高阈值。高阈值越低,边缘线条的细节会越丰富。其原理在10.2.1小节edges sub pix算子的参数介绍中有详细介绍。但这里值得一提的是,如果Sigma选得比较大,阈值就应选择较低的高阈值和较高的低阈值。因为选择的Sigma越大,二阶导数就越小。低阙值和高阈值也可以根据要提取的线的相应灰度对比度和Sigma参数值进行计算。

  • LightDark:为输入参数,表示提取较亮的线条还是较暗的线条。默认为light,即提取较亮线条。

  • ExtractWidth:为输入参数,表示是否需要提取线条的宽度。默认为true,即提取每条线段的宽度值。

  • LineModel:为输入参数,表示调整线条位置和宽度的线段模型。可选的有 bar-shaped(条型).gaussian(高斯型)、 parabolic(抛物线型)。默认为条型,大多数应用场景都可以选择该选项。如果是背光比较强的情况,可以考虑另外两种模型。其中,当图像中的线条比较清晰明锐时,可以选择抛物线型:如果不是特别清晰,可以选择高斯型。

  • CompleteJunctions:为输入参数,表示是否添加连接,用于边缘线段不连续的情况,默认为true。因为某些非连通线段无法通过边缘提取器进行提取,所以这里设为true,即可使用其他方式尝试对非连续部分进行连接。

    以下是一个实例:

read_image(Image,'C:/Users/Administrator/Desktop/test1.jpg')
rgb1_to_gray (Image, GrayImage)
dev_open_window (0, 512, 512, 512, 'black', WindowHandle1)
*进行边缘检测
lines_gauss(GrayImage,Lines,1.5,1,8,'light','true','bar-shaped','true')

三、轮廓处理

    对于检测任务来说,提取出边缘或者线条,获取了线条的属性,工作还远未结束。由于这些边缘或者线条并不能表示轮廓,轮廓必须是闭合的,而且有些高精度测量对轮廓的精度要求非常高,因此还需要对轮廓做一些处理。

    在Halcon中,轮廓的数据结构为XLD。对于亚像素级的轮廓处理,Halcon中有许多强大的工具,下面将针对不同的应用情况进行介绍。

3.1轮廓的生成

    轮廓的生成最常用的edges_sub_pix算子,在该算子中可以选择不同的滤波器类型,最常见的滤波器有canny 和 lanser2。

    如果输入图像是多通道的彩色图像,可以选择edges color_sub_pix算子,其与edges_sub_pix算子类似、也推荐选择sobel fast滤波器,用于快速地提取边缘。

    最常用的线条提取方法是lines_gauss,它具有很强的鲁棒性。也可以通过指定ExtractWidth参数提取出线条的宽度等多种特征。线条的宽度越宽,其 Sigma参数的取值也应当越大。

    与提取边缘类似,提取线条也有一个对应于彩色图像的算子,即 lines_color算子,用于处理输入图像为多通道图像的线条提取。

    这些边缘或者线条提取算子输出的除了XLD轮廓之外,还会返回一些表示属性的特征值。这些属性特征与轮廓的整体或者其控制节点密切相关。可以使用gen contour attrib xld算子或者gen_contour_global_attrib_xld算子通过属性名称访问轮廓的某个属性,这些属性一般是以Tuple数组形式存放的。典型的属性有关于边缘的属性,如梯度和方向:关于线条的属性,如线宽等。还可以使用query_contour_attrib_xld算子或者query contour global attrib xld算子对给定的轮廓进行属性查询。

 

3.2轮廓的处理

    输出了目标的轮廓后,接下来还需要对轮廓进行处理,这主要基于以下3个原因。

  1. 对于某些测量任务而言,并不需要分析目标的整个轮廓,可能只需要局部的一段轮廓就够了。而有时由于ROI(感兴趣区域)选择得过大,因此需要对提取的轮廓进行分割,以得到所需的部分。

  2. 在提取轮廓或线条的过程中,可能会有一些杂点或背景区域被误认为是轮廓也被提取了出来,所以需要做一些剔除,以得到完全需要的区域。

  3. 提取出的轮廓线条可能会有一些不连续,而某些检测中需要轮廓是闭合的,因此需要做一些连接或者填补。

   1.轮廓分割

    首先要介绍的是轮廓分割,可以使用segment_contours_xld算子将轮廓分割成线段、圆弧或者椭圆等预定义的形状,分割出的各个线段可以使用select_obj算子单独进行选择。

    如果只需要分割成线段,则可以使用gen_polygons_xld算子和 split_contours_xld算子的组合,这两步操作的结果类似于segment_contours_xld算子的功能。两种方式的区别主要在于对轮廓进行分割后的处理,使用两步组合法,将生成XLD多边形类型的轮廓。

 

    2.轮廓的筛选

    对于轮廓处理来说,很重要的一步是抑制不相关的轮廓,可以使用select_shape_xld算子实现这一功能。该算子的功能非常强大,与第9章介绍过的select_shape算子类似,它使用一步操作就能提取输入区域的多种特征并进行筛选。该算子提供了30多种不同的形状特征,通过指定不同特征的阈值并结合多种特征进行评估,能非常灵活地提取出理想的轮廓部分。也可以选择select_contours_xld算子,它包含了更多线性结构的典型特征。如果需要用鼠标进行交互操作,如实时选择一些轮廓,可以使用sclect_xld _point算子,通过单击鼠标来选取轮廓。

 

    3.轮廊的连接

    如果轮廓的线条是不连续的,那么断开的部分会被当成独立的部分,后续的处理过程会更加棘手。这时可以试着将断开的部分连接起来,使用union _collinear_contours_xld算子或者union_straight_contours_xld算子,就可以实现这一功能。前者适用于共线的连接,后者适用于同方向的邻近轮廓。还可以选择union_adjacent_contours_xld算子,它适用于端点邻近的情况。

    Halcon也提供了一个 shape_trans_xld 算子用于修改形状,把轮廓转换成包围的圆或者矩形等。还可以使用union2_closed _contours_ xld等算子合并闭合轮廓。

 

    4.轮廓的拟合

前面得到的轮廓有可能是不规则的,实际检测中可能需要将其进行拟合,以得到规则的轮廓,便于后续处理。Halcon 提供了几种不同形状的拟合算子,简要介绍如下。

  1. 拟合直线使用fit_line_contour_xld算子,该算子提供了多种拟合的方法,大部分都是用于抑制非相关轮廓线的。该算子会返回线段和线段两端的坐标。其配合gen contour polygon xld算子可以查看直线的显示结果。

  2. 拟合圆形使用fit_circle_contour_ xld算子,其也有许多拟合方法可选,将返回圆的中心坐标和半径。可以使用gen_circle_contour_xld 算子查看拟和结果。

  3. 拟合矩形选择fit_rectangle2_contour xld算子,该算子返回的主要是矩形的中心坐标和边长,以及矩形的旋转角度。其配合gen_rectangle2 contour_xld算子可以显示拟合结果。

  4. 拟合椭圆形可以用fit_ellinse_contour_xld算子,返回椭圆的中心坐标。长轴和短轴的半径,以及椭圆的角度和方向特征。其搭配使用geo_ellipse cntour_xld算子,可以轮廓曲线。

 

<think>好的,我现在要回答用户的问题:“连通域是什么”。首先,我需要确认用户对这个概念的基础了解程度。用户之前询问过形态学操作,所以可能是在图像处理或计算机视觉的上下文中遇到连通域的概念。 接下来,我需要明确连通域的基本定义。连通域通常指的是在二值图像中,由相邻的前景像素(比如白色像素)组成的区域,这些像素通过某种连通性规则连接在一起。这里的连通性规则是关键,常见的有4连通8连通两种方式。需要解释这两种方式的区别,以及它们如何影响连通域的划分。 然后,我应该考虑用户可能的应用场景。比如在图像分割、目标检测、OCR(光学字符识别)等领域,连通域分析都是基础步骤。例如,在OCR中,识别每个字符可能就需要先通过连通域分析将每个字符分离出来。 用户可能需要了解连通域分析的步骤。这通常包括扫描图像,标记不同的区域,并统计各个区域的属性如面积、中心位置等。这里需要分步骤详细解释,比如逐行扫描、使用等价表解决区域合并等问题。 另外,用户可能对连通域分析的算法感兴趣,比如两遍扫描法、基于并查集(Union-Find)的方法等。需要简要介绍这些算法的基本思想,以及它们的优缺点,比如时间复杂度、内存占用等。 还要考虑实际应用中的注意事项。例如,噪声可能导致多个小连通域,这时候可能需要形态学操作(如开运算)来预处理图像,减少噪声的影响。或者,在处理大图像时,算法的效率问题,如何优化等。 可能还需要提到连通域分析在不同领域的变体或扩展,比如在三维图像中的连通域分析(体素连通),或者在灰度图像中的区域生长算法,虽然这些可能超出用户当前的问题范围,但可以作为扩展知识简要提及。 用户可能存在的误区也需要澄清。比如,连通域分析仅适用于二值图像,还是也可以用于灰度图像?需要明确说明通常是二值图像,但通过阈值处理可以将灰度图像转化为二值图像进行分析。 此外,连通域的属性后续处理可能也是用户关心的内容。比如,计算每个连通域的面积、周长、外接矩形、中心矩等特征,用于后续的分类或识别任务。这些属性如何计算,以及它们的应用场景。 最后,总结连通域分析的重要性,强调其在图像处理中的基础地位,以及与其他技术(如形态学操作、边缘检测)的结合使用。确保用户理解连通域不仅是概念,更是实际应用中的实用工具。 在整个思考过程中,需要保持逻辑清晰,由浅入深,从定义到应用,再到算法注意事项,逐步展开,确保用户能够逐步理解。同时,使用示例或类比来帮助理解,比如将连通域比作孤岛,不同的连通性规则相当于不同的连接方式(只允许上下左右,还是包括对角线),这样更直观。 需要检查是否有遗漏的重要点,比如连通域标记的不同算法比较,或者实际工具中的实现(如OpenCV中的connectedComponents函数)。可能用户在实际操作中会用到这些工具,简要提及可以增加实用性。 还要注意术语的准确性,比如“连通域”与“连通区域”是否同义,是否需要区分。在中文资料中,这两个术语通常可以互换使用,但需要保持一致性。 最后,确保回答结构清晰,分点明确,避免信息过载,同时提供足够细节帮助用户真正理解连通域的概念应用。</think>### **连通域(Connected Component)详解** --- #### **一、基本定义** **连通域**(Connected Component)指在**二值图像**中,由**相邻的前景像素**(通常为白色,值为1)组成的连续区域。判断像素是否“相邻”需要依据**连通性规则**,常见的有两种: 1. **4连通(4-邻域)** - 只考虑**上下左右**四个方向相邻的像素。 - 例如:中心像素$(x,y)$的4邻域为$(x±1,y)$$(x,y±1)$。 2. **8连通(8-邻域)** - 考虑**上下左右及对角线**共八个方向。 - 例如:中心像素$(x,y)$的邻域包括$(x±1,y)$、$(x,y±1)$、$(x±1,y±1)$。 **关键区别**: - 4连通更严格,可能将同一物体分割为多个区域(例如对角线连接的像素不被视为同一区域)。 - 8连通更宽松,适合处理复杂形状,但可能将本应分离的物体合并。 --- #### **二、连通域的作用** 1. **目标分离**:将图像中不同物体标记为独立区域。 - 例如:分离照片中的多个细胞、识别文档中的文字字符。 2. **特征提取**:统计每个连通域的属性(面积、周长、外接矩形等)。 3. **去噪**:通过面积过滤剔除小连通域(如噪点)。 --- #### **三、连通域分析的步骤** 以**两遍扫描法**(Two-Pass Algorithm)为例: 1. **第一遍扫描**: - 逐行遍历图像,为每个前景像素分配临时标签。 - 若当前像素的**上方或左侧已有标签**,继承相同标签;否则分配新标签。 - 若上方左侧标签不同,记录等价关系(表示这些标签实际属于同一区域)。 2. **解析等价关系**: - 使用**并查集(Union-Find)** 合并等价标签,确保每个连通域有唯一标签。 3. **第二遍扫描**: - 根据最终标签替换临时标签,生成标记后的图像。 --- #### **四、算法示例** **输入图像**(二值化,0为背景,1为前景): ``` 0 1 0 0 1 1 0 1 0 0 1 1 0 1 1 0 ``` **步骤解析**: 1. **第一遍扫描**(临时标签分配): ``` 0 1 0 0 2 2 0 3 0 0 4 4 0 5 5 0 ``` - 第1行第2列:新标签1。 - 第2行第1列:上方无标签,左侧无标签 → 新标签2。 - 第2行第4列:新标签3。 - 第3行第3列:新标签4。 - 第4行第2列:新标签5。 2. **等价关系处理**: - 无冲突等价关系(本例简单,未出现多标签合并)。 3. **第二遍扫描**(最终标签): ``` 0 1 0 0 1 1 0 2 0 0 3 3 0 4 4 0 ``` --- #### **五、连通域属性计算** 标记完成后,可计算每个连通域的以下属性: 1. **面积**:区域内像素总数。 2. **外接矩形(Bounding Box)**:包围区域的最小矩形。 3. **中心坐标**:区域的质心($(\bar{x}, \bar{y}) = \frac{1}{N}\sum x_i, \frac{1}{N}\sum y_i$)。 4. **周长**:区域边界的像素数。 **示例**: - 标签1的面积=3,外接矩形为第1-2行、第1-2列。 - 标签2的面积=1,外接矩形为第2行第4列。 --- #### **六、实际应用案例** 1. **OCR文字分割**: - 对二值化文档图像进行连通域分析,分离每个字符(如图中的字母“A”、“B”)。 2. **医学图像分析**: - 识别CT图像中的肿瘤区域,统计其面积位置。 3. **工业检测**: - 检测电路板上的焊点缺陷(通过面积过滤异常连通域)。 --- #### **七、代码实现(Python示例)** 使用OpenCV的`connectedComponentsWithStats`函数: ```python import cv2 import numpy as np # 读取二值图像 image = cv2.imread("binary_image.png", 0) # 连通域分析 num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(image) # 输出结果 print("连通域数量(含背景):", num_labels) for i in range(1, num_labels): print(f"区域{i}: 面积={stats[i, cv2.CC_STAT_AREA]}, 中心坐标={centroids[i]}") ``` --- #### **八、注意事项** 1. **预处理关键**: - 需先进行二值化,且需根据场景选择阈值(如Otsu算法)。 - 噪声较多时,可先通过**开运算**消除小噪点。 2. **连通性选择**: - 细长物体(如文字)通常用8连通,避免断裂。 3. **性能优化**: - 大图像可改用逐块处理或优化算法(如并行计算)。 --- #### **九、与区域生长的对比** | **特性** | **连通域分析** | **区域生长** | |----------------|-------------------------------|---------------------------------| | **输入** | 二值图像 | 灰度/彩色图像 | | **自动化程度** | 全自动 | 需种子点或生长准则 | | **适用场景** | 分离已明确前景的区域 | 分割灰度渐变或纹理复杂的区域 | --- **总结**:连通域是图像处理中分离标记独立区域的基础工具,核心在于**连通性规则****标签合并算法**。掌握其原理与应用,可为目标检测、特征提取等任务奠定基础。
评论 61
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值