LBP
LBP原理参见其他博主博客,旋转不变性是通过寻找八位数的最小值实现的
窗口如下
(v-1,w-1)| (v-1,w) | (v-1,w+1)
(v,w-1) | (v,w) | (v,w+1)
(v+1,w-1)| (v+1,w) | (v+1,w+1)
直接上代码
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
using namespace std;
using namespace cv;
//求最小的的特征值
int smallest(int a[])
{
int temp = 256;
int down_num;
for (int j = 0; j < 8; j++)
{
int Lbp = 0,ii=0;
for (int k = j; k < 8+j; k++,ii++)
{
down_num = k % 8;
//for(int ii=0;ii<8;ii++)
Lbp = a[down_num]*pow(2, ii) + Lbp;
}
if (temp > Lbp)
temp = Lbp;
}
return temp;
}
//旋转不变圆形LBP,考虑到我只考虑了八个采样点的情况,这时圆形与3*3效果相当,此处用的是3*3的窗口
void rotation_invariant_LBP(Mat image,Mat output)
{
//边缘置0
for (int v = 0; v < output.rows; v++)
{
output.at<uchar>(v, 0) = 0;
output.at<uchar>(v, output.cols - 1) = 0;
}
for (int w = 0; w < output.cols; w++)
{
output.at<uchar>(0, w) = 0;
output.at<uchar>(output.rows - 1, w) = 0;
}
//进行窗口扫描
for (int w = 1; w < output.cols - 1; w++)
{
for (int v = 1; v < output.rows - 1; v++)
{
int a[8] = { 1,1,1,1,1,1,1,1 };
if (image.at<uchar>(v, w) > image.at<uchar>(v - 1, w - 1))
a[0] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v - 1, w))
a[1] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v - 1, w + 1))
a[2] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v , w + 1))
a[3] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v + 1, w + 1))
a[4] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v + 1, w))
a[5] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v + 1, w - 1))
a[6] = 0;
if (image.at<uchar>(v, w) > image.at<uchar>(v, w - 1))
a[7] = 0;
output.at<uchar>(v,w)=smallest(a);
}
}
}
//跳变次数获取
int getHopCount(uchar i)
{
int a[8] = { 0 };
int k = 7;
int cnt = 0;
while (i)
{
a[k] = i & 1;
i >>= 1;
--k;
}
for (int k = 0; k < 8; ++k)
{
if (a[k] != a[k + 1 == 8 ? 0 : k + 1])
{
++cnt;
}
}
return cnt;
}
//59个等价模式
void lbp59table(uchar* table)
{
memset(table, 0, 256);
uchar temp = 1;
for (int i = 0; i < 256; ++i)
{
if (getHopCount(i) <= 2)
{
table[i] = temp;
temp++;
}
// printf("%d\n",table[i]);
}
}
void LBP_dengjia(Mat src, Mat dst)
{
int width = src.rows;
int height = src.cols;
uchar table[256];
lbp59table(table);
for (int j = 1; j < width - 1; j++)
{
for (int i = 1; i < height - 1; i++)
{
uchar neighborhood[8] = { 0 };
neighborhood[7] = src.at<uchar>(j, i - 1);
neighborhood[6] = src.at<uchar>(j + 1, i - 1);
neighborhood[5] = src.at<uchar>(j + 1, i);
neighborhood[4] = src.at<uchar>(j + 1, i + 1);
neighborhood[2] = src.at<uchar>(j - 1, i + 1);
neighborhood[1] = src.at<uchar>(j - 1, i);
neighborhood[0] = src.at<uchar>(j - 1, i - 1);
uchar center = src.at<uchar>(j, i);
uchar temp = 0;
for (int k = 0; k < 8; k++)
{
temp += (neighborhood[k] >= center) << k;
}
dst.at<uchar>(j, i) = table[temp];
}
}
}
void main()
{
Mat input = imread("D:a2.jpeg");
Mat output1,output2;
cvtColor(input, input,COLOR_RGB2GRAY);
output1 = input.clone();
output2 = input.clone();
rotation_invariant_LBP(input, output1);
LBP_dengjia(input, output2);
namedWindow("1", 0);
namedWindow("2", 0);
namedWindow("3", 0);
imshow("1", input);
imshow("2", output1);
imshow("3", output2);
waitKey(0);
}
结果如下
原灰度图如下
旋转不变的结果
等价模式
等价模式与旋转不变的结果图不同的原因:比较准则不同,一个是大于则置1,一个是大于则置0,反映的内容是一样的