zoukankan      html  css  js  c++  java
  • (原)欧式距离变换

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

    下面分别给出计算欧式距离(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。

  • 相关阅读:
    tomcat报错:java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
    mysql 的 case when 用法
    分享几个能用的 editplus 注册码
    windows 时间同步至最新时间方法 | windows 时间同步服务器
    tomcat 如何登录 Server Status、Manager App、Host Manager
    Eclipse将java项目导出可执行的jar文件
    Java 中将字符串与 unicode 相互转换的工具类
    解决Lost connection to MySQL server during query错误方法
    gt,gte,lt,lte缩写的含义
    python 打印调用栈
  • 原文地址:https://www.cnblogs.com/darkknightzh/p/4342195.html
Copyright © 2011-2022 走看看