天天看點

LBP的c++實作

LBP的計算結果如下:

(1) 将檢測視窗切分為區塊(cells,例如,每個區塊 16x16 像素)。

(2) 對區塊中的每個像素,與它的八個鄰域像素進行比較(左上、左中、左

下、右上等)。可以按照順時針或者逆時針的順序進行比較。

(3) 對于中心像素大于某個鄰域的,設定為 1;否則,設定為 0。這就獲得

了一個 8 位的二進制數(通常情況下會轉換為十進制數字),作為該位置的特征,計算公式如下:

LBP的c++實作

其中 xi為中心像素,xj為所選鄰域像素,|Si| 為所選像素個數。

(4) 對每一個區塊計算直方圖。此時,可以選擇将直方圖歸一化。串聯所有

區塊的直方圖,這就得到了目前檢測視窗的特征向量。

(5) 最後特征向量可以通過諸如支援向量機等機器學習算法來産生一個分類

器。

本文需要用到opencv2.4中的庫函數:

将一幅圖像分塊的代碼如下:

vector<Mat> Mycv::partion(Mat& image)

{

vector<Mat> result;

int n=image.rows/16;

int m=image.cols/16;

for(int i=0;i<n;i++)

{

for(int j=0;j<m;j++)

{

result.push_back(image(Range(i*16,i*16+16),Range(j*16,j*16+16)));

}

}

return result;

}

向量result即包括了分塊後的所有圖像。

對于8鄰域的LBP,共有256種模式,為了簡化計算,我們采用LBP的等價模式,将其降59種模式,可以用如下數組實作:

int  table[256]={    

    1,   2,   3,   4,   5,   0,   6,   7,   8,   0,   0,   0,   9,   0,  10,  11,

12,   0,   0,   0,   0,   0,   0,   0,  13,   0,   0,   0,  14,   0,  15,  16,

17,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

18,   0,   0,   0,   0,   0,   0,   0,  19,   0,   0,   0,  20,   0,  21,  22,

23,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

24,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

25,   0,   0,   0,   0,   0,   0,   0,  26,   0,   0,   0,  27,   0,  28,  29,

30,  31,   0,  32,   0,   0,   0,  33,   0,   0,   0,   0,   0,   0,   0,  34,

0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  35,

0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  36,

37,  38,   0,  39,   0,   0,   0,  40,   0,   0,   0,   0,   0,   0,   0,  41,

0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  42,

43,  44,   0,  45,   0,   0,   0,  46,   0,   0,   0,   0,   0,   0,   0,  47,

48,  49,   0,  50,   0,   0,   0,  51,  52,  53,   0,  54,  55,  56,  57,  58

};

求直方圖的代碼如下:

void Mycv::lbphis(Mat& image)

{

int his[1024][59]={0};

// int* his[59];

 vector<Mat> result;

 int m=partion(image).size();

 for(int i=0;i<m;i++)

 {

   result.push_back(partion(image)[i]);

 }

 for (int k=0;k<m;k++)

 {

for (int j= 1; j<result[k].rows-1; j++) 

{ // for all rows (except first and last)

const uchar* previous= result[k].ptr<const uchar>(j-1); // previous row

const uchar* current= result[k].ptr<const uchar>(j); // current row

const uchar* next= result[k].ptr<const uchar>(j+1); // next row

for (int i=1; i<result[k].cols-1; i++) 

{

uchar neighborhood[8]={0}; 

neighborhood[7]=previous[i-1];

neighborhood[6]=previous[i];

neighborhood[5]=previous[i+1];

neighborhood[4]=current[i-1];

neighborhood[3]=current[i+1];

neighborhood[2]=next[i-1];

neighborhood[1]=next[i];

neighborhood[0]=next[i+1];

uchar center=current[i];

uchar temp=0;  

for(int n=0;n<8;n++)  

{  

temp+=(neighborhood[n]>=center)<<n;  

}  

his[k][table[temp]]++;

}

}

 }

 FILE      *stream; 

 if((stream=fopen("D:/mylbp.txt", "w+t ")) != NULL) 

 { 

for (int a=0;a<1024;a++)

{

for(int b=0;b<59;b++)

{

  fprintf(stream, "his[%d][%d]= %d\n ", a,b,his[a][b]); 

}

}

fclose(stream); 

 }

}

最後是在main函數中實作運作:

int main()

{

Mycv mycv;

Mat image=imread("E:/Mypic/1.png",0);

mycv.lbphis(image);

         return 0;

}

最終各塊圖像的LBP直方圖存到了D盤的mylbp.txt檔案下。這裡我采用的是512*512的圖檔,分塊後有1024個圖像,這裡我定義了his[1024][59]數組來統計每幅圖像的LBP模式值,這個方法很不好,希望大家指教改進。

繼續閱讀