C/C++ opencv 计算 LBP特征 包括旋转不变 uniform 圆形邻域

 话不多说直接上代码,没有做直方图的统计,没有做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");


}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值