分享

fractal 分形维数 盒子维 纹理特征

 清风明月0391 2013-12-03

分形  盒子维纹理特征

在纹理特征的提取中,纹理的分形维数特征(FD)是对纹理的一种重要描述。图像的纹理越复杂、细腻,则分形维数越大。提取分形维数特征的方法有很多种,理论以及计算的复杂度各有差异。

本文中分形维数的计算方法采用的是 DBC(Differential Box-counting)即 差分盒子计数法。该方法是由Sarkar and Chaudhuri 于1994年前后提出的(An Efficient Differential  Box-Counting Approach to Compute Fractal Dimension of  Image),在前人的分形维数计算方法上做了重要改进,使得FD的计算以及准确度得到了较大的提升。在本文算法的编写过程中还参考了两篇中文综述:[二维灰度图像的分形维数计算.张志],[图像分形维数计算方法的比较.赵海英]。

为节省篇幅,先主要罗列所用到的基本公式,以及Sarkar原著中的论述,其他基本知识点,读者可参阅上述两篇中文综述。

 


D就是要求的纹理分形维数特征。由于D是Nr、1/r对应直线的斜率,所以需要多次改变r,即网格大小,获得多个样本点,最后通过直线拟合求得最终的D。


这种基于DBC的方法计算出的纹理分形维数特征的值应该介于2~3。这是有理论证明的。在Sarkar的原著中,仅有提及,未给证明:


[二维灰度图像的分形维数计算.张志]中作者则给出了 FD< 3 的证明。FD>2的证明类似。且[二维灰度图像的分形维数计算.张志]中,作者提及了Sarkar的DBC方法存在的问题,即DBC方法存在多余的空盒子。所以本文在程序设计时,注意了此问题,排除了空盒子的影响,得到了较好的FD计算效果。

现给出本次设计中分形盒子维的代码。代码经验证,FD值符合纹理复杂程度。理论上,FD值本身还应具有“三不变”特性:平移、旋转、缩放。经验证,在某些图像上,本算法具备缩放不变性,平移、旋转不变形未经验证。

代码之中存在的冗余、不适、bug还望各位读者指正。

