距离变换 matlab实现 opencv实现

距离变换将一幅二值图像(特征点为0,非特征点为1)变换为一幅灰度图像,灰度图像每一点的像素值为二值图像上非零像素到最近的0像素的距离。

Syntax

D = bwdist(BW)
[D,IDX] = bwdist(BW)
[D,IDX] = bwdist(BW,method)

Description

D = bwdist(BW) computesthe Euclidean distance transform of the binary imageBW.For each pixel in BW, the distance transform assignsa number that is the distance between that pixel and the nearest nonzeropixel ofBW. bwdist uses theEuclidean distance metric by default. BW can haveany dimension.D is the same size as BW.

[D,IDX] = bwdist(BW) alsocomputes the closest-pixel map in the form of an index array,IDX.(The closest-pixel map is also called the feature map, feature transform,or nearest-neighbor transform.)IDX has the samesize as BW and D. Each elementof IDX contains the linear index of the nearestnonzero pixel ofBW.

[D,IDX] = bwdist(BW,method) computesthe distance transform, wheremethod specifiesan alternate distance metric. method cantake any of the following values. Themethod stringcan be abbreviated.

Method

Description

'chessboard'

In2-D, the chessboard distance between (x1,y1) and (x2,y2)is max(│x1x2│,│y1y2│).

'cityblock'

In2-D, the cityblock distance between (x1,y1) and (x2,y2)is │x1x2│+ │y1y2│.

'euclidean'

In2-D, the Euclidean distance between (x1,y1) and (x2,y2)is

This is the default method.

'quasi-euclidean'

In2-D, the quasi-Euclidean distance between (x1,y1)and (x2,y2) is

Class Support

BW can be numeric or logical, and it mustbe nonsparse. D is a single matrix with the samesize asBW. The class of IDX dependson the number of elements in the input image, and is determined usingthe following table.

ClassRange
'uint32'numel(BW) <= 232 −1
'uint64'numel(BW) >= 232

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


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

 

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

ALAL
ALP
AL 

                           Mask  1

 BR
