距離
定義
滿足以下函數條件
D(p,q)>=0,當且僅當p=q時D(p,q)=0;
D(p,q)=D(q,p)
D(p,r)<=D(p,q)+D(q,r)
歐式距離
D[(i,j),(k,h)]=((i-k)^2+(j-h)^2)^(1/2);

城市街區距離
只允許橫向以及縱向的移動
D[(i,j),(k,h)]=|i-k|+|j-h|;

棋盤距離
允許橫向、縱向以及對角線上的移動
D[(i,j),(k,h)]=max{|i-k|,|j-h|}
算法實現
步驟
1.按照一種距離度量D,D是D4或D8,對大小為M*N的圖像的一個子集S計算距離變換,建立一個M*N的數組F並作初始化:子集S中元素置為0,
其他置為無窮。
2.按行遍歷圖像,從上到下,從左到右。對於上方和左面的鄰接像素設F(p)=min[F(p),D(p,q)+F(q)]。
3.按行遍歷圖像,從下到上,從右到左。對於下方和右面的鄰接像素設F(p)=min[F(p),D(p,q)+F(q)]。
4.數組F中得到的是子集S的斜切。
具體函數
初始化函數
void DistanceTransformD4(vector<vector<int>> &src, vector<vector<int>> &f)
{
int cols = src[0].size();
int rows = src.size();
//初始化
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
if (src[i][j] == 1)
f[i][j] = 0;
else
f[i][j] = INT_MAX - 2;//簡單的防止溢出
//按行遍歷圖像,從上到下,從左到右
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
D4AL(i, j, rows, cols, f);
//按行遍歷圖像,從下到上,從右到左
for (int i = rows - 1; i >= 0; --i)
for (int j = cols - 1; j >= 0; --j)
D4BR(i, j, rows, cols, f);
}
左變換函數
void D4AL(int i,int j, int rows, int cols, vector<vector<int>> &f)
{
//上
if (InArea(i - 1, j, rows, cols))
f[i][j] = min(f[i][j], 1 + f[i - 1][j]);
//左上
if (InArea(i - 1, j - 1, rows, cols))
f[i][j] = min(f[i][j], 2 + f[i - 1][j - 1]);
//左
if (InArea(i, j - 1, rows, cols))
f[i][j] = min(f[i][j], 1 + f[i][j - 1]);
//左下
if (InArea(i + 1, j - 1, rows, cols))
f[i][j] = min(f[i][j], 2 + f[i + 1][j - 1]);
}
右變換函數
void D4BR(int i, int j, int rows, int cols, vector<vector<int>> &f)
{
//下
if (InArea(i + 1, j, rows, cols))
f[i][j] = min(f[i][j], 1 + f[i + 1][j]);
//右下
if (InArea(i + 1, j + 1, rows, cols))
f[i][j] = min(f[i][j], 2 + f[i + 1][j + 1]);
//右
if (InArea(i, j + 1, rows, cols))
f[i][j] = min(f[i][j], 1 + f[i][j + 1]);
//右上
if (InArea(i - 1, j + 1, rows, cols))
f[i][j] = min(f[i][j], 2 + f[i - 1][j + 1]);
}
判斷是否出界函數
bool InArea(int i, int j, int rows, int cols)
{
if (i<0 || i>=rows)
return false;
if (j<0 || j>=cols)
return false;
return true;
}