图像特征之LBP(OpenCV)

来源:互联网 发布:js获取服务上下文 编辑:程序博客网 时间:2024/06/06 05:32

LBP(Local binary pattern)是一个易理解且有效的局部图像特征,应用很广泛。在网上可以搜到一大把的LBP介绍,所以本博文就忽略了对其的介绍。直接附上代码,代码不难,只是希望对大家有用!如有错误和补充,欢迎提出,大家共同进步哈!

注意:下面代码仅为示例便利,牺牲了一些效率!

一)一般的LBP,256维

//====================================================================  // 作者   : quarryman  // 邮箱   : quarrying{at}qq.com  // 主页   : http://blog.csdn.net/quarryman  // 日期   : 2013年08月11日  // 描述   : 实现一般的LBP  //====================================================================  #include <cv.h>#include <highgui.h>void LBP(IplImage* src, IplImage* dst){int width=src->width;int height=src->height;for(int j=1;j<width-1;j++){for(int i=1;i<height-1;i++){uchar neighborhood[8]={0};neighborhood[7]= CV_IMAGE_ELEM( src, uchar, i-1, j-1);neighborhood[6]= CV_IMAGE_ELEM( src, uchar, i-1, j);neighborhood[5]= CV_IMAGE_ELEM( src, uchar, i-1, j+1);neighborhood[4]= CV_IMAGE_ELEM( src, uchar, i, j-1);neighborhood[3]= CV_IMAGE_ELEM( src, uchar, i, j+1);neighborhood[2]= CV_IMAGE_ELEM( src, uchar, i+1, j-1);neighborhood[1]= CV_IMAGE_ELEM( src, uchar, i+1, j);neighborhood[0]= CV_IMAGE_ELEM( src, uchar, i+1, j+1);uchar center = CV_IMAGE_ELEM( src, uchar, i, j);uchar temp=0;for(int k=0;k<8;k++){temp+=(neighborhood[k]>=center)<<k;}CV_IMAGE_ELEM( dst, uchar, i, j)=temp;}}}int main(){IplImage* img=cvLoadImage("lena.jpg", 0);IplImage* dst=cvCreateImage(cvGetSize(img),8,1);LBP(img,dst);cvNamedWindow("图像", 1);cvShowImage("图像", dst);cvWaitKey(0);cvDestroyAllWindows();cvReleaseImage(&img);cvReleaseImage(&dst);return 0;}
结果图像为:


二)Uniform Pattern的LBP,将256维降为59维。
绝大多数LBP模式最多只包含两次从1到0或从0到1的跳变。因此,Ojala将Uniform Pattern定义为:当某个LBP所对应的循环二进制数从0到1或从1到0最多有两次跳变时,该LBP所对应的二进制就称为一个等价模式类。

代码一:

#include <stdio.h>typedef unsigned char uchar;int getHopCount(uchar i){int a[8]={0};int k=7;int cnt=0;while(i){a[k]=i&1;i>>=1;--k;}for(int k=0;k<8;++k){if(a[k]!=a[k+1==8?0:k+1]){++cnt;}}return cnt;}int main()  {int cnt[9]={0};for(int i=0;i<256;++i){cnt[getHopCount(i)]++;}for(int i=0;i<9;++i){printf("跳变%d次的数目:%d\n",i,cnt[i]);}return 0; }

输出结果为:
跳变0次的数目:2
跳变1次的数目:0
跳变2次的数目:56
跳变3次的数目:0
跳变4次的数目:140
跳变5次的数目:0
跳变6次的数目:56
跳变7次的数目:0
跳变8次的数目:2
可见:56+2+1==59,所以有59维。

代码二:

//====================================================================  // 作者   : quarryman  // 邮箱   : quarrying{at}qq.com  // 主页   : http://blog.csdn.net/quarryman  // 日期   : 2013年08月11日  // 描述   : Uniform Pattern的LBP  //==================================================================== #include <cv.h>#include <highgui.h>int getHopCount(uchar i){int a[8]={0};int k=7;int cnt=0;while(i){a[k]=i&1;i>>=1;--k;}for(int k=0;k<8;++k){if(a[k]!=a[k+1==8?0:k+1]){++cnt;}}return cnt;}void lbp59table(uchar* table){memset(table,0,256);uchar temp=1;for(int i=0;i<256;++i){if(getHopCount(i)<=2){table[i]=temp;temp++;}// printf("%d\n",table[i]);}}void LBP(IplImage* src, IplImage* dst){int width=src->width;int height=src->height;uchar table[256];lbp59table(table);for(int j=1;j<width-1;j++){for(int i=1;i<height-1;i++){uchar neighborhood[8]={0};neighborhood[7]= CV_IMAGE_ELEM( src, uchar, i-1, j-1);neighborhood[6]= CV_IMAGE_ELEM( src, uchar, i-1, j);neighborhood[5]= CV_IMAGE_ELEM( src, uchar, i-1, j+1);neighborhood[4]= CV_IMAGE_ELEM( src, uchar, i, j+1);neighborhood[3]= CV_IMAGE_ELEM( src, uchar, i+1, j+1);neighborhood[2]= CV_IMAGE_ELEM( src, uchar, i+1, j);neighborhood[1]= CV_IMAGE_ELEM( src, uchar, i+1, j-1);neighborhood[0]= CV_IMAGE_ELEM( src, uchar, i, j-1);uchar center = CV_IMAGE_ELEM( src, uchar, i, j);uchar temp=0;for(int k=0;k<8;k++){temp+=(neighborhood[k]>=center)<<k;}//CV_IMAGE_ELEM( dst, uchar, i, j)=temp;CV_IMAGE_ELEM( dst, uchar, i, j)=table[temp];}}}int main(){IplImage* img=cvLoadImage("lena.jpg", 0);IplImage* dst=cvCreateImage(cvGetSize(img),8,1);LBP(img,dst);cvNamedWindow("图像", 1);cvShowImage("图像", dst);cvWaitKey(0);cvDestroyAllWindows();cvReleaseImage(&img);cvReleaseImage(&dst);return 0;}
输出图像为: