话不多说直接上代码,没有做直方图的统计,没有做cell的归一化,请自行完成。
#include <iostream>
#include <opencv.hpp>
#define pi 3.1415926
using namespace std;
using namespace cv;
int binary2decimal(char descri[], int p)
{
//char a[8] = { 1,1,0,0,0,0,0,0};
//cout << binary2decimal(a, 8) << endl;
// -> 3
int sum = 0, factorial = 1;
for (int i = 0; i < p; i++)
{
sum += factorial * descri[i];
factorial = factorial * 2;
}
return sum;
}
void show(Mat img, string name = "1")
{
Mat temp;
img.convertTo(temp, CV_8U);
imshow(name, temp);
waitKey();
}
int LBPRotate(char descri[], int p)
{
char *temp = new char[p];
int min = binary2decimal(descri, p);
for (int epo = 0; epo < p; epo++)
{
for (int i = 0; i < p; i++)
{
temp[i] = descri[(i + epo) % p];
}
if (binary2decimal(temp, p) < min)
min = binary2decimal(temp, p);
}
return min;
}
void uniformpattern(char descri[], int p)
{
char pre = descri[0];
char change = 0;
for (int i = 1; i < p; i++)
{
if (descri[i] != pre)
{
change++;
}
}
if (change > 2)
{
for (int i = 1; i < p; i++)
{
descri[i] = 0;
}
}
}
char* LBPCircle(Mat src, int x, int y, int P, float R)
{
char* descriptor = new char[P];
int height = src.rows;
int width = src.cols;
float angle, px, py;
for (int i = 0; i < P; i++)
{
angle = pi / 2 - 2 * pi / P * i;
px = (float)x + R * cos(angle);
py = (float)y - R * sin(angle);
if (px <= 0 || py <= 0 ||
px >= width - 1 || py >= height - 1)
{
for (int m = 0; m < P; m++)
{
descriptor[m] = 0;
}
return descriptor;
}
else
{
int xl = int(px);
int xr = xl + 1;
int yl = int(py);
int yr = yl + 1;
float wxl = 1 - (px - xl);
float wxr = 1 - (xr - px);
float wyl = 1 - (py - yl);
float wyr = 1 - (yr - py);
float pixel = src.at<float>(yl, xl) * (wxl + wyl) +
src.at<float>(yr, xl) * (wxl + wyr) +
src.at<float>(yl, xr) * (wxr + wyl) +
src.at<float>(yr, xr) * (wxr + wyr);
pixel /= 4.0;
if (pixel > src.at<float>(y, x))
descriptor[i] = 1;
else
descriptor[i] = 0;
}
}
return descriptor;
}
char* LBPBase(Mat src, int x, int y)
{
char* descriptor = new char[8];
float center, pixel;
int width = src.cols;
int height = src.rows;
char dxdy[8][2] = { -1,-1, 0,-1, 1,-1,
1,0, 1,1, 0,1, -1,1, -1,0 };
if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
{
for (int m = 0; m < 8; m++)
{
descriptor[m] = 0;
}
return descriptor;
}
center = src.at<float>(y, x);
for (int m = 0; m < 8; m++)
{
pixel = src.at<float>(y + dxdy[m][1], x + dxdy[m][0]);
if (pixel > center)
descriptor[m] = 1;
else
descriptor[m] = 0;
}
return descriptor;
}
void LBP(InputArray src, OutputArray dst, bool rotate = true,
bool uniform = true, bool base = true, int P = 8, float R = 1)
{
Mat input = src.getMat();
dst.create(input.size(), CV_8UC1);
Mat output = dst.getMat();
int width = input.cols;
int height = input.rows;
//颜色空间归一化
input.convertTo(input, CV_32F);
Mat gray = Mat::zeros(input.size(), CV_32FC1);
float r, g, b;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
r = input.at<Vec3f>(i, j)[2];
g = input.at<Vec3f>(i, j)[1];
b = input.at<Vec3f>(i, j)[0];
gray.at<float>(i, j) = 0.3 * r + 0.59 * g + 0.11 * b;
}
}
int value;
char* desc;
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
if (base)
desc = LBPBase(gray, j, i);
else
desc = LBPCircle(gray, j, i, P, R);
if (uniform)
uniformpattern(desc, P);
if (rotate)
value = LBPRotate(desc, P);
else
value = binary2decimal(desc, P);
output.at<uchar>(i, j) = value;
}
}
}
int main()
{
Mat src = imread("F:\\users\\桌面\\123.jpg");
resize(src, src, Size(512, 512));
Mat dst;
show(src);
LBP(src, dst, false, false, true);
show(dst, "origin");
LBP(src, dst, false, false, false);
show(dst, "Circle");
}