OpenCV——LBP特征
LBP ( Local binary pattern) ,局部二進制模式.
LBP特征的描述
原始的LBP算子定義為在3 ? 3 的窗口內,以窗口中心像素為閾值,將相鄰的8個像素的灰度值與其進行比較,若周圍像素值大于等于中心像素值,則該點的位置被標記為1,否則為0。這樣3 ? 3鄰域內的8個點經比較可產生8位二進制數(通常轉換為十進制數即LBP碼,共256種),即得到該窗口中心像素點的LBP值,并用這個值來反映該區域的紋理信息。需要注意的是,LBP值是按照順時針方向組成的二進制數。
?上面的 C? 是對比度(contrast).? weights 就是閾值表示成十進制顯示出來的。
LBP特征的圓形化改進
? ? ? ?基本的 LBP算子的最大缺陷在于它只覆蓋了一個固定半徑范圍內的小區域,這顯然不能滿足不同尺寸和頻率紋理的需要。為了適應不同尺度的紋理特征,并達到灰度和旋轉不變性的要求,Ojala等對 LBP 算子進行了改進,將 3×3鄰域擴展到任意鄰域,并用圓形鄰域代替了正方形鄰域,改進后的 LBP 算子允許在半徑為 R 的圓形鄰域內有任意多個像素點。從而得到了諸如半徑為R的圓形區域內含有P個采樣點的LBP算子,稱為Extended LBP,也叫Circular LBP.
?
LBP旋轉不變模式
下圖中的8種 LBP 模式,對應的旋轉不變的 LBP模式都是00001111,即 LBP值為 15:
????????最為完整的LBP模式是 均勻+旋轉不變模式,均勻模式就是限制一個二進制序列從0到1或從1到0的跳變次數不超過2次.
?
LBP特征用于檢測的原理
???????上述提取的LBP算子在每個像素點都可以得到一個LBP“編碼”,那么,對一幅圖像(記錄的是每個像素點的灰度值)提取其原始的LBP算子之后,得到的原始LBP特征依然是“一幅圖片”(記錄的是每個像素點的LBP值)。
LBP的應用中,如紋理分類、人臉分析等,一般都不將LBP圖譜作為特征向量用于分類識別,而是采用LBP特征譜的統計直方圖作為特征向量用于分類識別。
代碼實現
#include<opencv2/opencv.hpp> #include<iostream> #include<math.h> using namespace cv; using namespace std; int current_radius = 3; int max_count = 20; void Expand_LBP_demo(int, void*); Mat src, gray_src; int main(int argc, char** argv) {src = imread("rui.jpg");if (!src.data){cout << "圖片未找到" << endl;return -1;}namedWindow("input title", WINDOW_AUTOSIZE);imshow("input title", src);cvtColor(src, gray_src, COLOR_BGR2GRAY);int width = src.cols - 2;int hight = src.rows - 2;//基本LBP演示Mat lbpImg = Mat::zeros(hight, width, CV_8UC1);for (int row = 1; row < src.rows - 1; row++){for (int col = 1; col < src.cols - 1; col++){uchar c = gray_src.at<uchar>(row, col);uchar code = 0;code |= (gray_src.at<uchar>(row - 1, col - 1) > c) << 7;code |= (gray_src.at<uchar>(row - 1, col) > c) << 6;code |= (gray_src.at<uchar>(row - 1, col + 1) > c) << 5;code |= (gray_src.at<uchar>(row, col + 1) > c) << 4;code |= (gray_src.at<uchar>(row + 1, col + 1) > c) << 3;code |= (gray_src.at<uchar>(row + 1, col) > c) << 2;code |= (gray_src.at<uchar>(row + 1, col - 1) > c) << 1;code |= (gray_src.at<uchar>(row, col) > c) << 0;lbpImg.at<uchar>(row - 1, col - 1) = code;}}imshow("LBP", lbpImg);namedWindow("Expand LBP", WINDOW_AUTOSIZE);createTrackbar("current_radius", "Expand LBP", ¤t_radius, max_count, Expand_LBP_demo);Expand_LBP_demo(0, 0);waitKey(0);return 0; } //擴展LBP demo void Expand_LBP_demo(int, void*) {int offset = current_radius * 2;Mat elbpImg = Mat::zeros(gray_src.rows - offset, gray_src.cols - offset, CV_8UC1);int numNeighbor = 8;for (int n = 0; n < numNeighbor; n++){float x = current_radius * cos((2 * CV_PI * n) / numNeighbor);float y = current_radius * (-sin((2 * CV_PI * n) / numNeighbor));int fx = static_cast<int>(floor(x)); //向下取整,它返回的是小于或等于函數參數,并且與之最接近的整數int fy = static_cast<int>(floor(y));int cx = static_cast<int>(ceil(x)); //向上取整,它返回的是大于或等于函數參數,并且與之最接近的整數int cy = static_cast<int>(ceil(y));float ty = y - fy;float tx = x = fx;float w1 = (1 - tx) * (1 - ty);float w2 = (tx) * (1 - ty);float w3 = (1 - tx) * (ty);float w4 = (tx) * (ty);for (int row = current_radius; row < (gray_src.rows - current_radius); row++){for (int col = current_radius; col < (gray_src.cols - current_radius); col++){float t = w1 * gray_src.at<uchar>(row + fy, col + fx) + w2 * gray_src.at<uchar>(row + fy, col + cx) +w3 * gray_src.at<uchar>(row + cy, col + fx) + w4 * gray_src.at<uchar>(row + cy, col + cx);elbpImg.at<uchar>(row - current_radius, col - current_radius) +=((t > gray_src.at<uchar>(row, col)) && (abs(t - gray_src.at<uchar>(row, col)) > std::numeric_limits<float>::epsilon())) << n;}}imshow("Expand LBP", elbpImg);} }?
?
?
總結
以上是生活随笔為你收集整理的OpenCV——LBP特征的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汽车CAN总线关闭故障的诊断与恢复
- 下一篇: 盘点程序员必备的免费资源网站