HALCON学习笔记(五)——图像分割

图像分割:将图像中具有特殊意义的不同区域划分开来,这些区域是不交互的。

一般采用的图像分割方法有阈值分割边缘检测区域生长霍夫变换等。

阈值分割

阈值分割:按图像灰度幅度进行分割的方法,把图像的灰度分成不同的等级,然后用设置灰度阈值的方法确定有意义的区域或要分割物体的边界。

难点:

  1. 无法确定图像分割生成区域的数目
  2. 阈值的确定(阈值选取过高,容易把大量的目标误判为背景;阈值选取过低,容易把大量的背景误判为目标)

阈值确定方法:

1.实验法

通过人眼的观察,对已知某些特征的图像试验不同的阈值,观察是否满足要求

2.根据直方图谷底确定阈值法

如果图像的前景物体内部和背景区域的灰度值分布都比较均匀,那么这个图形的灰度直方图具有明显的双峰,可以选择两峰之间的谷底对应的灰度值T作为阈值进行分割。

3.迭代选择阈值法

开始选择一个阈值作为初始估计值,按照某种规则不断地更新这一估计值,知道满足给定的条件为止。

4.最小均方误差法

以图像灰度为模式特征,假设各模式的灰度是独立分布的随机变量,并假设图像中待分割的模式服从一定的概率分布。一般来说采用正态分布。

5.最大类间方差法

在使用该方法对图像进行阈值分割的时候,选定的分割阈值应该使前景区域的平均灰度,背景区域的平均灰度与整幅图像的平均灰度之间差别最大,这种差异用方差来表示。

边缘检测

图像边缘是图像的基本特征,边缘上的点是指图像周围像素灰度产生变化的那些像素点,即灰度值导数较大的地方。

边缘检测的基本步骤:

  1. 平滑滤波:去除噪声(降低噪声的能力越强,边界强度的损失越大)
  2. 锐化滤波:加强了存在灰度局部变化位置的像素点
  3. 边缘判定:二值化处理和过零检测等
  4. 边缘连接:将间断的边缘连接为有意义的完整边缘,同时去除假边缘

边缘检测方法分类:

  • 基于查找的算法:通过寻找图像一阶导数中的最大值和最小值来检测边界,通常是将边界定位在梯度最大的方向,基于一阶导数的边缘检测算法,包括Roberts算子,Sobel算子,Prewitt算子等
  • 基于零穿越的算法:通过寻找图像二阶导数零穿越来寻找边界,通常是拉普拉斯过零点或非线性差分表示的过零点,基于二阶导数的边缘检测算法,包括高斯—拉普拉斯边缘检测算子
  • 除此之外还有Canny边缘检测算法,统计判别方法等

Roberts算子:

利用局部差分算子寻找边缘,边缘定位校准,但容易丢失一部分边缘,同事由于图像没有经过平滑处理,不具有一直噪声的能力。对具有陡峭边缘且噪声少的图像处理效果比较好。

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*用Roberts滤波器提取边缘
roberts (Image, ImageRoberts, 'roberts_max')
*阈值分割
threshold (ImageRoberts, Region, 30, 70)
*进行区域骨骼化
skeleton(Region, Skeleton)
dev_display (Image)
dev_set_color ('green')
dev_display (Skeleton)

Sobel算子:

根据当前像素点的8邻域点的灰度加权进行计算的算法,根据在边缘点处达到极值这一现象进行边缘检测。对噪声具有平滑作用,提供较为精准的边缘方向信息,但是由于局部平均的影响,同时也会检测出许多伪边缘,且边缘定位精度不高。

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*用Sobel算子进行滤波
sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
*阈值分割
threshold (EdgeAmplitude, Region, 30, 70)
*进行区域骨骼化
skeleton(Region, Skeleton)
dev_display (Image)
dev_set_color ('green')
dev_display (Skeleton)

Prewitt算子:

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*用Prewitt算子进行滤波
prewitt_amp (Image, ImageEdgeAmp)
*阈值分割
threshold (ImageEdgeAmp, Region, 30, 70)
*进行区域骨骼化
skeleton(Region, Skeleton)
dev_display (Image)
dev_set_color ('green')
dev_display (Skeleton)

Kirsch算子:

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*用Kirsch算子进行滤波
kirsch_amp (Image, ImageEdgeAmp)
*阈值分割
threshold (ImageEdgeAmp, Region, 30, 70)
*进行区域骨骼化
skeleton(Region, Skeleton)
dev_display (Image)
dev_set_color ('green')
dev_display (Skeleton)

高斯——拉普拉斯算子:

对噪声具有很大的敏感度,其幅值会产生双边缘;边缘方向不可检测性;使用前先进行高斯低通滤波

实例:

dev_close_window ()
read_image (Image, 'printer_chip/printer_chip_01')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
*进行拉普拉斯变换
laplace_of_gauss (Image, ImageLaplace, 5)
*通过提取拉普拉斯图像上的零交叉点进行边缘检测
zero_crossing (ImageLaplace, RegionCrossing)

