日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LBP特征原理及代码实现

發(fā)布時間:2023/12/31 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LBP特征原理及代码实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、LBP特征的背景介紹

LBP指局部二值模式,英文全稱:Local Binary Pattern,是一種用來描述圖像局部特征的算子,LBP特征具有灰度不變性和旋轉(zhuǎn)不變性等顯著優(yōu)點。它是由T. Ojala, M.Pietik?inen, 和 D. Harwood [1][2]在1994年提出,由于LBP特征計算簡單、效果較好,因此LBP特征在計算機(jī)視覺的許多領(lǐng)域都得到了廣泛的應(yīng)用,LBP特征比較出名的應(yīng)用是用在人臉識別和目標(biāo)檢測中,在計算機(jī)視覺開源庫Opencv中有使用LBP特征進(jìn)行人臉識別的接口,也有用LBP特征訓(xùn)練目標(biāo)檢測分類器的方法,Opencv實現(xiàn)了LBP特征的計算,但沒有提供一個單獨的計算LBP特征的接口。

二、LBP特征的原理

1、原始LBP特征描述及計算方法

原始的LBP算子定義在像素3*3的鄰域內(nèi),以鄰域中心像素為閾值,相鄰的8個像素的灰度值與鄰域中心的像素值進(jìn)行比較,若周圍像素大于中心像素值,則該像素點的位置被標(biāo)記為1,否則為0。這樣,3*3鄰域內(nèi)的8個點經(jīng)過比較可產(chǎn)生8位二進(jìn)制數(shù),將這8位二進(jìn)制數(shù)依次排列形成一個二進(jìn)制數(shù)字,這個二進(jìn)制數(shù)字就是中心像素的LBP值,LBP值共有28種可能,因此LBP值有256種。中心像素的LBP值反映了該像素周圍區(qū)域的紋理信息。?
備注:計算LBP特征的圖像必須是灰度圖,如果是彩色圖,需要先轉(zhuǎn)換成灰度圖。?
上述過程用圖像表示為:?
?
?
將上述過程用公式表示為:?

(xc,yc)為中心像素的坐標(biāo),p為鄰域的第p個像素,ip為鄰域像素的灰度值,ic為中心像素的灰度值,s(x)為符號函數(shù)

原始LBP特征計算代碼(Opencv下):

//原始LBP特征計算 template <typename _tp> void getOriginLBPFeature(InputArray _src,OutputArray _dst) {Mat src = _src.getMat();_dst.create(src.rows-2,src.cols-2,CV_8UC1);Mat dst = _dst.getMat();dst.setTo(0);for(int i=1;i<src.rows-1;i++){for(int j=1;j<src.cols-1;j++){_tp center = src.at<_tp>(i,j);unsigned char lbpCode = 0;lbpCode |= (src.at<_tp>(i-1,j-1) > center) << 7;lbpCode |= (src.at<_tp>(i-1,j ) > center) << 6;lbpCode |= (src.at<_tp>(i-1,j+1) > center) << 5;lbpCode |= (src.at<_tp>(i ,j+1) > center) << 4;lbpCode |= (src.at<_tp>(i+1,j+1) > center) << 3;lbpCode |= (src.at<_tp>(i+1,j ) > center) << 2;lbpCode |= (src.at<_tp>(i+1,j-1) > center) << 1;lbpCode |= (src.at<_tp>(i ,j-1) > center) << 0;dst.at<uchar>(i-1,j-1) = lbpCode;}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

測試結(jié)果:?

2、LBP特征的改進(jìn)版本

在原始的LBP特征提出以后,研究人員對LBP特征進(jìn)行了很多的改進(jìn),因此產(chǎn)生了許多LBP的改進(jìn)版本。

2.1 圓形LBP特征(Circular LBP or Extended LBP)

? ? ? ?由于原始LBP特征使用的是固定鄰域內(nèi)的灰度值,因此當(dāng)圖像的尺度發(fā)生變化時,LBP特征的編碼將會發(fā)生錯誤,LBP特征將不能正確的反映像素點周圍的紋理信息,因此研究人員對其進(jìn)行了改進(jìn)[3]。基本的 LBP 算子的最大缺陷在于它只覆蓋了一個固定半徑范圍內(nèi)的小區(qū)域,這顯然不能滿足不同尺寸和頻率紋理的需要。為了適應(yīng)不同尺度的紋理特征,并達(dá)到灰度和旋轉(zhuǎn)不變性的要求,Ojala 等對 LBP 算子進(jìn)行了改進(jìn),將 3×3 鄰域擴(kuò)展到任意鄰域,并用圓形鄰域代替了正方形鄰域,改進(jìn)后的 LBP 算子允許在半徑為 R 的圓形鄰域內(nèi)有任意多個像素點。從而得到了諸如半徑為R的圓形區(qū)域內(nèi)含有P個采樣點的LBP算子:?
?
這種LBP特征叫做Extended LBP,也叫Circular LBP。使用可變半徑的圓對近鄰像素進(jìn)行編碼,可以得到如下的近鄰:?
?
對于給定中心點(xc,yc),其鄰域像素位置為(xp,yp)pP,其采樣點(xp,yp)用如下公式計算:

