天天看點

圖像特征之LBP(OpenCV)

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;
}
           

結果圖像為:

圖像特征之LBP(OpenCV)

二)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;
}
           

輸出圖像為:

圖像特征之LBP(OpenCV)