灰度直方图
横坐标:是 0~255 表示灰度值的范围
纵坐标:是在不同灰度值下像素的个数!
那么灰度直方图的本质就是统计不同灰度下像素的个数!
它的直观目的,就是查看灰度的分布情况!
与之相关的函数:
threshold
threshold (ImageChannel3, Regions, 248, 255)
全局的阈值分割
binary_threshold
binary_threshold (ImageChannel3, Region, 'max_separability', 'dark', UsedThreshold)
如果你的背景和产品是很分明的,各自的灰度都有一个峰值(如上图)
这个函数会自动生产一个灰度值,可以很好的区分产品和背景。
'max_separability' 是一个算法的选择
'dark' 表示你想要的是比较暗的那个部分!
UsedThreshold,就是根据算法自动算出的灰度值!
mean_image
mean_image (Image, ImageMean, 13, 13)
字面意思就是,求图像的平均。专业的说法就是 【大名鼎鼎的】 均值滤波。
第一个参数是原始的图片,第二个参数是,滤波后的图片,最后两个参数表示,卷积核的大小(也就是平均的一个范围的大小)
我们来看看均值滤波的效果。
均值滤波后,给人的第一感觉就是,图片变模糊了,轮廓处没有那么分明了!
“ 那个这个均值滤波感觉没啥作用啊!”,我一度这么认为。
但其实,我们对对图片做某种滤波操作是,有的时候并不是为了宏观上的图片展示效果,而是微观上每个像素的值!比如均值滤波!得到每个像素值后再结合另个一个算子dyn_threshold达到目的!
dyn_threshold
dyn_threshold算子,字面意思就是 动态阈值,又名 局部阈值。比全局阈值 threshold,多了一个前缀 dyn_ 。不过是动态阈值,还是全局阈值,他们的目的都是 为了 做图片分割!把我们感兴趣的部分挑出来。动态阈值 的优势在于,在光照不均匀的情况下,还能做分割!
我们来看看这张图片:
很明显的光照不均匀,左边的偏暗,右边的偏亮!就是说产品是一个整体,是我们感兴趣的地方,需要将其分割出来,但是产品的左边变暗,右边偏亮,如果用全局阈值,那边我们很难将产品从图片中分割出来。全局分割效果如下:
动态阈值,或者说局部阈值,就能解决这个问题!它的思路是,将某个像素和周围的像素做对比,如果比 周围像素的平均值 高出某个值 就会被分割出来。这就体现了局部的特点。从而避开了光照不均的问题。
那现在的问题是 周围像素的平均值 ,这个平均值哪里来。没错,就是 mean_image。
mean_image 和 dyn_threshold 均一般是联合使用的。
首先对,图片做一个均值滤波,然后通过动态阈值,对比局部均值,分割出高出平均值一定值的像素点。
mean_image (Image, ImageMean, 27, 27)
dyn_threshold (Image, ImageMean, RegionDynThresh, 5, 'light')
dyn_threshold 参数解释:
第四个参数(5) 的意思 就是 如果比 平均值高出5,那么改像素就是我们想要的。
mean_image 卷积核大小的选择:
卷积核越大,平均的范围就越大,也就是这个“局部”越大!如果我们把卷积核设置的比较小,看看会有什么情况:
有的产品边缘提取出来是空心的,这是因为,产品边缘线中间的区域像素差不多,在加上平均的局部区域比较小,那么中间的像素和平均像素就会相差无几,所以不会被选中。
这时,我们就需要增加卷积核的大小,卷积核的大小得比你想选中得边缘要大,这样求出均值就会更低,这样就不会出现空心的问题。
小结:
这篇文章,由灰度直方图,引出了三个常用的用于分割的函数:
- threshold 全局阈值分割
- binary_threshold
- dyn_threshold 动态阈值分割
- mean_image 均值滤波。
更多的,分割算子可以到halcon的实例代码中的Segmentation分区中去寻找: