opencv_C++ LBP( Local Binary Patterns, 局部模式特征) 特征示例

理解LBP之前要先了解:
LBP的原理:https://blog.****.net/xidianzhimeng/article/details/19634573
双线性插值:https://blog.****.net/lxlclzy1130/article/details/50922867

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

#define WINDOW_NAME "ELBP"

Mat g_srcImage, g_grayImage;
int g_nRadius = 3, g_nMaxRadius = 30;

void normalLBP()
{
	g_srcImage = imread("chepai.jpg");
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
	int width = g_grayImage.cols;
	int height = g_grayImage.rows;

	// 基本LBP
	Mat lbpImage = Mat::zeros(height - 2, width - 2, CV_8UC1);
	uchar center;
	for (size_t row = 1; row < height - 1; row++)
	{
		for (size_t col = 1; col < width - 1; col++)
		{
			center = g_grayImage.at<uchar>(row, col);
			uchar code = 0;

			code |= (g_grayImage.at<uchar>(row - 1, col - 1) > center) << 7;
			code |= (g_grayImage.at<uchar>(row - 1, col) > center) << 6;
			code |= (g_grayImage.at<uchar>(row - 1, col + 1) > center) << 5;
			code |= (g_grayImage.at<uchar>(row, col + 1) > center) << 4;
			code |= (g_grayImage.at<uchar>(row + 1, col + 1) > center) << 3;
			code |= (g_grayImage.at<uchar>(row + 1, col) > center) << 2;
			code |= (g_grayImage.at<uchar>(row + 1, col - 1) > center) << 1;
			code |= (g_grayImage.at<uchar>(row, col - 1) > center) << 0;

			lbpImage.at<uchar>(row - 1, col - 1) = code;
		}
	}
	imshow("basic LBP", lbpImage);
}

void on_fOnChange_ELBP(int, void*)
{
	int offset = g_nRadius * 2;
	Mat elbpImage = Mat::zeros(g_grayImage.rows - offset, g_grayImage.cols - offset, CV_8UC1);
	int width = g_grayImage.cols;
	int height = g_grayImage.rows;
	int numNeighbors = 8;

	for (size_t n = 0; n < numNeighbors; n++)
	{
		float x = static_cast<float>(g_nRadius) * cos(2.0 * CV_PI * n / static_cast<float>(numNeighbors));
		float y = static_cast<float>(g_nRadius) * -sin(2.0 * CV_PI * n / static_cast<float>(numNeighbors));

		int fx = static_cast<int>(floor(x));
		int fy = static_cast<int>(floor(x));
		int cx = static_cast<int>(ceil(x));
		int cy = static_cast<int>(ceil(x));

		// U V 
		float tx = x - fx;
		float ty = y - fy;

		// 权重
		float w1 = (1 - tx) * (1-ty);
		float w2 = tx * (1-ty);
		float w3 = (1 - tx) * ty;
		float w4 = tx * ty;

		for (size_t row = g_nRadius; row < height - g_nRadius; row++)
		{
			for (size_t col = g_nRadius; col < width - g_nRadius; col++)
			{
				float t = w1 * g_grayImage.at<uchar>(row + fy, col + fx) + w2 * g_grayImage.at<uchar>(row + fy, col + cx)\
					+ w3 * g_grayImage.at<uchar>(row + cy, col + fx) + w4 * g_grayImage.at<uchar>(row + cy, col + cx);

				// 可以错误矫正,不加也没多大影响(abs(t - gray_src.at<uchar>(row, col)) > std::numeric_limits<float>::epsilon())) 
				elbpImage.at<uchar>(row - g_nRadius, col - g_nRadius) += ( (t > g_grayImage.at<uchar>(row, col)) \
					&& (abs(t - g_grayImage.at<uchar>(row, col)) > std::numeric_limits<float>::epsilon()) )  << n;
			}
		}
	}
	imshow(WINDOW_NAME, elbpImage);
}

int main()
{
	normalLBP();

	// ELBP
	namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
	createTrackbar("ELBP radius: ", WINDOW_NAME, &g_nRadius, g_nMaxRadius, on_fOnChange_ELBP);
	on_fOnChange_ELBP(0, NULL);

	waitKey(0);
	return 0;
}

运行结果:
opencv_C++ LBP( Local Binary Patterns, 局部模式特征) 特征示例
opencv_C++ LBP( Local Binary Patterns, 局部模式特征) 特征示例