(最小二乘法拟合基本原理:http://blog.csdn.net/ice_fire3/article/details/6709929)

  1. //************************//   
  2. //计算分形盒子维   
  3. //*** yangxin_szu 2013_03_28 ***//   
  4. //valarray与 MFC 有一定冲突    
  5. //#undef的使用是为了避免问题出现   
  6. #ifdef min    
  7. #undef min    
  8. #endif    
  9. #ifdef max    
  10. #undef max    
  11. #endif    
  12. #include <valarray>    
  13. using namespace std;  
  14. void My_Texture::Calculate_Fractal_Dim(unsigned char* Img_Data ,int Img_size)  
  15. {  
  16.     //*************************************************//   
  17.     //the width and height of the Image should be the same   
  18.     //gray level : 256   
  19.     //points for Least Square method: 20   
  20.     //*************************************************//   
  21.     int i=0 ,j=0;  
  22.     //分形盒子维相关参数   
  23.     int M = Img_size;//图像尺寸   
  24.     int G = 256;//图像灰度级   
  25.     int L_point = 20;//最小二乘法样本点数   
  26.     valarray<unsigned char> Img_VAL(Img_size*Img_size);  
  27.     valarray<int> L_VAL(L_point);  
  28.     valarray<int> h_VAL(L_point);  
  29.     valarray<double> r_VAL(L_point);  
  30.     valarray<double> Nr_VAL((double)0,L_point);  
  31.     valarray<int> Grid_Num(L_point);//网格数目   
  32.     valarray<double> fractal_D(0.0 ,L_point);  
  33.       
  34.     //复制数据   
  35.     int k = 0;  
  36.     for (i=0;i<Img_size;i++)  
  37.     {  
  38.         for (j=0;j<Img_size;j++)  
  39.         {  
  40.             Img_VAL[k] = Img_Data[i*Img_size + j];  
  41.             k++;  
  42.         }  
  43.     }  
  44.     //网格大小及相关参数   
  45.     //改进后的约束范围 M^(1/3)<= L <= M/3   
  46.     int L_min = (int)powf(M ,1/3.0);  
  47.     //int L_min = M/40;   
  48.     int L_max = (int)M/2;  
  49.     int L_step = (int)((L_max - L_min)/(float)L_point);  
  50.     for(i=0;i<L_point;i++)  
  51.     {  
  52.         L_VAL[i] = L_min + i*L_step;//各样本点对应的网格大小     L   
  53.         h_VAL[i] = (G*L_VAL[i])/M;  //各样本点对应的盒子高度     h   
  54.         r_VAL[i] = log10(1/(L_VAL[i]/(float)M));//各样本点对应的 r   
  55.         Grid_Num[i] = M/L_VAL[i];//各样本点对应的图像网格数目    Num   
  56.     }  
  57.   
  58.     int m =0,n =0,t=0;  
  59.     int grid_lt_x =0,grid_lt_y =0,grid_rd_x =0,grid_rd_y =0;  
  60.     unsigned char grid_I_max =0 ,grid_I_min =0;  
  61.     int dbc_l =0 ,dbc_k =0 ,nr =0;  
  62.     int s=0,p =0,q =0 ,box_non_zero =0,box_zero_count = 0;  
  63.     int gray_k =0,gray_l =0;  
  64.     //计算 Nr   
  65.     for (k=0;k<L_point;k++)  
  66.     {  
  67.         //临时存储单个网格数据   
  68.         valarray<unsigned char> grid_img((unsigned char)0,L_VAL[k]*L_VAL[k]);  
  69.         for (m=0;m<Grid_Num[k];m++)  
  70.         {  
  71.             for (n=0;n<Grid_Num[k];n++)  
  72.             {  
  73.                 //单个网格的坐标范围   
  74.                 grid_lt_x = n*L_VAL[k];  
  75.                 grid_lt_y = m*L_VAL[k];  
  76.                 grid_rd_x = grid_lt_x + L_VAL[k] - 1;  
  77.                 grid_rd_y = grid_lt_y + L_VAL[k] - 1;  
  78.                 //复制数据   
  79.                 t = 0;  
  80.                 for (i=grid_lt_y;i<grid_rd_y;i++)  
  81.                 {  
  82.                     for (j=grid_lt_x;j<grid_rd_x;j++)  
  83.                     {  
  84.                         grid_img[t] = Img_Data[i*M + j];  
  85.                         t++;  
  86.                     }  
  87.                 }  
  88.                 grid_I_min = grid_img.min();  
  89.                 grid_I_max = grid_img.max();  
  90.                 //最小、最大灰度所在的网格高度   
  91.                 dbc_k = grid_I_min/h_VAL[k];  
  92.                 dbc_l = grid_I_max/h_VAL[k];  
  93.                 //*******计算空盒子数目********//   
  94.                 for(s=dbc_k;s<=dbc_l;s++)  
  95.                 {  
  96.                     //灰度上下限   
  97.                     gray_k = s*h_VAL[k];  
  98.                     gray_l = gray_k + h_VAL[k] - 1;  
  99.                     //清零   
  100.                     box_non_zero = 0;  
  101.                     //落在指定盒子内的点数   
  102.                     for(p=0;p<t-1;p++)  
  103.                     {                         
  104.                         if((grid_img[p]>=gray_k)&&(grid_img[p]<=gray_l))  
  105.                             box_non_zero++;  
  106.                     }  
  107.                     //空盒子   
  108.                     if(box_non_zero == 0)  
  109.                         box_zero_count++;  
  110.                 }  
  111.                 //Nr累加并剔除空盒子   
  112.                 nr = dbc_l - dbc_k + 1 - box_zero_count;                  
  113.                 Nr_VAL[k] = Nr_VAL[k] + nr;  
  114.                 //清零   
  115.                 box_zero_count = 0;  
  116.             }  
  117.         }  
  118.         Nr_VAL[k] = log10(double(Nr_VAL[k]));  
  119.         grid_img.free();  
  120.     }  
  121.     //计算各样本点对应的理论斜率并保存   
  122.     fractal_D = Nr_VAL/r_VAL;  
  123.     ofstream outfile("F:\\Fractal_D.txt");//打开文件,准备写入   
  124.     for (j=0;j<L_point;j++)  
  125.     {  
  126.         outfile<<fractal_D[j]<<' '<<endl;//距离   
  127.     }  
  128.     outfile<<endl;  
  129.     outfile.close();//关闭文件,完成写入   
  130.     //****************************************//   
  131.     //最小二乘法拟合直线   
  132.     double A = 0.0;  
  133.     double B = 0.0;  
  134.     double C = 0.0;  
  135.     double D = 0.0;  
  136.   
  137.     A = (r_VAL*r_VAL).sum();  
  138.     B = r_VAL.sum();  
  139.     C = (r_VAL*Nr_VAL).sum();  
  140.     D = Nr_VAL.sum();  
  141.   
  142.     double fractal_k,fractal_b,tmp =0;  
  143.     if(tmp=(A*L_point-B*B))  
  144.     {  
  145.         fractal_k = (C*L_point-B*D)/tmp;  
  146.         fractal_b = (A*D-C*B)/tmp;  
  147.     }  
  148.     else  
  149.     {  
  150.         fractal_k = 1;  
  151.         fractal_b = 0;  
  152.     }  
  153.     //拟合得到的分形盒子维   
  154.     m_fractal_dim = fractal_k;  
  155.     m_fractal_shift = fractal_b;  
  156.   
  157.     //释放所有 valarray对象   
  158.     Img_VAL.free();  
  159.     L_VAL.free();  
  160.     h_VAL.free();  
  161.     r_VAL.free();  
  162.     Nr_VAL.free();  
  163.     Grid_Num.free();  
  164.     fractal_D.free();  
  165.   
  166. }  

算法效果:

  

FD = 2.73                           FD = 2.85

FD = 2.14                           FD = 2.16                     FD = 2.886

上图中黑色图像可能由于制图时截图所致,边缘像素以及图像品质变化,图像并非纯黑,且FD是由点拟合而来,所以此时的FD没能等于 2.由以上5幅图像可见,FD与纹理分布的细密、复杂程度符合得较好。



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多