LBP(Local Binary Pattern,局部二值模式)

        LBPLocal Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子;它具有旋转不变性和灰度不变性等显著的优点。它是首先由T. Ojala, M.Pietik?inen, D. Harwood 1994年提出,用于纹理特征提取。而且,提取的特征是图像的局部的纹理特征;

1LBP特征的描述

         原始的LBP算子定义为在3*3的窗口内,以窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,3*3邻域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理信息。如下图所示:

                   

LBP的改进版本:

       原始的LBP提出后,研究人员不断对其提出了各种改进和优化。

1)圆形LBP算子:

        基本的 LBP 算子的最大缺陷在于它只覆盖了一个固定半径范围内的小区域,这显然不能满足不同尺寸和频率纹理的需要。为了适应不同尺度的纹理特征,并达到灰度和旋转不变性的要求,Ojala 等对 LBP 算子进行了改进,将 3×邻域扩展到任意邻域,并用圆形邻域代替了正方形邻域,改进后的 LBP 算子允许在半径为 R 的圆形邻域内有任意多个像素点。从而得到了诸如半径为R的圆形区域内含有P个采样点的LBP算子;

                

2LBP旋转不变模式

       从 LBP 的定义可以看出,LBP 算子是灰度不变的,但却不是旋转不变的。图像的旋转就会得到不同的 LBP值。

         Maenpaa等人又将 LBP 算子进行了扩展,提出了具有旋转不变性的 LBP 算子,即不断旋转圆形邻域得到一系列初始定义的 LBP 值,取其最小值作为该邻域的 LBP 值。

       图 2.5 给出了求取旋转不变的 LBP 的过程示意图,图中算子下方的数字表示该算子对应的 LBP 值,图中所示的 8  LBP模式,经过旋转不变的处理,最终得到的具有旋转不变性的 LBP 值为 15。也就是说,图中的 8  LBP 模式对应的旋转不变的 LBP 模式都是00001111

3LBP等价模式

       一个LBP算子可以产生不同的二进制模式,对于半径为R的圆形区域内含有P个采样点的LBP算子将会产生P2 种模式。很显然,随着邻域集内采样点数的增加,二进制模式的种类是急剧增加的。例如:5×5邻域内20个采样点,有2201,048,576种二进制模式。如此多的二值模式无论对于纹理的提取还是对于纹理的识别、分类及信息的存取都是不利的。同时,过多的模式种类对于纹理的表达是不利的。例如,将LBP算子用于纹理分类或人脸识别时,常采用LBP模式的统计直方图来表达图像的信息,而较多的模式种类将使得数据量过大,且直方图过于稀疏。因此,需要对原始的LBP模式进行降维,使得数据量减少的情况下能最好的代表图像的信息。

        为了解决二进制模式过多的问题,提高统计性,Ojala提出了采用一种“等价模式”(Uniform Pattern)来对LBP算子的模式种类进行降维。Ojala等认为,在实际图像中,绝大多数LBP模式最多只包含两次从10或从01的跳变。因此,Ojala将“等价模式”定义为:当某个LBP所对应的循环二进制数从01或从10最多有两次跳变时,该LBP所对应的二进制就称为一个等价模式类。000000000次跳变),00000111(只含一次从01的跳变),10001111(先由1跳到0,再由0跳到1,共两次跳变)都是等价模式类。除等价模式类以外的模式都归为另一类,称为混合模式类,例如10010111(共四次跳变)(这是我的个人理解,不知道对不对)。

       通过这样的改进,二进制模式的种类大大减少,而不会丢失任何信息。模式数量由原来的2P种减少为 P ( P-1)+2种,其中P表示邻域集内的采样点数。对于3×3邻域内8个采样点来说,二进制模式由原始的256种减少为58种,这使得特征向量的维数更少,并且可以减少高频噪声带来的影响。