?
R是采樣半徑,p是第p個采樣點,P是采樣數(shù)目。由于計算的值可能不是整數(shù),即計算出來的點不在圖像上,我們使用計算出來的點的插值點。目的的插值方法有很多,Opencv使用的是雙線性插值,雙線性插值的公式如下:?
?
通過LBP特征的定義可以看出,LBP特征對光照變化是魯棒的,其效果如下圖所示:?

//圓形LBP特征計算,這種方法適于理解,但在效率上存在問題,聲明時默認(rèn)neighbors=8 template <typename _tp> void getCircularLBPFeature(InputArray _src,OutputArray _dst,int radius,int neighbors) {Mat src = _src.getMat();//LBP特征圖像的行數(shù)和列數(shù)的計算要準(zhǔn)確_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);Mat dst = _dst.getMat();dst.setTo(0);//循環(huán)處理每個像素for(int i=radius;i<src.rows-radius;i++){for(int j=radius;j<src.cols-radius;j++){//獲得中心像素點的灰度值_tp center = src.at<_tp>(i,j);unsigned char lbpCode = 0;for(int k=0;k<neighbors;k++){//根據(jù)公式計算第k個采樣點的坐標(biāo),這個地方可以優(yōu)化,不必每次都進(jìn)行計算radius*cos,radius*sinfloat x = i + static_cast<float>(radius * \cos(2.0 * CV_PI * k / neighbors));float y = j - static_cast<float>(radius * \sin(2.0 * CV_PI * k / neighbors));//根據(jù)取整結(jié)果進(jìn)行雙線性插值,得到第k個采樣點的灰度值//1.分別對x,y進(jìn)行上下取整int x1 = static_cast<int>(floor(x));int x2 = static_cast<int>(ceil(x));int y1 = static_cast<int>(floor(y));int y2 = static_cast<int>(ceil(y));//2.計算四個點(x1,y1),(x1,y2),(x2,y1),(x2,y2)的權(quán)重//下面的權(quán)重計算方式有個問題,如果四個點都相等,則權(quán)重全為0,計算出來的插值為0//float w1 = (x2-x)*(y2-y); //(x1,y1)//float w2 = (x2-x)*(y-y1); //(x1,y2)//float w3 = (x-x1)*(y2-y); //(x2,y1)//float w4 = (x-x1)*(y-y1); //(x2,y2)//將坐標(biāo)映射到0-1之間float tx = x - x1;float ty = y - y1;//根據(jù)0-1之間的x,y的權(quán)重計算公式計算權(quán)重float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) * ty;float w4 = tx * ty;//3.根據(jù)雙線性插值公式計算第k個采樣點的灰度值float neighbor = src.at<_tp>(x1,y1) * w1 + src.at<_tp>(x1,y2) *w2 \+ src.at<_tp>(x2,y1) * w3 +src.at<_tp>(x2,y2) *w4;//通過比較獲得LBP值,并按順序排列起來lbpCode |= (neighbor>center) <<(neighbors-k-1);}dst.at<uchar>(i-radius,j-radius) = lbpCode;}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
//圓形LBP特征計算,效率優(yōu)化版本,聲明時默認(rèn)neighbors=8 template <typename _tp> void getCircularLBPFeatureOptimization(InputArray _src,OutputArray _dst,int radius,int neighbors) {Mat src = _src.getMat();//LBP特征圖像的行數(shù)和列數(shù)的計算要準(zhǔn)確_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);Mat dst = _dst.getMat();dst.setTo(0);for(int k=0;k<neighbors;k++){//計算采樣點對于中心點坐標(biāo)的偏移量rx,ryfloat rx = static_cast<float>(radius * cos(2.0 * CV_PI * k / neighbors));float ry = -static_cast<float>(radius * sin(2.0 * CV_PI * k / neighbors));//為雙線性插值做準(zhǔn)備//對采樣點偏移量分別進(jìn)行上下取整int x1 = static_cast<int>(floor(rx));int x2 = static_cast<int>(ceil(rx));int y1 = static_cast<int>(floor(ry));int y2 = static_cast<int>(ceil(ry));//將坐標(biāo)偏移量映射到0-1之間float tx = rx - x1;float ty = ry - y1;//根據(jù)0-1之間的x,y的權(quán)重計算公式計算權(quán)重,權(quán)重與坐標(biāo)具體位置無關(guān),與坐標(biāo)間的差值有關(guān)float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) * ty;float w4 = tx * ty;//循環(huán)處理每個像素for(int i=radius;i<src.rows-radius;i++){for(int j=radius;j<src.cols-radius;j++){//獲得中心像素點的灰度值_tp center = src.at<_tp>(i,j);//根據(jù)雙線性插值公式計算第k個采樣點的灰度值float neighbor = src.at<_tp>(i+x1,j+y1) * w1 + src.at<_tp>(i+x1,j+y2) *w2 \+ src.at<_tp>(i+x2,j+y1) * w3 +src.at<_tp>(i+x2,j+y2) *w4;//LBP特征圖像的每個鄰居的LBP值累加,累加通過與操作完成,對應(yīng)的LBP值通過移位取得dst.at<uchar>(i-radius,j-radius) |= (neighbor>center) <<(neighbors-k-1);}}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

