(原)欧式距离变换

欧氏距离变换以后再添加。

 

下面分别给出计算欧式距离(EDT)的matlab和C代码。

 

参考网址

https://lost-contact.mit.edu/afs/cs.stanford.edu/package/matlab-r2009b/matlab/r2009b/toolbox/images/images/private/mexsrc/bwdistComputeEDT/

不清楚上面的网址是什么情况,但是有很多的matlab的mex文件的源码。

matlab:

 1 % 下面的为欧式距离变换的代码
 2 function Dr = mybwdist(binaryimg)  
 3 [height, width]=size(binaryimg); 
 4 D=[];
 5 for  k = 1: width   % 由于matlab按列存储,所以内层遍历行,外层遍历列。
 6     D=[D calcFirstPassD1(binaryimg(:,k), height)];
 7 end 
 8  
 9 Dr=processDimN([height, width], D); 
10 
11 end
12 
13 function D=calcFirstPassD1(I, vectorLength)
14 D1=zeros(vectorLength,1);
15 
16 %     // Initialize D1 - Feature points get set to zero, -1 otherwise
17 %     D1(i) = (I(col*nrows+i) == 1) ? 0.0f : -1.0f;
18 D1(I==0)= (-1);
19 
20 %     // Process column 
21 D=voronoiEDT(D1);  
22  
23 end
24 
25 function D=voronoiEDT(D)
26  
27 %     // Note: g and h are working vectors allocated in calling function
28 [ns, g, h] = constructPartialVoronoi(D);
29 if ns == -1
30     return;
31 end
32 
33 D=queryPartialVoronoi(g, h, ns, D);
34 
35 end 
36 
37 function [el, g, h]=constructPartialVoronoi(D)
38 %     //
39 %     // Construct partial voronoi diagram (see Maurer et al., 2003, Fig. 5, lines 1-14)
40 %     // Note: short variable names are used to mimic the notation of the paper
41 %     //
42 g=zeros(1,length(D));
43 h=zeros(1,length(D));
44 el = -1;
45 for k = 0:length(D)-1   % 在matlab中对应数组的高度
46     fk = D(k+1);
47     if fk ~= -1
48         if (el < 1)
49             el=el+1;
50             g(el+1) = fk;
51             h(el+1) = k;
52         else 
53             while ( (el >= 1) && RemoveEDT(g(el), g(el+1), fk, h(el), h(el+1), k))
54                 el=el-1;
55             end  
56             el=el+1;
57             g(el+1) = fk;
58             h(el+1) = k;
59         end
60     end
61 end
62 
63 end
64 
65 function res = RemoveEDT(du, dv, dw, u, v, w)
66 a = v - u;
67 b = w - v;
68 c = w - u;
69 
70 %     // See Eq. 2 from Maurer et al., 2003
71 res=(c * dv - b * du - a * dw) > (a * b * c);
72 end
73 
74 function D=queryPartialVoronoi(g, h, ns, D)
75 
76 %     //
77 %     // Query partial Voronoi diagram (see Maurer et al., 2003, Fig. 5, lines 18-24)
78 %     //
79 el = 0;
80 for k = 0:length(D)-1
81     while ( (el < ns) && ((g(el+1) + ((h(el+1) - k)*(h(el+1) - k))) > (g(el+2) + ((h(el+2) - k)*(h(el+2) - k)))) ) 
82         el=el+1;
83     end
84     D(k+1) = g(el+1) + (h(el+1) - k)*(h(el+1) - k);
85 end
86 end
87 
88 function D3=processDimN(dims, D)
89 %     // Create temporary vectors for processing along dimension N
90 D3=[];
91 for k = 0 : dims(1)-1         % // 若为二维数组,则得到第一维元素总数,即行数。注意,matlab按列存储,C按行存储。
92 % // Generate indices to points along vector path
93     D3=[D3;voronoiEDT(D(k+1,:))];
94 end
95 end

分别使用matlab自带的bwdist、上面的代码进行测试,测试结果一样。

