OpenCV4入门130:LBP特征计算

索引地址:系列索引

计算LBP特征:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 功能:代码 8-12 计算 LBP 特征
// 作者:朱伟 zhu1988wei@163.com
// 来源:《OpenCV图像处理编程实例》
// 博客:http://blog.csdn.net/zhuwei1988
// 更新:2016-8-1
// 说明:版权所有,引用或摘录请联系作者,并按照上面格式注明出处,谢谢。// 8-12 计算 LBP 特征
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/features2d/features2d.hpp>
// 计算原始LBP特征
cv::Mat OLBP(cv::Mat& srcImage)
{
const int nRows = srcImage.rows;
const int nCols = srcImage.cols;
cv::Mat resultMat(srcImage.size(), srcImage.type());
// 遍历图像,生成LBP特征
for (int y = 1; y < nRows - 1; y++)
{
for (int x = 1; x < nCols - 1; x++)
{
// 定义邻域
uchar neighbor[8] = { 0 };
neighbor[0] = srcImage.at<uchar>(y - 1, x - 1);
neighbor[1] = srcImage.at<uchar>(y - 1, x);
neighbor[2] = srcImage.at<uchar>(y - 1, x + 1);
neighbor[3] = srcImage.at<uchar>(y, x + 1);
neighbor[4] = srcImage.at<uchar>(y + 1, x + 1);
neighbor[5] = srcImage.at<uchar>(y + 1, x);
neighbor[6] = srcImage.at<uchar>(y + 1, x - 1);
neighbor[7] = srcImage.at<uchar>(y, x - 1);
// 当前图像的处理中心
uchar center = srcImage.at<uchar>(y, x);
uchar temp = 0;
// 计算LBP的值
for (int k = 0; k < 8; k++)
{
// 遍历中心点邻域
temp += (neighbor[k] >= center)* (1 << k);
}
resultMat.at<uchar>(y, x) = temp;
}
}
return resultMat;
}
int main()
{
cv::Mat srcImage = cv::imread("..\\images\\hand1.jpg", 0);
if (!srcImage.data)
return 0;
cv::Mat resultMat = OLBP(srcImage);
cv::imshow("srcImage", srcImage);
cv::imshow("resultMat", resultMat);
cv::waitKey(0);
return 0;
}

圆形LBP特征:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 功能:代码 8-11 圆形 LBP 特征
// 作者:朱伟 zhu1988wei@163.com
// 来源:《OpenCV图像处理编程实例》
// 博客:http://blog.csdn.net/zhuwei1988
// 更新:2016-8-1
// 说明:版权所有,引用或摘录请联系作者,并按照上面格式注明出处,谢谢。//
template <typename _Tp> static
inline void elbp_(InputArray _src, OutputArray _dst,
int radius, int neighbors) {
// 得到数据矩阵
Mat src = _src.getMat();
// 输出矩阵
_dst.create(src.rows-2*radius,
src.cols-2*radius, CV_32SC1);
Mat dst = _dst.getMat();
// 初始化
dst.setTo(0);
for(int n=0; n<neighbors; n++) {
// 相同点
float x = static_cast<float>(-radius * sin(2.0
*CV_PI*n/static_cast<float>(neighbors)));
float y = static_cast<float>(radius * cos(2.0
*CV_PI*n/static_cast<float>(neighbors)));
// 相关索引
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 i=radius; i < src.rows-radius;i++) {
for(int j=radius;j < src.cols-radius;j++) {
// 插值计算值
float t = static_cast<float>(
w1*src.at<_Tp>(i+fy,j+fx)
+ w2*src.at<_Tp>(i+fy,j+cx) +
w3*src.at<_Tp>(i+cy,j+fx)
+ w4*src.at<_Tp>(i+cy,j+cx));
// 限定浮点精度,生成输出图像
dst.at<int>(i-radius,j-radius) += ((t >
src.at<_Tp>(i,j)) ||
(std::abs(t-src.at<_Tp>(i,j)) <
std::numeric_limits<float>::epsilon())) << n;
}
}
}
}

经典LBP特征计算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 功能:代码 8-10 经典 LBP 特征
// 作者:朱伟 zhu1988wei@163.com
// 来源:《OpenCV图像处理编程实例》
// 博客:http://blog.csdn.net/zhuwei1988
// 更新:2016-8-1
// 说明:版权所有,引用或摘录请联系作者,并按照上面格式注明出处,谢谢。//
template <typename _Tp> static
void olbp_(InputArray _src, OutputArray _dst)
{
// 得到矩阵信息
Mat src = _src.getMat();
// 输出结果矩阵
_dst.create(src.rows-2, src.cols-2, CV_8UC1);
Mat dst = _dst.getMat();
// 初始化矩阵
dst.setTo(0);
// 遍历计算局部特征
for(int i=1;i<src.rows-1;i++) {
for(int j=1;j<src.cols-1;j++) {
// 获取当前图像处理的中心点
_Tp center = src.at<_Tp>(i,j);
unsigned char code = 0;
// 比较图像编码形成
code |= (src.at<_Tp>(i-1,j-1) >= center) << 7;
code |= (src.at<_Tp>(i-1,j) >= center) << 6;
code |= (src.at<_Tp>(i-1,j+1) >= center) << 5;
code |= (src.at<_Tp>(i,j+1) >= center) << 4;
code |= (src.at<_Tp>(i+1,j+1) >= center) << 3;
code |= (src.at<_Tp>(i+1,j) >= center) << 2;
code |= (src.at<_Tp>(i+1,j-1) >= center) << 1;
code |= (src.at<_Tp>(i,j-1) >= center) << 0;
dst.at<unsigned char>(i-1,j-1) = code;
}
}