測試結(jié)果:?
radius = 3,neighbors = 8?
?
第三幅圖像為radius = 3,neighbors = 8,第四幅圖像為radius = 1,neighbors = 8,從實驗結(jié)果可以看出,半徑越小,圖像紋理越精細(xì)?

第三幅圖像為radius = 3,neighbors = 8,第四幅圖像為radius = 3,neighbors = 4,從實驗結(jié)果可以看出,鄰域數(shù)目越小,圖像亮度越低,合理,因此4位的灰度值很小?
由于我代碼的問題,不能使neighbors >8,可改進(jìn)?

2.2 旋轉(zhuǎn)不變LBP特征

? ? ? ?從上面可以看出,上面的LBP特征具有灰度不變性,但還不具備旋轉(zhuǎn)不變性,因此研究人員又在上面的基礎(chǔ)上進(jìn)行了擴(kuò)展,提出了具有旋轉(zhuǎn)不變性的LBP特征。?
首先不斷的旋轉(zhuǎn)圓形鄰域內(nèi)的LBP特征,根據(jù)選擇得到一系列的LBP特征值,從這些LBP特征值選擇LBP特征值最小的作為中心像素點的LBP特征。具體做法如下圖所示:?
?
如圖,通過對得到的LBP特征進(jìn)行旋轉(zhuǎn),得到一系列的LBP特征值,最終將特征值最小的一個特征模式作為中心像素點的LBP特征。

//旋轉(zhuǎn)不變圓形LBP特征計算,聲明時默認(rèn)neighbors=8 template <typename _tp> void getRotationInvariantLBPFeature(InputArray _src,OutputArray _dst,int radius,int neighbors) {Mat src = _src.getMat();//LBP特征圖像的行數(shù)和列數(shù)的計算要準(zhǔn)確_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);Mat dst = _dst.getMat();dst.setTo(0);for(int k=0;k<neighbors;k++){//計算采樣點對于中心點坐標(biāo)的偏移量rx,ryfloat rx = static_cast<float>(radius * cos(2.0 * CV_PI * k / neighbors));float ry = -static_cast<float>(radius * sin(2.0 * CV_PI * k / neighbors));//為雙線性插值做準(zhǔn)備//對采樣點偏移量分別進(jìn)行上下取整int x1 = static_cast<int>(floor(rx));int x2 = static_cast<int>(ceil(rx));int y1 = static_cast<int>(floor(ry));int y2 = static_cast<int>(ceil(ry));//將坐標(biāo)偏移量映射到0-1之間float tx = rx - x1;float ty = ry - y1;//根據(jù)0-1之間的x,y的權(quán)重計算公式計算權(quán)重,權(quán)重與坐標(biāo)具體位置無關(guān),與坐標(biāo)間的差值有關(guān)float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) * ty;float w4 = tx * ty;//循環(huán)處理每個像素for(int i=radius;i<src.rows-radius;i++){for(int j=radius;j<src.cols-radius;j++){//獲得中心像素點的灰度值_tp center = src.at<_tp>(i,j);//根據(jù)雙線性插值公式計算第k個采樣點的灰度值float neighbor = src.at<_tp>(i+x1,j+y1) * w1 + src.at<_tp>(i+x1,j+y2) *w2 \+ src.at<_tp>(i+x2,j+y1) * w3 +src.at<_tp>(i+x2,j+y2) *w4;//LBP特征圖像的每個鄰居的LBP值累加,累加通過與操作完成,對應(yīng)的LBP值通過移位取得dst.at<uchar>(i-radius,j-radius) |= (neighbor>center) <<(neighbors-k-1);}}}//進(jìn)行旋轉(zhuǎn)不變處理for(int i=0;i<dst.rows;i++){for(int j=0;j<dst.cols;j++){unsigned char currentValue = dst.at<uchar>(i,j);unsigned char minValue = currentValue;for(int k=1;k<neighbors;k++){//循環(huán)左移unsigned char temp = (currentValue>>(neighbors-k)) | (currentValue<<k);if(temp < minValue){minValue = temp;}}dst.at<uchar>(i,j) = minValue;}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

