matlab实现距离变换,距离变换 matlab实现 opencv实现

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)

0818b9ca8b590ca3270a3433284dd417.png

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')

0818b9ca8b590ca3270a3433284dd417.png

出处:桑卡, 《图像处理分析与机器视觉》

计算全局图像中各个像素点对子图像的距离。

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;

}

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

原图                                                                                              棋盘距离变换

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

城市距离变换                                                                               欧式距离变换

你可能感兴趣的:(matlab实现距离变换)