什么是LBP?它是一种用来描述图像局部纹理特征的算子,英文叫做“Local Binary Pattern”,局部二值模式。
它具有旋转不变性,灰度不变性和光照强度不变性等优点。特别是光照强度不变性这一点,如果一张图片在光照很强的画面里特征物体根本无法识别,LBP就能很好的检测到物体。这一点我觉得很实用。
部分原理的话其实参考这篇文章就好,很详细,也很能懂。
参考文章:https://blog.csdn.net/heli200482128/article/details/79204008
我主要是以代码应用为主:
下面放上代码:
#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("D:/test/girl.png");
if (!src.data)
{
cout << "图片未找到" << endl;
return -1;
}
imshow("input title", src);
cvtColor(src, gray_src, CV_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", CV_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);
}
}
运行结果: