基本概念

欧式距离变换(Euclidean distance transform)用于将 二值图像 变换为 灰度图像,灰度图中各个像素点的灰度级与该像素点到背景像素的最小距离有关。

按距离类型划分,距离变换可分为:非欧氏距离变换欧氏距离变换(EDT)。其中 EDT 精度高,与实际距离相符,应用更广泛。

在二维平面上定义两点,那么他们之间的欧氏距离表示为:
python欧氏距离标准化 欧氏距离变换_ci
在二值图像中,1 表示前景点,0 表示背景点;在灰度图像中,像素的灰度值表示为该像素到最近前景点的距离。假设前景为 O,背景为 B,距离图为 D,则距离变换定义为:
python欧氏距离标准化 欧氏距离变换_python欧氏距离标准化_02
其中,python欧氏距离标准化 欧氏距离变换_欧氏距离_03

距离变换步骤

参考:

1) 将图像中的目标像素点分类,分为内部点,外部点和孤立点

以中心像素的四邻域为例,如果中心像素为前景像素(像素值为1)且四邻域均为前景像素,则该点为 内部点。如果该中心像素为前景像素,四邻域为背景像素(像素值为0),则该中心点为 孤立点。除了内部点和孤立点之外的目标区域点为 边界点

python欧氏距离标准化 欧氏距离变换_邻域_04


2) 计算图像中所有的内部点和非内部点,点的集合分别记为 S1,S2

3) 对于 S1 中的每一个内部点 (x,y),使用距离公式 disf() 计算其在 S2 中的最小距离,这些最小距离构成集合 S3

4) 计算 S3 中的最大值和最小值 Max,Min

5) 对于每一个内部点,转换后的灰度值 G 计算如下,其中 S3(x,y) 表示 S1 中内部点 (x,y) 在 S2 中的最小距离

python欧氏距离标准化 欧氏距离变换_python欧氏距离标准化_05

6) 孤立点保持不变

from scipy import ndimage

scipy.ndimage.morphology.distance_transform_edt(input, sampling=None, return_distances=True, return_indices=False, distances=None, indices=None)

执行欧式距离变换。除了距离变换外,还可以计算特征变换。在这种情况下,沿着结果的第一个轴返回最近的背景元素的索引。

  • input:用于进行距离变换的输入数据,可以是任何类型
  • sampling:float 或 int 类型
  • return_distances:bool 类型,是否返回距离矩阵
  • return_indices:bool 类型,是否返回索引矩阵
  • distance:n 维数组,输出距离,float64类型
  • indices:n 维数组,输出索引,int32类型

返回值: distance_transform_edt,n 维数组或列表,是距离矩阵、索引矩阵或者两者均输出,取决于输入参数 return_x

计算欧式距离:
python欧氏距离标准化 欧氏距离变换_ci_06
python欧氏距离标准化 欧氏距离变换_邻域_07 是像素值为 0 的背景点,python欧氏距离标准化 欧氏距离变换_python欧氏距离标准化_08 是输入坐标点,python欧氏距离标准化 欧氏距离变换_邻域_09

>>> a = np.array(([0,1,1,1,1],
                  [0,0,1,1,1],
                  [0,1,1,1,1],
                  [0,1,1,1,0],
                  [0,1,1,0,0]))
>>> from scipy import ndimage
>>> ndimage.distance_transform_edt(a)
array([[ 0.    ,  1.    ,  1.4142,  2.2361,  3.    ],
       [ 0.    ,  0.    ,  1.    ,  2.    ,  2.    ],
       [ 0.    ,  1.    ,  1.4142,  1.4142,  1.    ],
       [ 0.    ,  1.    ,  1.4142,  1.    ,  0.    ],
       [ 0.    ,  1.    ,  1.    ,  0.    ,  0.    ]])


>>> ndimage.distance_transform_edt(a, sampling=[2,1])
array([[ 0.    ,  1.    ,  2.    ,  2.8284,  3.6056],
       [ 0.    ,  0.    ,  1.    ,  2.    ,  3.    ],
       [ 0.    ,  1.    ,  2.    ,  2.2361,  2.    ],
       [ 0.    ,  1.    ,  2.    ,  1.    ,  0.    ],
       [ 0.    ,  1.    ,  1.    ,  0.    ,  0.    ]])

>>> edt, inds = ndimage.distance_transform_edt(a, return_indices=True)
>>> inds
array([[[0, 0, 1, 1, 3],
        [1, 1, 1, 1, 3],
        [2, 2, 1, 3, 3],
        [3, 3, 4, 4, 3],
        [4, 4, 4, 4, 4]],
       [[0, 0, 1, 1, 4],
        [0, 1, 1, 1, 4],
        [0, 0, 1, 4, 4],
        [0, 0, 3, 3, 4],
        [0, 0, 3, 3, 4]]])

>>> indices = np.zeros(((np.ndim(a),) + a.shape), dtype=np.int32)
>>> ndimage.distance_transform_edt(a, return_indices=True, indices=indices)
array([[ 0.    ,  1.    ,  1.4142,  2.2361,  3.    ],
       [ 0.    ,  0.    ,  1.    ,  2.    ,  2.    ],
       [ 0.    ,  1.    ,  1.4142,  1.4142,  1.    ],
       [ 0.    ,  1.    ,  1.4142,  1.    ,  0.    ],
       [ 0.    ,  1.    ,  1.    ,  0.    ,  0.    ]])
>>> indices
array([[[0, 0, 1, 1, 3],
        [1, 1, 1, 1, 3],
        [2, 2, 1, 3, 3],
        [3, 3, 4, 4, 3],
        [4, 4, 4, 4, 4]],
       [[0, 0, 1, 1, 4],
        [0, 1, 1, 1, 4],
        [0, 0, 1, 4, 4],
        [0, 0, 3, 3, 4],
        [0, 0, 3, 3, 4]]])