PBR
BRBR

                           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

  1. #include "opencv2/imgproc/imgproc.hpp"  
  2. #include "opencv2/highgui/highgui.hpp"  
  3. #include "math.h"  
  4. #include <stdio.h>  
  5.   
  6.   
  7. using namespace cv;  
  8.   
  9. Mat& DistTran(Mat& I);  
  10. Mat& NormImage(Mat& I);  
  11.   
  12. static float Round(float f)  
  13. {  
  14.     return ( ceil(f)-f > f-floor(f) ) ? floor(f) : ceil(f);  
  15. }  
  16.   
  17. int ChessBoardDist(int x1, int y1, int x2, int y2)  
  18. {  
  19.     return (abs(x1-x2) > abs(y1-y2)) ? abs(x1-x2) : abs(y1-y2);  
  20. }  
  21.   
  22. int CityBlockDist(int x1, int y1, int x2, int y2)  
  23. {  
  24.     return ( abs(x1-x2) + abs(y1-y2) );  
  25. }  
  26.   
  27. float EuclideanDist(int x1, int y1, int x2, int y2)  
  28. {  
  29.     return sqrt( (float)((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) );  
  30. }  
  31.   
  32. int MyMin(int x, int y)  
  33. {  
  34.     return (x < y) ? x : y;  
  35. }  
  36.   
  37. float MyMin(float x, float y)  
  38. {  
  39.     return (x < y) ? x : y;  
  40. }  
  41.   
  42. /** 
  43.  * @function main 
  44.  */  
  45. int main( int argc, char** argv )  
  46. {  
  47.   char* imageName = "test_wushuang.bmp";  
  48.   
  49.   Mat image;  
  50.   image = imread(imageName,1);  
  51.   if(!image.data)  
  52.   {  
  53.       printf("No image data\n");  
  54.   }  
  55.   
  56.   Mat gray_image;  
  57.   cvtColor( image, gray_image, CV_RGB2GRAY );  
  58.   
  59.     
  60.   DistTran( gray_image );  
  61.   NormImage( gray_image );  
  62.   
  63.     
  64.   imwrite("EuclideanDist_wushuang.bmp", gray_image);  
  65.   
  66.   namedWindow( imageName, CV_WINDOW_AUTOSIZE );  
  67.   namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );  
  68.   
  69.   imshow( imageName, image );  
  70.   imshow( "Gray image", gray_image );  
  71.   
  72.   waitKey(0);  
  73.   
  74.   
  75.     
  76.   return 0;  
  77. }  
  78.   
  79.   
  80. Mat& DistTran(Mat& I)  
  81. {  
  82.     // accept only char type matrices  
  83.     CV_Assert(I.depth() != sizeof(uchar));  
  84.     int channels = I.channels();  
  85.     int nRows = I.rows * channels;  
  86.     int nCols = I.cols;  
  87.     //if (I.isContinuous())  
  88.     //{  
  89.     //  nCols *= nRows;  
  90.     //  nRows = 1;  
  91.     //}  
  92.   
  93.     int i,j;  
  94.     uchar* p;  
  95.     uchar* q;  
  96.     //int min = 0;  
  97.     //int dis = 0;  
  98.     float fMin = 0.0;  
  99.     float fDis = 0.0;  
  100.   
  101.     // pass throuth from top to bottom, left to right  
  102.     for( i = 1; i < nRows-1; ++i)  
  103.     {  
  104.         p = I.ptr<uchar>(i);  
  105.         for ( j = 1; j < nCols; ++j)  
  106.         {  
  107.             /*q = I.ptr<uchar>(i-1); 
  108.             dis = CityBlockDist(i, j, i-1, j-1); 
  109.             min = MyMin( p[j], dis+q[j-1] ); 
  110.  
  111.             dis = CityBlockDist(i, j, i-1, j); 
  112.             min = MyMin( min, dis+q[j] ); 
  113.  
  114.             q = I.ptr<uchar>(i); 
  115.             dis = CityBlockDist(i, j, i, j-1); 
  116.             min = MyMin( min, dis+q[j-1] ); 
  117.  
  118.             q = I.ptr<uchar>(i+1); 
  119.             dis = CityBlockDist(i, j, i+1, j-1); 
  120.             min = MyMin( min, dis+q[j-1] ); 
  121.  
  122.             p[j] = min;*/  
  123.   
  124.             q = I.ptr<uchar>(i-1);  
  125.             fDis = EuclideanDist(i, j, i-1, j-1);  
  126.             fMin = MyMin( (float)p[j], fDis+q[j-1] );  
  127.   
  128.             fDis = EuclideanDist(i, j, i-1, j);  
  129.             fMin = MyMin( fMin, fDis+q[j] );  
  130.   
  131.             q = I.ptr<uchar>(i);  
  132.             fDis = EuclideanDist(i, j, i, j-1);  
  133.             fMin = MyMin( fMin, fDis+q[j-1] );  
  134.   
  135.             q = I.ptr<uchar>(i+1);  
  136.             fDis = EuclideanDist(i, j, i+1, j-1);  
  137.             fMin = MyMin( fMin, fDis+q[j-1] );  
  138.   
  139.             p[j] = (uchar)Round(fMin);  
  140.         }  
  141.     }  
  142.   
  143.     // pass throuth from bottom to top, right to left  
  144.     for( i = nRows-2; i > 0; i-- )  
  145.     {  
  146.         p = I.ptr<uchar>(i);  
  147.         for( j = nCols-1; j >= 0; j-- )  
  148.         {  
  149.             /*q = I.ptr<uchar>(i+1); 
  150.             dis = CityBlockDist(i, j, i+1, j); 
  151.             min = MyMin( p[j], dis+q[j] ); 
  152.  
  153.             dis = CityBlockDist(i, j, i+1, j+1); 
  154.             min = MyMin( min, dis+q[j+1] ); 
  155.  
  156.             q = I.ptr<uchar>(i); 
  157.             dis = CityBlockDist(i, j, i, j+1); 
  158.             min = MyMin( min, dis+q[j+1] ); 
  159.  
  160.             q = I.ptr<uchar>(i-1); 
  161.             dis = CityBlockDist(i, j, i-1, j+1); 
  162.             min = MyMin( min, dis+q[j+1] ); 
  163.  
  164.             p[j] = min;*/  
  165.   
  166.             q = I.ptr<uchar>(i+1);  
  167.             fDis = EuclideanDist(i, j, i+1, j);  
  168.             fMin = MyMin( (float)p[j], fDis+q[j] );  
  169.   
  170.             fDis = EuclideanDist(i, j, i+1, j+1);  
  171.             fMin = MyMin( fMin, fDis+q[j+1] );  
  172.   
  173.             q = I.ptr<uchar>(i);  
  174.             fDis = EuclideanDist(i, j, i, j+1);  
  175.             fMin = MyMin( fMin, fDis+q[j+1] );  
  176.   
  177.             q = I.ptr<uchar>(i-1);  
  178.             fDis = EuclideanDist(i, j, i-1, j+1);  
  179.             fMin = MyMin( fMin, fDis+q[j+1] );  
  180.   
  181.             p[j] = (uchar)Round(fMin);  
  182.         }  
  183.     }  
  184.   
  185.     return I;  
  186. }  
  187.   
  188.   
  189. Mat& NormImage(Mat& I)  
  190. {  
  191.     // accept only char type matrices  
  192.     CV_Assert(I.depth() != sizeof(uchar));  
  193.     int channels = I.channels();  
  194.     int nRows = I.rows * channels;  
  195.     int nCols = I.cols;  
  196.     //if (I.isContinuous())  
  197.     //{  
  198.     //  nCols *= nRows;  
  199.     //  nRows = 1;  
  200.     //}  
  201.   
  202.     int i,j;  
  203.     uchar* p;  
  204.     int min = 256;  
  205.     int max = -1;  
  206.   
  207.     // Do not count the outer boundary  
  208.     for( i = 1; i < nRows-1; ++i)  
  209.     {  
  210.         p = I.ptr<uchar>(i);  
  211.         for ( j = 1; j < nCols-1; ++j)  
  212.         {  
  213.             if( min > p[j] )  min = p[j];  
  214.             if( max < p[j] )  max = p[j];  
  215.         }  
  216.     }  
  217.   
  218.     for( i = 1; i < nRows-1; ++i)  
  219.     {  
  220.         p = I.ptr<uchar>(i);  
  221.         for ( j = 1; j < nCols-1; ++j)  
  222.         {  
  223.             p[j] = (p[j] - min) * 255 / (max - min);  
  224.         }  
  225.     }  
  226.   
  227.     return I;  
  228. }  


 

 

                                        原图                                                                                              棋盘距离变换 

 

 

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


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值