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;
}
輸出圖像為: