Examples
Compute the Euclidean distance transform.
bw = zeros(5,5); bw(2,2) = 1; bw(4,4) = 1
bw =
0 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 1 0
0 0 0 0 0
[D,IDX] = bwdist(bw)
D =
1.4142 1.0000 1.4142 2.2361 3.1623
1.0000 0 1.0000 2.0000 2.2361
1.4142 1.0000 1.4142 1.0000 1.4142
2.2361 2.0000 1.0000 0 1.0000
3.1623 2.2361 1.4142 1.0000 1.4142
IDX =
7 7 7 7 7
7 7 7 7 19
7 7 7 19 19
7 7 19 19 19
7 19 19 19 19
In the nearest-neighbor matrix IDX the values 7 and 19 representthe position of the nonzero elements using linear matrix indexing.If a pixel contains a 7, its closest nonzero neighbor is at linearposition 7.
Compare the 2-D distance transforms for each of the supporteddistance methods. In the figure, note how the quasi-Euclidean distancetransform best approximates the circular shape achieved by the Euclideandistance method.
bw = zeros(200,200); bw(50,50) = 1; bw(50,150) = 1;
bw(150,100) = 1;
D1 = bwdist(bw,'euclidean');
D2 = bwdist(bw,'cityblock');
D3 = bwdist(bw,'chessboard');
D4 = bwdist(bw,'quasi-euclidean');
figure
subplot(2,2,1), subimage(mat2gray(D1)), title('Euclidean')
hold on, imcontour(D1)
subplot(2,2,2), subimage(mat2gray(D2)), title('City block')
hold on, imcontour(D2)
subplot(2,2,3), subimage(mat2gray(D3)), title('Chessboard')
hold on, imcontour(D3)
subplot(2,2,4), subimage(mat2gray(D4)), title('Quasi-Euclidean')
hold on, imcontour(D4)
Compare isosurface plots for the distance transforms of a 3-Dimage containing a single nonzero pixel in the center.
bw = zeros(50,50,50); bw(25,25,25) = 1;
D1 = bwdist(bw);
D2 = bwdist(bw,'cityblock');
D3 = bwdist(bw,'chessboard');
D4 = bwdist(bw,'quasi-euclidean');
figure
subplot(2,2,1), isosurface(D1,15), axis equal, view(3)
camlight, lighting gouraud, title('Euclidean')
subplot(2,2,2), isosurface(D2,15), axis equal, view(3)
camlight, lighting gouraud, title('City block')
subplot(2,2,3), isosurface(D3,15), axis equal, view(3)
camlight, lighting gouraud, title('Chessboard')
subplot(2,2,4), isosurface(D4,15), axis equal, view(3)
camlight, lighting gouraud, title('Quasi-Euclidean')
出处:桑卡, 《图像处理分析与机器视觉》
计算全局图像中各个像素点对子图像的距离。
AL
AL
AL
P
AL
Mask 1
BR
P
BR
BR
BR
Mask 2
1. 将图像进行二值化,子图像值为0,背景为255;
2. 利用Mask 1从左向右,从上到下扫描,p点是当前像素点,q点是Mask 1中AL邻域中的点,D()为距离计算,包括棋盘距离、城市距离和欧式距离。F(p)为p点的像素值,计算
F(p) = min( F(p), F(q)+D(p,q) ), 其中,q属于AL.
3. 再利用Mask 2从右向左,从下向上扫描,计算
F(p) = min( F(p), F(q)+D(p,q) ), 其中,q属于BR
4. F(p) 则为距离变换后的图像。
代码如下,基于OpenCV 2.4
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "math.h"
#include
usingnamespacecv;
Mat& DistTran(Mat& I);
Mat& NormImage(Mat& I);
staticfloatRound(floatf)
{
return( ceil(f)-f > f-floor(f) ) ? floor(f) : ceil(f);
}
intChessBoardDist(intx1,inty1,intx2,inty2)
{
return(abs(x1-x2) > abs(y1-y2)) ? abs(x1-x2) : abs(y1-y2);
}
intCityBlockDist(intx1,inty1,intx2,inty2)
{
return( abs(x1-x2) + abs(y1-y2) );
}
floatEuclideanDist(intx1,inty1,intx2,inty2)
{
returnsqrt( (float)((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) );
}
intMyMin(intx,inty)
{
return(x
}
floatMyMin(floatx,floaty)
{
return(x
}
/**
* @function main
*/
intmain(intargc,char** argv )
{
char* imageName ="test_wushuang.bmp";
Mat image;
image = imread(imageName,1);
if(!image.data)
{
printf("No image data\n");
}
Mat gray_image;
cvtColor( image, gray_image, CV_RGB2GRAY );
DistTran( gray_image );
NormImage( gray_image );
imwrite("EuclideanDist_wushuang.bmp", gray_image);
namedWindow( imageName, CV_WINDOW_AUTOSIZE );
namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );
imshow( imageName, image );
imshow( "Gray image", gray_image );
waitKey(0);
return0;
}
Mat& DistTran(Mat& I)
{
// accept only char type matrices
CV_Assert(I.depth() != sizeof(uchar));
intchannels = I.channels();
intnRows = I.rows * channels;
intnCols = I.cols;
//if (I.isContinuous())
//{
// nCols *= nRows;
// nRows = 1;
//}
inti,j;
uchar* p;
uchar* q;
//int min = 0;
//int dis = 0;
floatfMin = 0.0;
floatfDis = 0.0;
// pass throuth from top to bottom, left to right
for( i = 1; i
{
p = I.ptr(i);
for( j = 1; j
{
/*q = I.ptr(i-1);
dis = CityBlockDist(i, j, i-1, j-1);
min = MyMin( p[j], dis+q[j-1] );
dis = CityBlockDist(i, j, i-1, j);
min = MyMin( min, dis+q[j] );
q = I.ptr(i);
dis = CityBlockDist(i, j, i, j-1);
min = MyMin( min, dis+q[j-1] );
q = I.ptr(i+1);
dis = CityBlockDist(i, j, i+1, j-1);
min = MyMin( min, dis+q[j-1] );
p[j] = min;*/
q = I.ptr(i-1);
fDis = EuclideanDist(i, j, i-1, j-1);
fMin = MyMin( (float)p[j], fDis+q[j-1] );
fDis = EuclideanDist(i, j, i-1, j);
fMin = MyMin( fMin, fDis+q[j] );
q = I.ptr(i);
fDis = EuclideanDist(i, j, i, j-1);
fMin = MyMin( fMin, fDis+q[j-1] );
q = I.ptr(i+1);
fDis = EuclideanDist(i, j, i+1, j-1);
fMin = MyMin( fMin, fDis+q[j-1] );
p[j] = (uchar)Round(fMin);
}
}
// pass throuth from bottom to top, right to left
for( i = nRows-2; i > 0; i-- )
{
p = I.ptr(i);
for( j = nCols-1; j >= 0; j-- )
{
/*q = I.ptr(i+1);
dis = CityBlockDist(i, j, i+1, j);
min = MyMin( p[j], dis+q[j] );
dis = CityBlockDist(i, j, i+1, j+1);
min = MyMin( min, dis+q[j+1] );
q = I.ptr(i);
dis = CityBlockDist(i, j, i, j+1);
min = MyMin( min, dis+q[j+1] );
q = I.ptr(i-1);
dis = CityBlockDist(i, j, i-1, j+1);
min = MyMin( min, dis+q[j+1] );
p[j] = min;*/
q = I.ptr(i+1);
fDis = EuclideanDist(i, j, i+1, j);
fMin = MyMin( (float)p[j], fDis+q[j] );
fDis = EuclideanDist(i, j, i+1, j+1);
fMin = MyMin( fMin, fDis+q[j+1] );
q = I.ptr(i);
fDis = EuclideanDist(i, j, i, j+1);
fMin = MyMin( fMin, fDis+q[j+1] );
q = I.ptr(i-1);
fDis = EuclideanDist(i, j, i-1, j+1);
fMin = MyMin( fMin, fDis+q[j+1] );
p[j] = (uchar)Round(fMin);
}
}
returnI;
}
Mat& NormImage(Mat& I)
{
// accept only char type matrices
CV_Assert(I.depth() != sizeof(uchar));
intchannels = I.channels();
intnRows = I.rows * channels;
intnCols = I.cols;
//if (I.isContinuous())
//{
// nCols *= nRows;
// nRows = 1;
//}
inti,j;
uchar* p;
intmin = 256;
intmax = -1;
// Do not count the outer boundary
for( i = 1; i
{
p = I.ptr(i);
for( j = 1; j
{
if( min > p[j] ) min = p[j];
if( max
}
}
for( i = 1; i
{
p = I.ptr(i);
for( j = 1; j
{
p[j] = (p[j] - min) * 255 / (max - min);
}
}
returnI;
}
原图 棋盘距离变换
城市距离变换 欧式距离变换