2LBP特征用于检测的原理

       显而易见的是,上述提取的LBP算子在每个像素点都可以得到一个LBP“编码”,那么,对一幅图像(记录的是每个像素点的灰度值)提取其原始的LBP算子之后,得到的原始LBP特征依然是“一幅图片”(记录的是每个像素点的LBP值)。

                    

        LBP的应用中,如纹理分类、人脸分析等,一般都不将LBP图谱作为特征向量用于分类识别,而是采用LBP特征谱的统计直方图作为特征向量用于分类识别。

       因为,从上面的分析我们可以看出,这个“特征”跟位置信息是紧密相关的。直接对两幅图片提取这种“特征”,并进行判别分析的话,会因为“位置没有对准”而产生很大的误差。后来,研究人员发现,可以将一幅图片划分为若干的子区域,对每个子区域内的每个像素点都提取LBP特征,然后,在每个子区域内建立LBP特征的统计直方图。如此一来,每个子区域,就可以用一个统计直方图来进行描述;整个图片就由若干个统计直方图组成;

        例如:一幅100*100像素大小的图片,划分为10*10=100个子区域(可以通过多种方式来划分区域),每个子区域的大小为10*10像素;在每个子区域内的每个像素点,提取其LBP特征,然后,建立统计直方图;这样,这幅图片就有10*10个子区域,也就有了10*10个统计直方图,利用这10*10个统计直方图,就可以描述这幅图片了。之后,我们利用各种相似性度量函数,就可以判断两幅图像之间的相似性了;

3、对LBP特征向量进行提取的步骤

1)首先将检测窗口划分为16×16的小区域(cell);

2)对于每个cell中的一个像素,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,3*3邻域内的8个点经比较可产生8位二进制数,即得到该窗口中心像素点的LBP值;

3)然后计算每个cell的直方图,即每个数字(假定是十进制数LBP值)出现的频率;然后对该直方图进行归一化处理。

4)最后将得到的每个cell的统计直方图进行连接成为一个特征向量,也就是整幅图的LBP纹理特征向量;

然后便可利用SVM或者其他机器学习算法进行分类了。