Canny算子:

利用高斯函数一阶微分性质,把边缘检测问题转为检测准则函数极大值的问题,能在噪声抑制和边缘检测之间取得较好的折中;极小化由图像信噪比和边缘定位精度乘积组成的函数表达式,得到最优逼近算子

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*使用canny算法进行边缘提取
edges_image (Image, ImaAmp, ImaDir, 'canny', 0.5, 'nms', 20, 40)
threshold(ImaAmp, Region, 90, 255)
*骨骼化
skeleton (Region, Skeleton)
*将骨骼化的区域转化为XLD轮廓
gen_contours_skeleton_xld (Skeleton, Contours, 1, 'filter')
dev_display (Image)
dev_set_colored (6)
dev_display (Contours)

亚像素级别的边缘提取:

提取边缘时根据提取的边缘为像素或是亚像素分为像素边缘提取和亚像素边缘提取

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*利用sobel算法提取亚像素级别上的边缘
edges_sub_pix (Image, Edges, 'canny', 1, 20, 40)
dev_set_part (0, 0, 511, 511)
dev_display (Image)
dev_set_colored (6)
*边缘可视化
dev_display (Edges)

 

区域分割

区域分割利用的是图像的空间性质,认为分割出来的属于同一个区域的像素应具有相似的性质。传统的区域分割方法有区域生长和区域分裂与合并。

1.区域生长法

将一幅图像分成许多小的区域,并将具有相似性质的像素集合起来构成区域。

2.分裂合并法

阈值分割:从上到下(从整幅图像根据不同的阈值分成不同的区域)对图像进行分割

区域生长法:从下往上(从种子像素开始不断接纳新像素最后构成整幅图像)不断对像素进行合并,实质是先把图像分成任一大小而且不重叠 的区域,然后再合并成分裂这些区域以满足分割需求。

read_image (Image, 'printer_chip/printer_chip_01')
dev_set_colored (12)
*进行区域生长操作
regiongrowing (Image, Regions, 1, 1, 1, 1000)
*创建一个空区域
gen_empty_region (EmptyRegion)
*依据灰度值或颜色填充两个区域的间隙或分割重叠区域
expand_gray (Regions, Image, EmptyRegion, RegionExpand, 'maximal', 'image', 32)

Hough变换

Hough变换把二值图变换到Hough参数空间,在参数空间用极值点的检测来完成目标的检测。

例程:

read_image (Image, 'printer_chip/printer_chip_01')
*获取目标区域图像
rectangle1_domain (Image, ImageReduced, 100, 700, 200, 900)
*用Sobel边缘检测算子提取边缘
sobel_dir (ImageReduced, EdgeAmplitude, EdgeDirection, 'sum_abs', 3)
dev_set_color ('red')
*阈值分割得到边缘区域
threshold (EdgeAmplitude, Region, 80, 255)
reduce_domain (EdgeDirection, Region, ImageReduced1)
*用边缘方向信息进行霍夫变换
hough_lines_dir (ImageReduced1, HoughImage, Lines, 4, 2, 'mean', 3, 25, 5, 5, 'true', Angle, Dist)
*根据得到的angle dist生成线
gen_region_hline (Regions, Angle, Dist)
dev_display (Image)
dev_set_colored (6)
dev_set_draw ('margin')
dev_display (Regions)
dev_set_draw ('fill')
dev_display (Lines)

 

动态聚类分割

选择一些初始聚类中心,让样本按某种原则划分到各类中,得到初始分类,然后用某种原则进行修正,直到分类比较合理为止。

  1. K-均值聚类
  2. 模糊C-均值聚类

 

分水岭算法

基于拓扑理论的数学形态的分割算法,基本思想是把图像看作是测地学上的拓扑地貌,图像中每一个像素的灰度值表示该点的海拔高度,高灰度值代表山脉,低灰度值代表盆地,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成了分水岭。

分水岭算法相关算子

对区域作距离变换获得距离变换图:

distance_transform(region距离变换目标区域:distanceimage获得距离信息图:metric度量距离类型,foreground‘true’指针对前景区域作距离变换,‘false’指针对背景区域作距离变换,width,height输出图像大小设置

直接提取图像的分地区域和分水岭区域;

watersheds(image需要分割的图像(只能是byte/uint2/real类型):basins分割后得到的盆地信息,threshold分割时的阈值

实例:

read_image (Image, 'printer_chip/printer_chip_01')
*用高斯派生对一个图像进行卷积运算
derivate_gauss (Image, DerivGauss, 2, 'none')
*转换图像类型
convert_image_type (DerivGauss, ImageConverted, 'byte')
*提取图像的盆地区域和分水岭区域
watersheds (ImageConverted, Basins, Watersheds)
dev_set_draw ('margin')
dev_set_colored (6)
*显示最终的分水岭区域
dev_display (Watersheds)

 

 

 

 

 

 

 

 

你可能感兴趣的:(HALCON)