“浓淡补正”是基恩士视觉的一个很强大的算法工具。使用“浓淡补正”的预处理,可以消除工件表面的光泽和阴影,仅抽取污点及瑕疵。(如下图)
至于它的实现原理,网上搜不到相关资料。不过根据它的实现效果,能大致窥见它的原理:排除背景渐变的浓淡变化,只抽取对比度急剧变化的部分。
看到这句话,想必有些人已经想到了一个词“动态阈值”,没错,动态阈值是跟它有几分相似,这个我后面第二部分再分析。
一、浓淡补正的近似实现
下图中,要把“黑点”和“弯曲的细黑线”提取出来,其中黑点正方形的边长是5个像素。
处理算法如下:
1 read_image (Image, '白格矩阵.jpg')
2 rgb1_to_gray (Image, GrayImage)
3
4 gen_disc_se (SE, 'byte', 11, 11, 0) //设计结构元素
5 gray_dilation (GrayImage, SE, ImageDilation)
6 gray_erosion (ImageDilation, SE, ImageErosion)
7 sub_image (ImageErosion, GrayImage, ImageSub, 1, 120) //这个120也可以设置其他值
构造的结构元素是一个11 × 11的矩形结构元素。
分析:
① gray_dilation (GrayImage, SE, ImageDilation),对图像进行灰度值像素膨胀,即灰度值较大的区域膨胀,面积变大。(如下图左ImageDilation)
② gray_erosion (ImageDilation, SE, ImageErosion),对图像进行灰度值像素收缩,即灰度值较大的区域收缩,面积变小。(如下图右ImageErosion)
③ 在灰度值像素膨胀的过程中,原图中的“小黑点”和“细长的黑线”被它们周围的高亮灰度值像素膨胀覆盖掉了。(如下图左)
④ 在灰度值像素收缩的过程中,图中的白格子面积缩小,几乎恢复原状,不过在上一步中被膨胀覆盖掉的小黑点、细黑线不可能再复原了。
⑤ sub_image (ImageErosion, GrayImage, ImageSub, 1, 120),用无黑点、无黑线的图ImageErosion减去原始图,就有效提取出了黑点和黑线。(如上图所示)
使用这种方式提取复杂背景的黑点和黑线,有什么注意点呢?
① 结构元素要构造得合理,一般来说,构造正方形结构元素最通用。
② 图中“小黑点”的边长是5 pix,结构元素至少要设置为6 × 6 才行,不然不能有效提取出小黑点。
③ 点只能提取较小的,线也只能提取较细长的。(因为结构元素设计过大,可能会有难以预料的结果)
下图中展示了结构元素分别为3 × 3、50 × 50时,最终的效果图ImageSub:
如果其他图像中,要提取白色的点和白色细线呢?其实只需要把gray_erosion、gray_dilation这两行调换一下顺序即可,如下:
1 gray_erosion (GrayImage, SE, ImageErosion)
2 gray_dilation (ImageErosion, SE, ImageDilation) // 膨胀、腐蚀调换顺序
3 sub_image (ImageDilation, GrayImage, ImageSub, 1, 120)
二、复杂背景下的算法表现
1、光照不均匀背景下黑色小脏污提取
算法跟最前面的那个一样,只是把结构元素改成19 × 19,处理结果图经阈值分割后如下:
2、去除手写笔记图的重阴影
算法如下:
1 read_image (Image, '手写笔记.jpg')
2 rgb1_to_gray (Image, GrayImage)
3
4 gen_disc_se (SE, 'byte', 7, 7, 0) //设计结构元素
5 gray_dilation (GrayImage, SE, ImageDilation)
6 gray_erosion (ImageDilation, SE, ImageErosion)
7
8 * 上面是用ImageErosion - GrayImage,这里是反过来,其实都可以
9 sub_image (GrayImage, ImageErosion, ImageSub, 1, 110)
10 **invert_image (ImageSub, ImageInvert)
11 scale_image_max (ImageSub, ImageScaleMax) //拓展色阶,增强对比度
3、光照不均匀、对比度低的字符提取
算法如下:
1 read_image (Image, '产品号.png')
2 rgb1_to_gray (Image, GrayImage)
3 threshold (GrayImage, RegionTemp, 150, 200) //观察原始图阈值分割
4
5 gen_disc_se (SE, 'byte', 19, 19, 0) //设计结构元素
6 gray_dilation (GrayImage, SE, ImageDilation)
7 gray_erosion (ImageDilation, SE, ImageErosion)
8 sub_image (ImageErosion, GrayImage, ImageSub, 1, 120)
9 threshold (ImageSub, Regions, 140, 200) //观察处理后图像阈值分割
上面的几个例子,应该已经足够说明“灰度值膨胀、腐蚀、图像差分”这套算法逻辑的强大。
同时也要再强调一下它的适用情况:适用于背景复杂或光照不均匀的细小或者狭长的缺陷的提取。
三、动态阈值
动态阈值也是通过捕捉局部灰度值的剧烈变化,将缺陷从光照不均匀背景中分割出来的算法。与上面的算法有类似之处,下面研究一下这两种算法有什么不同。
以之前的“白格矩阵.jpg”图为例:
1 read_image (Image, '白格矩阵.jpg')
2 rgb1_to_gray (Image, GrayImage)
3
4 get_image_size (GrayImage, Width, Height)
5 mean_image (GrayImage, ImageMean, 15, 15)
6 dyn_threshold (GrayImage, ImageMean, RegionDynThresh, 20, 'dark')
7 connection (RegionDynThresh, ConnectedRegions)
8 select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 10, 99999)
9 **region_to_bin (SelectedRegions, BinImage, 0, 255, Width, Height)
可以看出,使用动态阈值也可以将黑点和黑线轻松分离出来。但是动态阈值有一个缺陷:它容易把图像边缘也当做“灰度值变化剧烈”的区域找出来,这就属于误判了,后面还需要设计算法去过滤掉边缘找出的区域。
上面这张图不是“光照不均匀”的图,对于光照不均匀的图,动态阈值的表现如何呢?(以“黑色污点.jpg”为例)
1 read_image (Image, '黑色污点.jpg')
2 rgb1_to_gray (Image, GrayImage)
3
4 get_image_size (GrayImage, Width, Height)
5 mean_image (GrayImage, ImageMean, 15, 15)
6 dyn_threshold (GrayImage, ImageMean, RegionDynThresh, 50, 'dark')
7 connection (RegionDynThresh, ConnectedRegions)
8 select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 10, 99999)
9 **region_to_bin (SelectedRegions, BinImage, 0, 255, Width, Height)
虽然也基本分割出来了,但是经过本人反复调整参数对比,效果其实略差于前面的“近似浓淡补正”算法。
这两种算法具体怎么选,要根据实际项目需要,以及算法处理时间来决定。当图片尺寸很大时(例如大于1000万像素),动态阈值的算法时间更短。
四、diff_of_gauss
高斯-拉普拉斯算子又称为LOG(Laplacian of Gaussian)算子,是在高斯函数的基础上再利用拉普拉斯算子提取边缘得出的一个算子。
拉普拉斯算子是一种高通滤波器,是影像灰度函数在两个垂直方向二阶偏导数之和。在离散数字影像的情况下,直接用影像灰度级的二阶差分代替连续情形下的二阶偏导数,对噪声很敏感,在提取边缘时往往会出现伪边缘响应。为克服拉普拉斯算子的不足,宜先对数字影像进行低通滤波,抑制噪声。高斯函数是一种很好的归一化低通滤波器,可用于对数字影像进行低通滤波以减少噪声的影响,在此基础上再利用拉普拉斯算子提取边缘。
简单说就是:先用高斯模糊进行降噪(低通滤波),再用拉普拉斯算子进行边缘提取(高通滤波)。
由于diff_of_gauss算子的这种特性,其实也适合做光照不均匀图像中的特征分割。
1 read_image (Image, '产品号.png')
2 rgb1_to_gray (Image, GrayImage)
3
4 diff_of_gauss (GrayImage, DiffOfGauss, 2, 1.2)
5 threshold (DiffOfGauss, Region, 2, 9)
五、相关算子
灰度腐蚀(或膨胀)的算子一共有3个:gray_erosion、gray_erosion_rect、gray_erosion_shape。
其用法和说明如下:(注意注释)
gen_disc_se (SE, 'byte', 9, 9, 0) //生成结构元素,一般是圆形或者椭圆
gray_erosion (Image, SE, ImageErosion) //圆形结构元素腐蚀,耗时35ms
gray_erosion_rect (Image, ImageErosion, 9, 9) //矩形结构元素腐蚀,耗时28.2ms
gray_erosion_shape (Image, ImageErosion, 9, 9, 'rectangle') //矩形结构元素腐蚀,耗时28.1ms
gray_erosion_shape (Image, ImageErosion, 9, 9, 'octagon') //八角形结构元素腐蚀,耗时39ms
gray_erosion_shape (Image, ImageErosion, 9, 9, 'rhombus') //菱形结构元素腐蚀,耗时45ms
以上就是对复杂背景中细小缺陷检测的阶段性学习成果,欢迎留言讨论。
【参考文章】
基恩士视觉的预处理功能:浓淡补正、渐变滤波器等等
Halcon学习笔记之OCR系列-环形字符,斜体字
Halcon 算子 diff_of_gauss
--------------------------------------------
本文系原创,转载请注明出处。
如果文章对您有帮助,可以点击下方的【好文要顶】或【关注我】;如果您想进一步表示感谢,可通过网页右侧的【打赏】功能进行打赏。
感谢您的支持,我会继续写出更多的相关文章!文章有不理解的地方欢迎跟帖交流,博主经常在线!^_^