1. 程式人生 > >OpenCv-C++-LBP特徵檢測

OpenCv-C++-LBP特徵檢測

什麼是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", &current_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);
	}


}

執行結果:
在這裡插入圖片描述

在這裡插入圖片描述