測試結(jié)果:?
radius = 3,neighbors = 8,最后一幅是旋轉(zhuǎn)不變LBP特征?

2.3 Uniform Pattern LBP特征

? ? ? ?Uniform Pattern,也被稱為等價模式或均勻模式,由于一個LBP特征有多種不同的二進(jìn)制形式,對于半徑為R的圓形區(qū)域內(nèi)含有P個采樣點的LBP算子將會產(chǎn)生2P種模式。很顯然,隨著鄰域集內(nèi)采樣點數(shù)的增加,二進(jìn)制模式的種類是以指數(shù)形式增加的。例如:5×5鄰域內(nèi)20個采樣點,有220=1,048,576種二進(jìn)制模式。這么多的二進(jìn)制模式不利于紋理的提取、分類、識別及存取。例如,將LBP算子用于紋理分類或人臉識別時,常采用LBP模式的統(tǒng)計直方圖來表達(dá)圖像的信息,而較多的模式種類將使得數(shù)據(jù)量過大,且直方圖過于稀疏。因此,需要對原始的LBP模式進(jìn)行降維,使得數(shù)據(jù)量減少的情況下能最好的表示圖像的信息。?
????為了解決二進(jìn)制模式過多的問題,提高統(tǒng)計性,Ojala提出了采用一種“等價模式”(Uniform Pattern)來對LBP算子的模式種類進(jìn)行降維。Ojala等認(rèn)為,在實際圖像中,絕大多數(shù)LBP模式最多只包含兩次從1到0或從0到1的跳變。因此,Ojala將“等價模式”定義為:當(dāng)某個LBP所對應(yīng)的循環(huán)二進(jìn)制數(shù)從0到1或從1到0最多有兩次跳變時,該LBP所對應(yīng)的二進(jìn)制就稱為一個等價模式類。如00000000(0次跳變),00000111(只含一次從0到1的跳變),10001111(先由1跳到0,再由0跳到1,共兩次跳變)都是等價模式類。除等價模式類以外的模式都?xì)w為另一類,稱為混合模式類,例如10010111(共四次跳變)。通過這樣的改進(jìn),二進(jìn)制模式的種類大大減少,而不會丟失任何信息。模式數(shù)量由原來的2P種減少為 P ( P-1)+2種,其中P表示鄰域集內(nèi)的采樣點數(shù)。對于3×3鄰域內(nèi)8個采樣點來說,二進(jìn)制模式由原始的256種減少為58種,即:它把值分為59類,58個uniform pattern為一類,其它的所有值為第59類。這樣直方圖從原來的256維變成59維。這使得特征向量的維數(shù)更少,并且可以減少高頻噪聲帶來的影響。?
????具體實現(xiàn):采樣點數(shù)目為8個,即LBP特征值有28種,共256個值,正好對應(yīng)灰度圖像的0-255,因此原始的LBP特征圖像是一幅正常的灰度圖像,而等價模式LBP特征,根據(jù)0-1跳變次數(shù),將這256個LBP特征值分為了59類,從跳變次數(shù)上劃分:跳變0次—2個,跳變1次—0個,跳變2次—56個,跳變3次—0個,跳變4次—140個,跳變5次—0個,跳變6次—56個,跳變7次—0個,跳變8次—2個。共9種跳變情況,將這256個值進(jìn)行分配,跳變小于2次的為等價模式類,共58個,他們對應(yīng)的值按照從小到大分別編碼為1—58,即它們在LBP特征圖像中的灰度值為1—58,而除了等價模式類之外的混合模式類被編碼為0,即它們在LBP特征中的灰度值為0,因此等價模式LBP特征圖像整體偏暗。

//等價模式LBP特征計算 template <typename _tp> void getUniformPatternLBPFeature(InputArray _src,OutputArray _dst,int radius,int neighbors) {Mat src = _src.getMat();//LBP特征圖像的行數(shù)和列數(shù)的計算要準(zhǔn)確_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);Mat dst = _dst.getMat();dst.setTo(0);//LBP特征值對應(yīng)圖像灰度編碼表,直接默認(rèn)采樣點為8位uchar temp = 1;uchar table[256] = {0};for(int i=0;i<256;i++){if(getHopTimes(i)<3){table[i] = temp;temp++;}}//是否進(jìn)行UniformPattern編碼的標(biāo)志bool flag = false;//計算LBP特征圖for(int k=0;k<neighbors;k++){if(k==neighbors-1){flag = true;}//計算采樣點對于中心點坐標(biāo)的偏移量rx,ryfloat rx = static_cast<float>(radius * cos(2.0 * CV_PI * k / neighbors));float ry = -static_cast<float>(radius * sin(2.0 * CV_PI * k / neighbors));//為雙線性插值做準(zhǔn)備//對采樣點偏移量分別進(jìn)行上下取整int x1 = static_cast<int>(floor(rx));int x2 = static_cast<int>(ceil(rx));int y1 = static_cast<int>(floor(ry));int y2 = static_cast<int>(ceil(ry));//將坐標(biāo)偏移量映射到0-1之間float tx = rx - x1;float ty = ry - y1;//根據(jù)0-1之間的x,y的權(quán)重計算公式計算權(quán)重,權(quán)重與坐標(biāo)具體位置無關(guān),與坐標(biāo)間的差值有關(guān)float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) * ty;float w4 = tx * ty;//循環(huán)處理每個像素for(int i=radius;i<src.rows-radius;i++){for(int j=radius;j<src.cols-radius;j++){//獲得中心像素點的灰度值_tp center = src.at<_tp>(i,j);//根據(jù)雙線性插值公式計算第k個采樣點的灰度值float neighbor = src.at<_tp>(i+x1,j+y1) * w1 + src.at<_tp>(i+x1,j+y2) *w2 \+ src.at<_tp>(i+x2,j+y1) * w3 +src.at<_tp>(i+x2,j+y2) *w4;//LBP特征圖像的每個鄰居的LBP值累加,累加通過與操作完成,對應(yīng)的LBP值通過移位取得dst.at<uchar>(i-radius,j-radius) |= (neighbor>center) <<(neighbors-k-1);//進(jìn)行LBP特征的UniformPattern編碼if(flag){dst.at<uchar>(i-radius,j-radius) = table[dst.at<uchar>(i-radius,j-radius)];}}}} } //計算跳變次數(shù) int getHopTimes(int n) {int count = 0;bitset<8> binaryCode = n;for(int i=0;i<8;i++){if(binaryCode[i] != binaryCode[(i+1)%8]){count++;}}return count; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

測試結(jié)果:?
radius = 3,neighbors = 8,最后一幅是等價模式LBP特征?

2.4 MB-LBP特征

MB-LBP特征,全稱為Multiscale Block LBP,來源于論文[9],中科院的人發(fā)明的,在Traincascade級聯(lián)目標(biāo)訓(xùn)練檢測中的LBP特征使用的就是MB-LBP。?
MB-LBP的原理:?
?
將圖像分成一個個小塊(Block),每個小塊再分為一個個的小區(qū)域(類似于HOG中的cell),小區(qū)域內(nèi)的灰度平均值作為當(dāng)前小區(qū)域的灰度值,與周圍小區(qū)域灰度進(jìn)行比較形成LBP特征,生成的特征稱為MB-LBP,Block大小為3*3,則小區(qū)域的大小為1,就是原始的LBP特征,上圖的Block大小為9*9,小區(qū)域的大小為3*3。?
不同Block提取的MB-LBP特征如圖所示:?
?
計算MB-LBP代碼:

//MB-LBP特征的計算 void getMultiScaleBlockLBPFeature(InputArray _src,OutputArray _dst,int scale) {Mat src = _src.getMat();Mat dst = _dst.getMat();//定義并計算積分圖像int cellSize = scale / 3;int offset = cellSize / 2;Mat cellImage(src.rows-2*offset,src.cols-2*offset,CV_8UC1);for(int i=offset;i<src.rows-offset;i++){for(int j=offset;j<src.cols-offset;j++){int temp = 0;for(int m=-offset;m<offset+1;m++){for(int n=-offset;n<offset+1;n++){temp += src.at<uchar>(i+n,j+m);}}temp /= (cellSize*cellSize);cellImage.at<uchar>(i-cellSize/2,j-cellSize/2) = uchar(temp); }}getOriginLBPFeature<uchar>(cellImage,dst); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

效果圖:?
Block=3,即原始的LBP特征?
?
Block=9?
?
Block=15?
?
????到此為止,還沒有結(jié)束,作者對得到LBP特征又進(jìn)行了均值模式編碼,通過對得到的特征圖求直方圖,得到了LBP特征值0-255之間(0-255即直方圖中的bin)的特征數(shù)量,通過對bin中的數(shù)值進(jìn)行排序,通過權(quán)衡,將排序在前63位的特征值看作是等價模式類,其他的為混合模式類,總共64類,作者在論文中稱之為SEMB-LBP(Statistically Effective MB-LBP )。類似于等價模式LBP,等價模式的LBP的等價模式類為58種,混合模式類1種,共59種。二者除了等價模式類的數(shù)量不同之外,主要區(qū)別在于:對等價模式類的定義不同,等價模式LBP是根據(jù)0-1的跳變次數(shù)定義的,而SEMB-LBP是通過對直方圖排序得到的。當(dāng)然下一步要做的就是將SEMB-LBP變?yōu)長BPH進(jìn)行使用。?
計算SEMB-LBP的代碼

//求SEMB-LBP void SEMB_LBPFeature(InputArray _src,OutputArray _dst,int scale) {Mat dst=_dst.getMat();Mat MB_LBPImage;getMultiScaleBlockLBPFeature(_src,MB_LBPImage,scale);//imshow("dst",dst);Mat histMat;int histSize = 256;float range[] = {float(0),float(255)};const float* ranges = {range};//計算LBP特征值0-255的直方圖calcHist(&MB_LBPImage,1,0,Mat(),histMat,1,&histSize,&ranges,true,false);histMat.reshape(1,1);vector<float> histVector(histMat.rows*histMat.cols);uchar table[256];memset(table,64,256);if(histMat.isContinuous()){//histVector = (int *)(histMat.data);//將直方圖histMat變?yōu)関ector向量histVectorhistVector.assign((float*)histMat.datastart,(float*)histMat.dataend);vector<float> histVectorCopy(histVector);//對histVector進(jìn)行排序,即對LBP特征值的數(shù)量進(jìn)行排序,降序排列sort(histVector.begin(),histVector.end(),greater<float>());for(int i=0;i<63;i++){for(int j=0;j<histVectorCopy.size();j++){if(histVectorCopy[j]==histVector[i]){//得到類似于Uniform的編碼表table[j]=i;}}}}dst = MB_LBPImage;//根據(jù)編碼表得到SEMB-LBPfor(int i=0;i<dst.rows;i++){for(int j=0;j<dst.cols;j++){dst.at<uchar>(i,j) = table[dst.at<uchar>(i,j)];}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

測試結(jié)果:?
第二幅為對MB-LBP進(jìn)行編碼得到的SEMB-LBP圖像?
?
總結(jié):MB-LBP有點類似于先將圖像進(jìn)行平滑處理,然后再求LBP特征。而SEMB-LBP是在MB-LBP進(jìn)行編碼后的圖像。類似于等價模式LBP,先求LBP特征,再用等價模式進(jìn)行編碼。當(dāng)Scale=3時,MB-LBP和SEMB-LBP就是LBP和等價模式LBP。想具體了解需要去看論文,當(dāng)然要自己實現(xiàn)才會理解的更透徹。

三、LBPH——圖像的LBP特征向量

????LBPH,Local Binary Patterns Histograms,即LBP特征的統(tǒng)計直方圖,LBPH將LBP特征與圖像的空間信息結(jié)合在一起。這種表示方法由Ahonen等人在論文[3]中提出,他們將LBP特征圖像分成m個局部塊,并提取每個局部塊的直方圖,然后將這些直方圖依次連接在一起形成LBP特征的統(tǒng)計直方圖,即LBPH。?
一幅圖像具體的計算LBPH的過程(以O(shè)pencv中的人臉識別為例):?
1. 計算圖像的LBP特征圖像,在上面已經(jīng)講過了。?
2. 將LBP特征圖像進(jìn)行分塊,Opencv中默認(rèn)將LBP特征圖像分成8行8列64塊區(qū)域?
3. 計算每塊區(qū)域特征圖像的直方圖cell_LBPH,將直方圖進(jìn)行歸一化,直方圖大小為1*numPatterns?
4. 將上面計算的每塊區(qū)域特征圖像的直方圖按分塊的空間順序依次排列成一行,形成LBP特征向量,大小為1*(numPatterns*64)?
5. 用機(jī)器學(xué)習(xí)的方法對LBP特征向量進(jìn)行訓(xùn)練,用來檢測和識別目標(biāo)?
舉例說明LBPH的維度:?
采樣點為8個,如果用的是原始的LBP或Extended LBP特征,其LBP特征值的模式為256種,則一幅圖像的LBP特征向量維度為:64*256=16384維,?
而如果使用的UniformPatternLBP特征,其LBP值的模式為59種,其特征向量維度為:64*59=3776維,可以看出,使用等價模式特征,其特征向量的維度大大減少,?
這意味著使用機(jī)器學(xué)習(xí)方法進(jìn)行學(xué)習(xí)的時間將大大減少,而性能上沒有受到很大影響。?
Opencv的人臉識別使用的是Extended LBP

計算LBPH的代碼如下:

//計算LBP特征圖像的直方圖LBPH Mat getLBPH(InputArray _src,int numPatterns,int grid_x,int grid_y,bool normed) {Mat src = _src.getMat();int width = src.cols / grid_x;int height = src.rows / grid_y;//定義LBPH的行和列,grid_x*grid_y表示將圖像分割成這么些塊,numPatterns表示LBP值的模式種類Mat result = Mat::zeros(grid_x * grid_y,numPatterns,CV_32FC1);if(src.empty()){return result.reshape(1,1);}int resultRowIndex = 0;//對圖像進(jìn)行分割,分割成grid_x*grid_y塊,grid_x,grid_y默認(rèn)為8for(int i=0;i<grid_x;i++){for(int j=0;j<grid_y;j++){//圖像分塊Mat src_cell = Mat(src,Range(i*height,(i+1)*height),Range(j*width,(j+1)*width));//計算直方圖Mat hist_cell = getLocalRegionLBPH(src_cell,0,(numPattern-1),true);//將直方圖放到result中Mat rowResult = result.row(resultRowIndex);hist_cell.reshape(1,1).convertTo(rowResult,CV_32FC1);resultRowIndex++;}}return result.reshape(1,1); } //計算一個LBP特征圖像塊的直方圖 Mat getLocalRegionLBPH(const Mat& src,int minValue,int maxValue,bool normed) {//定義存儲直方圖的矩陣Mat result;//計算得到直方圖bin的數(shù)目,直方圖數(shù)組的大小int histSize = maxValue - minValue + 1;//定義直方圖每一維的bin的變化范圍float range[] = { static_cast<float>(minValue),static_cast<float>(maxValue + 1) };//定義直方圖所有bin的變化范圍const float* ranges = { range };//計算直方圖,src是要計算直方圖的圖像,1是要計算直方圖的圖像數(shù)目,0是計算直方圖所用的圖像的通道序號,從0索引//Mat()是要用的掩模,result為輸出的直方圖,1為輸出的直方圖的維度,histSize直方圖在每一維的變化范圍//ranges,所有直方圖的變化范圍(起點和終點)calcHist(&src,1,0,Mat(),result,1,&histSize,&ranges,true,false);//歸一化if(normed){result /= (int)src.total();}//結(jié)果表示成只有1行的矩陣return result.reshape(1,1); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

總結(jié):上面的LBP特征都是較經(jīng)典的LBP特征,除此之外,LBP特征還有大量的變種,如TLBP(中心像素與周圍所有像素比較,而不是根據(jù)采樣點的數(shù)目),DLBP(編碼標(biāo)準(zhǔn)四個方向的灰度變化,每個方向上用2比特編碼),MLBP(將中心像素值替換成采樣點像素的平均值),MB-LBP(上面有介紹),VLBP(沒太看懂),RGB-LBP(RGB圖像分別計算LBP,然后連接在一起)等,具體的需要自己去研究,可參考維基百科

四、LBP特征的匹配與使用

1、LBP特征用在目標(biāo)檢測中

人臉檢測比較出名的是Haar+Adaboost方法,其實目前的Opencv也支持LBP+Adaboost和HOG+Adaboost方法進(jìn)行目標(biāo)檢測,從目前我的使用效果來看,LBP+Adaboost方法用在目標(biāo)檢測中的效果比Haar特征、HOG特征都要好(HOG特征用的不多,主要是Haar和LBP),而且LBP特征的訓(xùn)練速度比Haar和HOG都要快很多。在LBP+Adaboost中,LBP特征主要是用作輸入的訓(xùn)練數(shù)據(jù)(特征),使用的LBP特征應(yīng)該是DLBP(維基百科上說的,待考證,沒太看明白Cascade中LBP特征的計算方式),具體用法需要看源碼。Opencv的TrainCascade中使用的LBP特征是MB-LBP。?
老外的對Opencv級聯(lián)檢測中使用的LBP的解釋(非常好,自己讀,就不翻譯了),在看這個之前最好是運行過TrainCascade來訓(xùn)練目標(biāo)檢測的分類器,并使用過LBP特征訓(xùn)練,調(diào)節(jié)過參數(shù)[8]:

OpenCV ships with a tool called traincascade that trains LBP, Haar and HOG. Specifically for face detection they even ship the 3000-image dataset of 24x24 pixel faces, in the format needed bytraincascade.In my experience, of the three types traincascade supports, LBP takes the least time to train, taking on the order of hours rather than days for Haar.A quick overview of its training process is that for the given number of stages (a decent choice is 20), it attempts to find features that reject as many non-faces as possible while not rejecting the faces. The balance between rejecting non-faces and keeping faces is controlled by the mininum hit rate (OpenCV chose 99.5%) and false alarm rate (OpenCV chose 50%). The specific meta-algorithm used for crafting OpenCV's own LBP cascade is Gentle AdaBoost (GAB).The variant of LBP implemented in OpenCV is described here:Shengcai Liao, Xiangxin Zhu, Zhen Lei, Lun Zhang and Stan Z. Li. Learning Multi-scale Block Local Binary Patterns for Face Recognition. International Conference on Biometrics (ICB), 2007, pp. 828-837.What it amounts to in practice in OpenCV with default parameters is:OpenCV LBP Cascade Runtime OverviewThe detector examines 24x24 windows within the image looking for a face. Stepping from Stage 1 to 20 of the cascade classifier, if it can show that the current 24x24 window is likely not a face, it rejects it and moves over the window by one or two pixels over to the next position; Otherwise it proceeds to the next stage.During each stage, 3-10 or so LBP features are examined. Every LBP feature has an offset within the window and a size, and the area it covers is fully contained within the current window. Evaluating an LBP feature at a given position can result in either a pass or fail. Depending on whether an LBP feature succeeds or fails, a positive or negative weight particular to that feature is added to an accumulator.Once all of a stage's LBP features are evaluated, the accumulator's value is compared to the stage threshold. A stage fails if the accumulator is below the threshold, and passes if it is above. Again, if a stage fails, the cascade is exited and the window moves to the next position.LBP feature evaluation is relatively simple. At that feature's offset within the window, nine rectangles are laid out in a 3x3 configuration. These nine rectangles are all the same size for a particular LBP feature, ranging from 1x1 to 8x8.The sum of all the pixels in the nine rectangles are computed, in other words their integral. Then, the central rectangle's integral is compared to that of its eight neighbours. The result of these eight comparisons is eight bits (1 or 0), which are assembled in an 8-bit LBP.This 8-bit bitvector is used as an index into a 2^8 == 256-bit LUT, computed by the training process and particular to each LBP feature, that determines whether the LBP feature passed or failed.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