C++代码(进行了简化,将不需要的代码合并了,同时,有些代码并非完全对应,但是结果正确。注意,matlab调用时需要取反,下面的C代码不再需要取反,如107行):

  1 // Removal Function - FVs that are the Voronoi sites of Voronoi cells that do not intersect Rd are removed
  2 inline bool RemoveEDT(const double du, const double dv, const double dw, const double u, const double v, const double w)
  3 {
  4     double a = v - u;
  5     double b = w - v;
  6     double c = w - u;
  7 
  8     // See Eq. 2 from Maurer et al., 2003
  9     return ((c * dv - b * du - a * dw) > (a * b * c));
 10 }
 11 
 12 inline int constructPartialVoronoi(double* D, double* g, int* h, int length)
 13 {
 14     //
 15     // Construct partial voronoi diagram (see Maurer et al., 2003, Fig. 5, lines 1-14)
 16     // Note: short variable names are used to mimic the notation of the paper
 17     //
 18     int el = -1;
 19 
 20     for (int k = 0; k < length; k++)
 21     {
 22         double fk = D[k];
 23         if (fk != -1.0f)
 24         {
 25             if (el < 1)
 26             {
 27                 el++;
 28                 g[el] = fk;
 29                 h[el] = k;
 30             }
 31             else
 32             {
 33                 while ((el >= 1) && RemoveEDT(g[el - 1], g[el], fk, h[el - 1], h[el], k))
 34                 {
 35                     el--;
 36                 }
 37                 el++;
 38                 g[el] = fk;
 39                 h[el] = k;
 40             }
 41         }
 42     }
 43 
 44     return(el);
 45 }
 46 
 47 inline void queryPartialVoronoi(const double* g, const int* h, const int ns, double* D, int length)
 48 {
 49     //
 50     // Query partial Voronoi diagram (see Maurer et al., 2003, Fig. 5, lines 18-24)
 51     //
 52     int el = 0;
 53 
 54     for (int k = 0; k < length; k++)
 55     {
 56         while ((el < ns) && ((g[el] + ((h[el] - k)*(h[el] - k))) >(g[el + 1] + ((h[el + 1] - k)*(h[el + 1] - k))))) 
 57         {
 58             el++;
 59         }
 60         D[k] = g[el] + (h[el] - k)*(h[el] - k);
 61     }
 62 }
 63 
 64 void voronoiEDT(double* D, double* g, int* h, int length)
 65 {
 66     // Note: g and h are working vectors allocated in calling function
 67     int ns = constructPartialVoronoi(D, g, h, length);
 68     if (ns == -1)
 69         return;
 70 
 71     queryPartialVoronoi(g, h, ns, D, length);
 72 
 73     return;
 74 }
 75 
 76 inline void processDimN(int width, int height/*const mwSize *dims, const mwSize ndims*/, double *D)
 77 {
 78     // Create temporary vectors for processing along dimension N
 79 
 80     double* g = new double[width];
 81     int* h = new int[width];
 82 
 83     // 若为二维数组,则得到第一维元素总数,即行数。注意,matlab按列存储,C按行存储。
 84     for (int k = 0; k < height; k++)
 85     {
 86         // Process vector
 87         voronoiEDT(&D[k*width], g, h, width);
 88     }
 89 
 90     delete[] g;
 91     delete[] h;
 92 }
 93 
 94 // mxI为输入,unsigned char*类型,mxD为输出,double* 类型
 95 // 注意,matlab中mxI是逻辑类型,需要1-mxI才是真正的输入;此处省略了这一步。
 96 // 输入为二值化图像,大于阈值的不为0,小于阈值的为0。
 97 void computeEDT(double *mxD, const unsigned char *mxI, int width, int height)
 98 {
 99     double* D1 = new double[width];
100     double* g = new double[width];
101     int* h = new int[width];
102 
103     for (int k = 0; k < width; k++)
104     {
105         for (int i = 0; i < height; i++)
106         {
107             D1[i] = (mxI[i*width + k] == 0) ? 0.0f : -1.0f;
108         }
109 
110         voronoiEDT(D1, g, h, height);
111 
112         for (int i = 0; i < height; i++)
113         {
114             mxD[i*width + k] = D1[i];
115         }
116     }
117 
118     delete[] D1;
119     delete[] g;
120     delete[] h;
121 
122     processDimN(width, height, mxD);
123 }

matlab代码对320*240的图像处理,耗时200ms左右(记不清了);当然,matlab使用的自带的代码耗时2ms左右。C中debug时耗时9ms,release耗时2ms。

posted on 2015-03-16 16:36  darkknightzh  阅读(2297)  评论(2编辑  收藏  举报

导航