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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值