2、 LBP用在人臉識別中

LBP在人臉識別中比較出名,從源碼上來看,人臉識別中LBPH的使用主要是用來進(jìn)行直方圖的比較,通過直方圖的比較來判斷目標(biāo)的類別。在Opencv的基于LBP的人臉識別的實現(xiàn)中使用的LBP特征是Extendes LBP,即圓形LBP特征。參考的論文為文獻(xiàn)[10]。?
LBPH訓(xùn)練主要是提取輸入的圖像的LBPH保存,當(dāng)進(jìn)行識別時,遍歷保存的LBPH,找到輸入圖像與訓(xùn)練圖像方差最小的LBPH,將其對應(yīng)的類別作為識別的類別輸出。?
用LBPH進(jìn)行訓(xùn)練和識別的代碼。

#include<iostream> #include<opencv2\core\core.hpp> #include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> #include<opencv2\contrib\contrib.hpp>using namespace std; using namespace cv;int main(int argc,char* argv[]) {vector<Mat> images;vector<int> labels;char buff[10];for(int i=1;i<8;i++){sprintf(buff,"0%d.tif",i);Mat image = imread(buff);Mat grayImage;cvtColor(image,grayImage,COLOR_BGR2GRAY);images.push_back(grayImage);labels.push_back(1);}for(int i=8;i<12;i++){sprintf(buff,"0%d.tif",i);Mat image = imread(buff);Mat grayImage;cvtColor(image,grayImage,COLOR_BGR2GRAY);images.push_back(grayImage);labels.push_back(2);}Ptr<FaceRecognizer> p = createLBPHFaceRecognizer();p->train(images,labels);Mat test= imread("12.tif");Mat grayImage;cvtColor(test,grayImage,COLOR_BGR2GRAY);int result = p->predict(grayImage);cout<<result<<endl;system("pause");return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

測試結(jié)果:?

參考資料

[1] T. Ojala, M. Pietik?inen, and D. Harwood (1994), “Performance evaluation of texture measures with classification based on Kullback discrimination of distributions”, Proceedings of the 12th IAPR International Conference on Pattern Recognition (ICPR 1994), vol. 1, pp. 582 - 585.?
[2] T. Ojala, M. Pietik?inen, and D. Harwood (1996), “A Comparative Study of Texture Measures with Classification Based on Feature Distributions”, Pattern Recognition, vol. 29, pp. 51-59.?
[3] Ahonen, T., Hadid, A., and Pietikainen, M. Face Recognition with Local Binary Patterns. Computer Vision- ECCV 2004 (2004), 469–481.?
[4]?http://blog.csdn.net/xidianzhimeng/article/details/19634573?
[5] opencv參考手冊,Opencv源碼?
[6]?http://blog.csdn.net/zouxy09/article/details/7929531?
[7]?http://blog.csdn.net/songzitea/article/details/17686135?
[8]?http://stackoverflow.com/questions/20085833/face-detection-algorithms-with-minimal-training-time/20086402#20086402?
[9] Shengcai Liao, Xiangxin Zhu, Zhen Lei, Lun Zhang and Stan Z. Li. Learning Multi-scale Block Local Binary Patterns for Face Recognition. International Conference on Biometrics (ICB), 2007, pp. 828-837.?
[10] Ahonen T, Hadid A. and Pietik?inen M. “Face description with local binary patterns: Application to face recognition.” IEEE Transactions on Pattern Analysis and Machine Intelligence, 28(12):2037-2041.

總結(jié)

以上是生活随笔為你收集整理的LBP特征原理及代码实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。