距离变换 matlab实现 opencv实现

来源:互联网 发布:足球数据库软件哪个好 编辑:程序博客网 时间:2024/05/17 13:46

距离变换将一幅二值图像(特征点为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 inBW, 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 asBW.

[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 elementofIDX 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 ofIDX 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) = 1bw =     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.4142IDX =     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');figuresubplot(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');figuresubplot(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')


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

 

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

ALALALPAL 

                           Mask  1

 BRPBRBRBR

                           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

[cpp] view plaincopy
  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. }  


 

 

                                        原图                                                                                              棋盘距离变换 

 

 

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


原创粉丝点击