1,距离变换概念
1.1 距离变换的目的
距离变换提供了像素与某个图像子集(可能表示物体或某些特征)的距离度量。
距离变换是图像外理只中常用的一种图像变换算法,它计算出每个像素离图像中满足某个特定条件的像素的距离,然后使用这人计算出的距离进行灰度值的变换。
1.2 常用距离度量
常用的距离有:欧几里德距离、棋盘距离、街区距离(曼哈顿距离)。
这一个距离中最常用的距离是欧几里德距离。
1.3 距离变换的应用
距离变换的应用非常广泛,以下是几个常见的应用:
形态学分割:距离变换可以用于形态学分割,通过计算图像中每个像素到离它最近的背景像素的距离,可以得到一张距离图像,再通过应用闻值分割,可以得到一个二值图像,其中距离小于闻值的像素会被标记为前景,距离大于等于闻值的像素会被标记为背景,从而实现图像分割。
图像形态学:距离变换可以用于图像形态学操作,如骨架提取、形态学梯度等。通过计算图像中每个像素到其周围像素的距离,可以得到张距离图像,再通过应用形态学操作,如膨胀和腐蚀等,可以得到不同的形态学变换结果。
边缘检测:距离变换可以用于边缘检测,通过计算图像中每个像素到最近的边缘像素的距离,可以得到一张距离图像,再通过应用非极大值抑制和闽值分割等操作,可以得到图像的边缘
模板匹配:距离变换可以用于模板匹配,通过计算图像中每个像素到模板像索的距离,可以得到一张距离图像,再通过应用闻值分割等操作,可以得到匹配结果。
1.4 距离变换算法的输入输出
输入:二值图;输出:灰度图
1.5 距离变换实例
一个比较好的例子,就是目标物体是白色圆形,背景为黑色,源图像如下图所示:
其中背景(黑色部分)和目标物体(白色部分)两个集合都是已经确定的,现在度量的是目标物体到背景的距离。经过距离变换后的图像是什么样的呢?如下图所示,
理解:从距离变换后的图中可以看出,离背景部分距离越远,该点也就越亮(像素值越大)。那么这个性质有什么用呢?可以想象一下,在黑色的背景中的任意一个物体,那个经过距离变换后最亮的像素点不就可以大致看作这个物体的形心吗!这个形心可以为后续的图像处理提供信息,比如作为种子区域生长法的初始种子。
细心的同学可能发现,距离变换后的图像有几道比较亮的直线,不符合设想啊,按理说,应该是一个无数个(理想情况)同心圆组成的图案啊。产生这一现象和下面我要介绍的内容——距离变换的具体计算有关。
2 ,距离变换算法
距离变换实际就是求一个点到点集合的最近距离,那么首先就是来确定这个距离。常用的距离公式有欧式距离、曼哈顿距离等等,不太了解的同学可以自行百度,具体使用哪种距离进行度量,需要结合自己的实际情况来选择。
2.1 直观计算:
确定了距离公式之后,根据直观的理解应该怎么计算呢?还是拿上面的例子进行说明,B代表着黑色背景的集合,里面有
b
1
,
b
2
,
b
3
b_1,b_2,b_3
b1,b2,b3 ……等一些点;W代表着白色物体的集合,里面有
w
1
,
w
2
,
w
3
w_1,w_2,w_3
w1,w2,w3
……等一些点。
现在我们就是要计算W集合里面的每一个点,到B集合的距离,那么我们就每一次取一个W里面的
w
i
w_i
wi ,然后根据距离公式,计算
w
i
w_i
wi 到B集合每一个点
b
j
b_j
bj 的距离
D
i
j
D_{ij}
Dij ,取其中距离
D
i
j
D_{ij}
Dij 最小的值,作为最后的度量结果,直到W集合的每一个点都计算一遍。
实际上,在进行计算距离这一步之前,还要遍历图像把像素点分成两个集合,这种直观的计算相对来说,较复杂且花费时间较长,因此前人发明一种快速计算距离变换的方法。
2.2 快速计算:
通过掩模进行遍历图像,掩模如下,
这是一个应用比较普遍的模板,我在学习到这里的时候,脑子里就出现了一个疑问,为什么模板是上面那个而不是下面的掩模?按照常理来说相邻像素之间的距离应该为1啊?
后来我想明白了,对于同种元素来确实可以用空间距离来度量他们之间的关系,但是距离变换针对的是两个不同的元素集合,这两个元素集合本身就具有一定差异,我们需要一定的数值来描述这个差异。因此我们设置目标集合和背景集合最近的距离为3而不是1,在3的基础上再逐渐增加,这样会让距离变换后的效果更加明显(显示出来的效果图也会更亮)。这个初始距离可以并不是一定为3,也可以为4,5,6等等,是可以人为设置的,但是在编程的时候,并不意味这个初始距离可以无限大,因为灰度值只有256个,所以最大的距离也就是255,所以需要设置合适的初始距离值,保证距离空间足够大。
那么为什么把那两个掩模分别遍历两遍就可以计算出来距离变换的结果呢?这里需要想明白两个点,1、为什么掩模可以计算出距离?;2、为什么需要两次遍历图像?。要弄明白第一个问题,需要去实践;实践中你会发现通过掩模和这套规则可以计算距离(没有办法很清晰的用语言表达出来,大家可以去试验一下,相信会有一些体会)。至于第二个问题,我想用“星火燎原”来表达很合适,在掩模没有遇到背景元素之前目标,是求不出来距离的,因为掩模位置上的值都是无穷,只有遇到背景元素之后,才开始求出距离并蔓延开。所以,从左上角到右下角和从右下角到左上角的两次遍历就可以保证星火(即背景像素)蔓延整张图片。大家可以看下图中的一个实例,体会一下
那么上面白色圆的距离变换实例为什么会出现几条亮白线,我认为应该是和距离公式的选取和模板本身的量级有关,如果模板足够大应该不会出现这种现象。这是我的想法,也不能十分确定,如果有同学有不同的意见,非常希望告知!
是否可以通过一个掩模遍历一次图像求距离?
首先不能一次遍历图像,原因参照上面为什么需要两次遍历图像。但是可以用一个3*3的模板多次遍历图像,原理也是从背景像素逐渐向外扩展,直到所有目标像素的距离计算出来。这种方法感觉并不是特别实用,虽然减少了编程量,但是却大大增加了时间复杂度,有点花里胡哨。一个实例可以方便大家理解:
参考:
https://blog.csdn.net/qq_35535744/article/details/95247601
https://blog.csdn.net/wenhao_ir/article/details/51656160