4LBP特征的实现(参考博客:http://blog.csdn.net/jinshengtao/article/details/18219697)

      下面代码用C实现,读入一副灰度图像,采样点个数,采样半径,对每个像素计算LBP特征并输出,LBP图像及其直方图。

对于旋转不变性及uniform旋转不变性,我没有对每个像素都进行上述公式的操作,由于是2进制的圆形循环,可以提前做个mapping映射关系,加快程序执行速度。

 采样点数量均为8,采样半径为10

输入图像:

                


4.1 灰度不变性LBP:

[cpp]  view plain copy
  1. void gray_invariant_lbp(IplImage *src,int height,int width,int num_sp,MyPoint *spoint)  
  2. {  
  3.     IplImage *target,*hist;  
  4.     int i,j,k,box_x,box_y,orign_x,orign_y,dx,dy,tx,ty,fy,fx,cy,cx,v;  
  5.     double min_x,max_x,min_y,max_y,w1,w2,w3,w4,N,x,y;  
  6.     int *result;  
  7.     float dishu;  
  8.       
  9.     dishu = 2.0;  
  10.     max_x=0;max_y=0;min_x=0;min_y=0;  
  11.     for (k=0;k
  12.     {  
  13.         if (max_x
  14.         {  
  15.             max_x=spoint[k].x;  
  16.         }  
  17.         if (max_y
  18.         {  
  19.             max_y=spoint[k].y;  
  20.         }  
  21.         if (min_x>spoint[k].x)  
  22.         {  
  23.             min_x=spoint[k].x;  
  24.         }  
  25.         if (min_y>spoint[k].y)  
  26.         {  
  27.             min_y=spoint[k].y;  
  28.         }  
  29.     }  
  30.   
  31.     //计算模版大小  
  32.     box_x = ceil(MAX(max_x,0)) - floor(MIN(min_x,0)) + 1;  
  33.     box_y = ceil(MAX(max_y,0)) - floor(MIN(min_y,0)) + 1;  
  34.       
  35.     if (width
  36.     {  
  37.         printf("Too small input image. Should be at least (2*radius+1) x (2*radius+1)");  
  38.         return;  
  39.     }  
  40.   
  41.     //计算可滤波图像大小,opencv图像数组下标从0开始  
  42.     orign_x = 0 - floor(MIN(min_x,0));//起点  
  43.     orign_y = 0 - floor(MIN(min_x,0));  
  44.       
  45.     dx = width - box_x+1;//终点  
  46.     dy = height - box_y+1;  
  47.       
  48.     int cols = pow(dishu,(float)num_sp);  
  49.     hist = cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);//直方图图像  
  50.     target = cvCreateImage(cvSize(dx,dy),IPL_DEPTH_8U,1);  
  51.     result = (int *)malloc(sizeof(int)*dx*dy);  
  52.     double *val_hist = (double *)malloc(sizeof(double)*cols);   //直方图数组  
  53.       
  54.     memset(result,0,sizeof(int)*dx*dy);  
  55.     CvRect roi =cvRect(orign_x, orign_y, dx, dy);  
  56.     cvSetImageROI(src, roi);  
  57.     cvCopy(src, target);    
  58.     cvResetImageROI(src);  
  59.     cvSaveImage("haha.jpg",target);  
  60.       
  61.     for ( k = 0; k
  62.     {  
  63.         x = spoint[k].x+orign_x;  
  64.         y = spoint[k].y+orign_y;  
  65.   
  66.         //二线性插值图像  
  67.         fy = floor(y);  //向下取整  
  68.         fx = floor(x);  
  69.         cy = ceil(y);   //向上取整  
  70.         cx = ceil(x);  
  71.         ty = y - fy;  
  72.         tx = x - fx;  
  73.         w1 = (1 - tx) * (1 - ty);  
  74.         w2 = tx  * (1 - ty);  
  75.         w3 = (1 - tx) * ty ;  
  76.         w4 = tx * ty ;  
  77.         v = pow(dishu,(float)k);  
  78.   
  79.         for (i = 0;i
  80.         {  
  81.             for (j = 0;j
  82.             {  
  83.                 //灰度插值图像像素  
  84.                 N = w1 * (double)(unsigned char)src->imageData[(i+fy)*src->width+j+fx]+  
  85.                       w2 * (double)(unsigned char)src->imageData[(i+fy)*src->width+j+cx]+  
  86.                       w3 * (double)(unsigned char)src->imageData[(i+cy)*src->width+j+fx]+  
  87.                       w4 * (double)(unsigned char)src->imageData[(i+cy)*src->width+j+cx];  
  88.                   
  89.                 if( N >= (double)(unsigned char)target->imageData[i*dx+j])  
  90.                 {  
  91.                     result[i*dx+j] = result[i*dx+j] + v * 1;  
  92.                 }else{  
  93.                     result[i*dx+j] = result[i*dx+j] + v * 0;  
  94.                 }  
  95.             }  
  96.         }  
  97.     }  
  98.     //显示图像  
  99.     if (num_sp<=8)  
  100.     {  
  101.         //只有采样数小于8,则编码范围0-255,才能显示图像  
  102.         for (i = 0;i
  103.         {  
  104.             for (j = 0;j
  105.             {  
  106.                 target->imageData[i*dx+j] = (unsigned char)result[i*dx+j];  
  107.                 //printf("%d\n",(unsigned char)target->imageData[i*width+j]);  
  108.             }  
  109.         }  
  110.         cvSaveImage("result.jpg",target);  
  111.     }  
  112.       
  113.     //显示直方图  
  114.   
  115.     for (i=0;i
  116.     {  
  117.         val_hist[i]=0.0;  
  118.     }  
  119.     for (i=0; i
  120.     {  
  121.         val_hist[result[i]]++;  
  122.     }  
  123.       
  124.     double temp_max=0.0;  
  125.   
  126.     for (i=0;i//求直方图最大值,为了归一化  
  127.     {  
  128.         //printf("%f\n",val_hist[i]);  
  129.         if (temp_max
  130.         {  
  131.             temp_max=val_hist[i];  
  132.         }  
  133.     }  
  134.     //画直方图  
  135.     CvPoint p1,p2;  
  136.     double bin_width=(double)hist->width/cols;  
  137.     double bin_unith=(double)hist->height/temp_max;  
  138.   
  139.     for (i=0;i
  140.     {  
  141.         p1.x=i*bin_width;p1.y=hist->height;  
  142.         p2.x=(i+1)*bin_width;p2.y=hist->height-val_hist[i]*bin_unith;  
  143.         cvRectangle(hist,p1,p2,cvScalar(0,255),-1,8,0);  
  144.     }  
  145.     cvSaveImage("hist.jpg",hist);  
  146. }  
实验结果:

                

                


4.2 旋转不变性:

[cpp]  view plain copy
  1. void rotation_invariant_mapping(int range,int num_sp,int *Mapping)  
  2. {  
  3.     int newMax,rm,r;  
  4.     int *tmpMap;  
  5.   
  6.     newMax = 0;  
  7.     tmpMap = (int *)malloc(sizeof(int)*range);  
  8.     memset(tmpMap,-1,sizeof(int)*range);  
  9.   
  10.     for (int i = 0 ; i < range ; i++)  
  11.     {  
  12.         rm = i;  
  13.         r = i;  
  14.         for (int j = 0 ; j < num_sp -1 ;j++)  
  15.         {  
  16.             //将r向左循环移动一位,当r超过num_sp位时,舍弃  
  17.             r = r << 1;  
  18.             if (r > range -1)  
  19.             {  
  20.                 r = r - (range -1);  
  21.             }  
  22.             //printf("%d,%d\n",r,rm);  
  23.             if (r < rm)  
  24.             {  
  25.                 rm = r;  
  26.             }  
  27.         }  
  28.         if (tmpMap[rm] < 0)  
  29.         {  
  30.             tmpMap[rm] = newMax;  
  31.             newMax++;  
  32.               
  33.         }  
  34.         Mapping[i] = tmpMap[rm];  
  35.     }  
  36.     free(tmpMap);  
  37. }  
  38.   
  39. void rotation_invariant_lbp(IplImage *src,int height,int width,int num_sp,MyPoint *spoint,int *Mapping)  
  40. {  
  41.     IplImage *target,*hist;  
  42.     int i,j,k,box_x,box_y,orign_x,orign_y,dx,dy,tx,ty,fy,fx,cy,cx,v;  
  43.     double min_x,max_x,min_y,max_y,w1,w2,w3,w4,N,x,y;  
  44.     int *result;  
  45.     float dishu;  
  46.   
  47.     dishu = 2.0;  
  48.     max_x=0;max_y=0;min_x=0;min_y=0;  
  49.     for (k=0;k
  50.     {  
  51.         if (max_x
  52.         {  
  53.             max_x=spoint[k].x;  
  54.         }  
  55.         if (max_y
  56.         {  
  57.             max_y=spoint[k].y;  
  58.         }  
  59.         if (min_x>spoint[k].x)  
  60.         {  
  61.             min_x=spoint[k].x;  
  62.         }  
  63.         if (min_y>spoint[k].y)  
  64.         {  
  65.             min_y=spoint[k].y;  
  66.         }  
  67.     }  
  68.   
  69.     //计算模版大小  
  70.     box_x = ceil(MAX(max_x,0)) - floor(MIN(min_x,0)) + 1;  
  71.     box_y = ceil(MAX(max_y,0)) - floor(MIN(min_y,0)) + 1;  
  72.   
  73.     if (width
  74.     {  
  75.         printf("Too small input image. Should be at least (2*radius+1) x (2*radius+1)");  
  76.         return;  
  77.     }  
  78.   
  79.     //计算可滤波图像大小,opencv图像数组下标从0开始  
  80.     orign_x = 0 - floor(MIN(min_x,0));//起点  
  81.     orign_y = 0 - floor(MIN(min_x,0));  
  82.   
  83.     dx = width - box_x+1;//终点  
  84.     dy = height - box_y+1;  
  85.   
  86.     target = cvCreateImage(cvSize(dx,dy),IPL_DEPTH_8U,1);  
  87.     result = (int *)malloc(sizeof(int)*dx*dy);  
  88.       
  89.     memset(result,0,sizeof(int)*dx*dy);  
  90.     CvRect roi =cvRect(orign_x, orign_y, dx, dy);  
  91.     cvSetImageROI(src, roi);  
  92.     cvCopy(src, target);    
  93.     cvResetImageROI(src);  
  94.     cvSaveImage("haha.jpg",target);  
  95.   
  96.     for ( k = 0; k
  97.     {  
  98.         x = spoint[k].x+orign_x;  
  99.         y = spoint[k].y+orign_y;  
  100.   
  101.         //二线性插值图像  
  102.         fy = floor(y);  //向下取整  
  103.         fx = floor(x);  
  104.         cy = ceil(y);   //向上取整  
  105.         cx = ceil(x);  
  106.         ty = y - fy;  
  107.         tx = x - fx;  
  108.         w1 = (1 - tx) * (1 - ty);  
  109.         w2 = tx  * (1 - ty);  
  110.         w3 = (1 - tx) * ty ;  
  111.         w4 = tx * ty ;  
  112.         v = pow(dishu,(float)k);  
  113.   
  114.         for (i = 0;i
  115.         {  
  116.             for (j = 0;j
  117.             {  
  118.                 //灰度插值图像像素  
  119.                 N = w1 * (double)(unsigned char)src->imageData[(i+fy)*src->width+j+fx]+  
  120.                     w2 * (double)(unsigned char)src->imageData[(i+fy)*src->width+j+cx]+  
  121.                     w3 * (double)(unsigned char)src->imageData[(i+cy)*src->width+j+fx]+  
  122.                     w4 * (double)(unsigned char)src->imageData[(i+cy)*src->width+j+cx];  
  123.   
  124.                 if( N >= (double)(unsigned char)target->imageData[i*dx+j])  
  125.                 {  
  126.                     result[i*dx+j] = result[i*dx+j] + v * 1;  
  127.                 }else{  
  128.                     result[i*dx+j] = result[i*dx+j] + v * 0;  
  129.                 }  
  130.             }  
  131.         }  
  132.     }  
  133.   
  134.     //将result的值映射为mapping的值  
  135.     for(i = 0; i < dy ;i++)  
  136.     {  
  137.         for (j = 0; j < dx ;j ++)  
  138.         {  
  139.             result[i*dx+j] = Mapping[result[i*dx+j]];  
  140.         }  
  141.     }  
  142.   
  143.     //显示图像  
  144.     int cols = 0;//直方图的横坐标,也是result数组的元素种类  
  145.     int mapping_size = pow(dishu,(float)num_sp);  
  146.     for (i = 0;i < mapping_size; i++ )  
  147.     {  
  148.         if (cols < Mapping[i])  
  149.         {  
  150.             cols = Mapping[i];  
  151.         }  
  152.     }  
  153.   
  154.     if (cols < 255)  
  155.     {  
  156.         //只有采样数小于8,则编码范围0-255,才能显示图像  
  157.         for (i = 0;i
  158.         {  
  159.             for (j = 0;j
  160.             {  
  161.                 target->imageData[i*dx+j] = (unsigned char)result[i*dx+j];  
  162.                 //printf("%d\n",(unsigned char)target->imageData[i*width+j]);  
  163.             }  
  164.         }  
  165.         cvSaveImage("result.jpg",target);  
  166.     }  
  167.   
  168.     //计算直方图  
  169.     hist = cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);//直方图图像  
  170.       
  171.     double *val_hist = (double *)malloc(sizeof(double)*cols);   //直方图数组  
  172.     for (i=0;i
  173.     {  
  174.         val_hist[i]=0.0;  
  175.     }  
  176.     for (i=0; i
  177.     {  
  178.         val_hist[result[i]]++;  
  179.     }  
  180.   
  181.     double temp_max=0.0;  
  182.   
  183.     for (i=0;i//求直方图最大值,为了归一化  
  184.     {  
  185.         //printf("%f\n",val_hist[i]);  
  186.         if (temp_max
  187.         {  
  188.             temp_max=val_hist[i];  
  189.         }  
  190.     }  
  191.     //画直方图  
  192.     CvPoint p1,p2;  
  193.     double bin_width=(double)hist->width/cols;  
  194.     double bin_unith=(double)hist->height/temp_max;  
  195.   
  196.     for (i=0;i
  197.     {  
  198.         p1.x=i*bin_width;p1.y=hist->height;  
  199.         p2.x=(i+1)*bin_width;p2.y=hist->height-val_hist[i]*bin_unith;  
  200.         cvRectangle(hist,p1,p2,cvScalar(0,255),-1,8,0);  
  201.     }  
  202.     cvSaveImage("hist.jpg",hist);  
  203. }  
实验结果:

                

                


4.3 uniform 旋转不变性,给出完整代码:

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #define  PI 3.1415926  
  5. #define MAX(x,y) (x)>(y)?(x):(y)  
  6. #define MIN(x,y) (x)<(y)?(x):(y)  
  7.   
  8. typedef struct MyPoint  
  9. {  
  10.     double x;  
  11.     double y;  
  12. }MyPoint;  
  13. void calc_position(int radius,int num_sp,MyPoint *spoint)  
  14. {  
  15.     double theta;  
  16.   
  17.     theta = 2*PI/num_sp;  
  18.       
  19.     for (int i = 0; i < num_sp; i++)  
  20.     {  
  21.         spoint[i].y = -radius * sin(i * theta);  
  22.         spoint[i].x = radius * cos(i * theta);  
  23.     }  
  24. }  
  25. int calc_sum(int r)  
  26. {  
  27.     int res_sum;  
  28.   
  29.     res_sum = 0;  
  30.     while (r)  
  31.     {  
  32.         res_sum = res_sum + r % 2;  
  33.         r /= 2;  
  34.     }  
  35.     return res_sum;  
  36. }  
  37. void rotation_uniform_invariant_mapping(int range,int num_sp,int *Mapping)  
  38. {  
  39.     int numt,i,j,tem_xor;  
  40.   
  41.     numt = 0;  
  42.     tem_xor = 0;  
  43.     for (i = 0; i< range; i++)  
  44.     {  
  45.         j = i << 1;  
  46.         if (j > range -1)  
  47.         {  
  48.             j = j - (range -1);  
  49.         }  
  50.           
  51.         tem_xor = i ^ j;    // 异或  
  52.         numt = calc_sum(tem_xor);//计算异或结果中1的个数,即跳变个数  
  53.           
  54.         if (numt <= 2)  
  55.         {  
  56.             Mapping[i] = calc_sum(i);  
  57.         }else{  
  58.             Mapping[i] = num_sp+1;  
  59.         }  
  60.     }     
  61.   
  62. }  
  63.   
  64. void rotation_uniform_invariant_lbp(IplImage *src,int height,int width,int num_sp,MyPoint *spoint,int *Mapping)  
  65. {  
  66.     IplImage *target,*hist;  
  67.     int i,j,k,box_x,box_y,orign_x,orign_y,dx,dy,tx,ty,fy,fx,cy,cx,v;  
  68.     double min_x,max_x,min_y,max_y,w1,w2,w3,w4,N,x,y;  
  69.     int *result;  
  70.     float dishu;  
  71.   
  72.     dishu = 2.0;  
  73.     max_x=0;max_y=0;min_x=0;min_y=0;  
  74.     for (k=0;k
  75.     {  
  76.         if (max_x
  77.         {  
  78.             max_x=spoint[k].x;  
  79.         }  
  80.         if (max_y
  81.         {  
  82.             max_y=spoint[k].y;  
  83.         }  
  84.         if (min_x>spoint[k].x)  
  85.         {  
  86.             min_x=spoint[k].x;  
  87.         }  
  88.         if (min_y>spoint[k].y)  
  89.         {  
  90.             min_y=spoint[k].y;  
  91.         }  
  92.     }  
  93.   
  94.     //计算模版大小  
  95.     box_x = ceil(MAX(max_x,0)) - floor(MIN(min_x,0)) + 1;  
  96.     box_y = ceil(MAX(max_y,0)) - floor(MIN(min_y,0)) + 1;  
  97.   
  98.     if (width
  99.     {  
  100.         printf("Too small input image. Should be at least (2*radius+1) x (2*radius+1)");  
  101.         return;  
  102.     }  
  103.   
  104.     //计算可滤波图像大小,opencv图像数组下标从0开始  
  105.     orign_x = 0 - floor(MIN(min_x,0));//起点  
  106.     orign_y = 0 - floor(MIN(min_x,0));  
  107.   
  108.     dx = width - box_x+1;//终点  
  109.     dy = height - box_y+1;  
  110.   
  111.     target = cvCreateImage(cvSize(dx,dy),IPL_DEPTH_8U,1);  
  112.     result = (int *)malloc(sizeof(int)*dx*dy);  
  113.   
  114.     memset(result,0,sizeof(int)*dx*dy);  
  115.     CvRect roi =cvRect(orign_x, orign_y, dx, dy);  
  116.     cvSetImageROI(src, roi);  
  117.     cvCopy(src, target);    
  118.     cvResetImageROI(src);  
  119.     cvSaveImage("haha.jpg",target);  
  120.   
  121.     for ( k = 0; k
  122.     {  
  123.         x = spoint[k].x+orign_x;  
  124.         y = spoint[k].y+orign_y;  
  125.   
  126.         //二线性插值图像  
  127.         fy = floor(y);  //向下取整  
  128.         fx = floor(x);  
  129.         cy = ceil(y);   //向上取整  
  130.         cx = ceil(x);  
  131.         ty = y - fy;  
  132.         tx = x - fx;  
  133.         w1 = (1 - tx) * (1 - ty);  
  134.         w2 = tx  * (1 - ty);  
  135.         w3 = (1 - tx) * ty ;  
  136.         w4 = tx * ty ;  
  137.         v = pow(dishu,(float)k);  
  138.   
  139.         for (i = 0;i
  140.         {  
  141.             for (j = 0;j
  142.             {  
  143.                 //灰度插值图像像素  
  144.                 N = w1 * (double)(unsigned char)src->imageData[(i+fy)*src->width+j+fx]+  
  145.                     w2 * (double)(unsigned char)src->imageData[(i+fy)*src->width+j+cx]+  
  146.                     w3 * (double)(unsigned char)src->imageData[(i+cy)*src->width+j+fx]+  
  147.                     w4 * (double)(unsigned char)src->imageData[(i+cy)*src->width+j+cx];  
  148.   
  149.                 if( N >= (double)(unsigned char)target->imageData[i*dx+j])  
  150.                 {  
  151.                     result[i*dx+j] = result[i*dx+j] + v * 1;  
  152.                 }else{  
  153.                     result[i*dx+j] = result[i*dx+j] + v * 0;  
  154.                 }  
  155.             }  
  156.         }  
  157.     }  
  158.   
  159.     //将result的值映射为mapping的值  
  160.     for(i = 0; i < dy ;i++)  
  161.     {  
  162.         for (j = 0; j < dx ;j ++)  
  163.         {  
  164.             result[i*dx+j] = Mapping[result[i*dx+j]];  
  165.         }  
  166.     }  
  167.   
  168.     //显示图像  
  169.     int cols = 0;//直方图的横坐标,也是result数组的元素种类  
  170.     int mapping_size = pow(dishu,(float)num_sp);  
  171.     for (i = 0;i < mapping_size; i++ )  
  172.     {  
  173.         if (cols < Mapping[i])  
  174.         {  
  175.             cols = Mapping[i];  
  176.         }  
  177.     }  
  178.   
  179.     if (cols < 255)  
  180.     {  
  181.         //只有采样数小于8,则编码范围0-255,才能显示图像  
  182.         for (i = 0;i
  183.         {  
  184.             for (j = 0;j
  185.             {  
  186.                 target->imageData[i*dx+j] = (unsigned char)result[i*dx+j];  
  187.                 //printf("%d\n",(unsigned char)target->imageData[i*width+j]);  
  188.             }  
  189.         }  
  190.         cvSaveImage("result.jpg",target);  
  191.     }  
  192.   
  193.     //计算直方图  
  194.     hist = cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);//直方图图像  
  195.     double *val_hist = (double *)malloc(sizeof(double)*cols);   //直方图数组  
  196.     for (i=0;i
  197.     {  
  198.         val_hist[i]=0.0;  
  199.     }  
  200.     for (i=0; i
  201.     {  
  202.         val_hist[result[i]]++;  
  203.     }  
  204.   
  205.     double temp_max=0.0;  
  206.   
  207.     for (i=0;i//求直方图最大值,为了归一化  
  208.     {  
  209.         //printf("%f\n",val_hist[i]);  
  210.         if (temp_max
  211.         {  
  212.             temp_max=val_hist[i];  
  213.         }  
  214.     }  
  215.     //画直方图  
  216.     CvPoint p1,p2;  
  217.     double bin_width=(double)hist->width/cols;  
  218.     double bin_unith=(double)hist->height/temp_max;  
  219.   
  220.     for (i=0;i
  221.     {  
  222.         p1.x=i*bin_width;p1.y=hist->height;  
  223.         p2.x=(i+1)*bin_width;p2.y=hist->height-val_hist[i]*bin_unith;  
  224.         cvRectangle(hist,p1,p2,cvScalar(0,255),-1,8,0);  
  225.     }  
  226.     cvSaveImage("hist.jpg",hist);  
  227. }  
  228.   
  229. int _tmain(int argc, _TCHAR* argv[])  
  230. {  
  231.     IplImage *src,*grey,*result;  
  232.     int samples,radius,range,*mapping;  
  233.     MyPoint *spoint;  
  234.     float Mi;  
  235.   
  236.     samples = 8;  
  237.     radius = 10;  
  238.     Mi = 2.0;  
  239.     range = pow(Mi,samples);  
  240.   
  241.     src = cvLoadImage("test2.jpg");  
  242.     grey = cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  243.     cvCvtColor(src,grey,CV_BGR2GRAY);  
  244.     mapping = (int *)malloc(sizeof(int)*range);  
  245.     memset(mapping,0,sizeof(int)*range);  
  246.       
  247.     //计算采样点相对坐标  
  248.     spoint = (MyPoint *)malloc(sizeof(MyPoint)*samples);   
  249.     calc_position(radius,samples,spoint);  
  250.       
  251.     //计算灰度不变性LBP特征,写回浮点数图像矩阵中  
  252.     //gray_invariant_lbp(grey,src->height,src->width,samples,spoint);  
  253.   
  254.     //计算旋转不变形LBP特征  
  255.     //rotation_invariant_mapping(range,samples,mapping);  
  256.     //rotation_invariant_lbp(grey,src->height,src->width,samples,spoint,mapping);  
  257.   
  258.     //计算旋转不变等价LBP特征  
  259.     rotation_uniform_invariant_mapping(range,samples,mapping);  
  260.     rotation_uniform_invariant_lbp(grey,src->height,src->width,samples,spoint,mapping);  
  261.     return 0;  
  262. }  
 实验结果:

                 

                

越到后面越黑,因为输出的种类越来越少。


你可能感兴趣的:(机器学习,&,深度学习,特征提取,LBP,纹理)