本章我们学习LBP图像的原理和使用,因为接下来教程我们要使用LBP图像的直方图来进行脸部识别。

参考资料:

http://docs.opencv.org/modules/contrib/doc/facerec/facerec_tutorial.html

http://www.cnblogs.com/mikewolf2002/p/3438166.html

      LBP的基本思想是以图像中某个像素为中心,对相邻像素进行阈值比较。如果中心像素的亮度大于等于它的相邻像素,把相邻像素标记为1,否则标记为0。我们可以用二进制数字来表示LBP图中的每个像素的LBP编码,比如下图中的中心像素,它的LBP编码为:00010011,其十进制值为19。

用公式表示就是:

其中(xc,yc)是中心像素,ic是灰度值,in是相邻像素的灰度值,s是一个符号函数:

在OpenCV的LBP算法中,使用圆形的LBP算子:

 

对于一个点, 它的近邻点 用以下公式计算:

其中R是半径,p是样本点的个数。

如果就算的结果不在像素坐标上,我们则使用双线性插值进行近似处理。

下面的代码中,我们分别实现了通常LBP图和圆形算子LBP图。

      elbp是圆形算子LBP函数,elbp1是通常LBP图,我们分别对lena的图像进行了处理,结果如下所示,从途中可以看出来,使用圆形算子的效果锐度更强。

#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp" #include <iostream>
#include <fstream>
#include <sstream> using namespace cv;
using namespace std; void elbp(Mat& src, Mat &dst, int radius, int neighbors)
{ 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<uchar>(i+fy,j+fx) + w2*src.at<uchar>(i+fy,j+cx) + w3*src.at<uchar>(i+cy,j+fx) + w4*src.at<uchar>(i+cy,j+cx));
// 进行编码
dst.at<uchar>(i-radius,j-radius) += ((t > src.at<uchar>(i,j)) || (std::abs(t-src.at<uchar>(i,j)) < std::numeric_limits<float>::epsilon())) << n;
}
}
}
} void elbp1(Mat& src, Mat &dst)
{ // 循环处理图像数据
for(int i=1; i < src.rows-1;i++)
{
for(int j=1;j < src.cols-1;j++)
{
uchar tt = 0;
int tt1 = 0;
uchar u = src.at<uchar>(i,j);
if(src.at<uchar>(i-1,j-1)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i-1,j)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i-1,j+1)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i,j+1)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i+1,j+1)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i+1,j)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i+1,j-1)>u) { tt += 1 <<tt1; }
tt1++;
if(src.at<uchar>(i-1,j)>u) { tt += 1 <<tt1; }
tt1++; dst.at<uchar>(i-1,j-1) = tt;
}
}
} int main()
{
Mat img = cv::imread("../lenna.jpg", 0);
namedWindow("image");
imshow("image", img); int radius, neighbors;
radius = 1;
neighbors = 8; //创建一个LBP
//注意为了溢出,我们行列都在原有图像上减去2个半径
Mat dst = Mat(img.rows-2*radius, img.cols-2*radius,CV_8UC1, Scalar(0));
elbp1(img,dst);
namedWindow("normal");
imshow("normal", dst); Mat dst1 = Mat(img.rows-2*radius, img.cols-2*radius,CV_8UC1, Scalar(0));
elbp(img,dst1,1,8);
namedWindow("circle");
imshow("circle", dst1); while(1)
cv::waitKey(0);
}

我们换另外一张图,该图包括不同光照下的四副照片,再来看看LBP图的效果:

 

 

程序代码:

FirstOpenCV36

OpenCV学习(39) OpenCV中的LBP图像的更多相关文章

  1. OpenCV学习(22) opencv中使用kmeans算法

    kmeans算法的原理参考:http://www.cnblogs.com/mikewolf2002/p/3368118.html 下面学习一下opencv中kmeans函数的使用.      首先我们 ...

  2. OpenCV学习笔记:resize函数改变图像的大小

    OpenCV提供了resize函数来改变图像的大小,函数原型如下: , , int interpolation=INTER_LINEAR ); 参数解释: src:输入,原图像,即待改变大小的图像: ...

  3. OpenCV学习笔记——OpenCV安装

    关于OpenCV安装 1.下载和安装OpenCV SDK 在官网:http://opencv.org/上找到OpenCV windows版下载 . 后得到一个 opencv-2.X.X.exe的文件, ...

  4. OpenCV学习2-----使用inpaint函数进行图像修复

    安装opencv时,在opencv的安装路径下, sources\samples\cpp\  路径里面提供了好多经典的例子,很值得学习. 这次的例子是利用inpaint函数进行图像修复. CV_EXP ...

  5. OpenCV学习(35) OpenCV中的PCA算法

    PCA算法的基本原理可以参考:http://www.cnblogs.com/mikewolf2002/p/3429711.html     对一副宽p.高q的二维灰度图,要完整表示该图像,需要m = ...

  6. 【OpenCV学习笔记】之六 手写图像旋转函数---万丈高楼平地起

    话说,平凡之处显真格,这一点也没错!  比如,对旋转图像进行双线性插值,很简单吧?  可,对我,折腾了大半天,也没有达到预期效果!  尤其是三个误区让我抓瞎好久: 1,坐标旋转公式.   这东西,要用 ...

  7. opencv学习笔记(03)——遍历图像(迭代器法)

    #include <opencv2\highgui\highgui.hpp> #include <opencv2\imgproc\imgproc.hpp> #include & ...

  8. opencv学习笔记(01)——操作图像的像素

    #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <ope ...

  9. opencv学习笔记(02)——遍历图像(指针法)

    #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <ope ...

随机推荐

  1. git推送本地仓库到github

    总结一下,方便后人,也方便自己查阅.直接写步骤 一.本地创建一个文件夹,在里面写项目的文件(* .php/*.js.....). git本地操作: 1 .  cd  /path/to/project  ...

  2. Windows 中打开 shell

    按住 Shift,单机鼠标右键"在当前目录打开命令窗口"

  3. OpenJudge——0003:jubeeeeeat

    OpenJudge——0003:jubeeeeeat 描述 众所周知,LZF很喜欢打一个叫Jubeat的游戏.这是个音乐游戏,游戏界面是4×4的方阵,会根据音乐节奏要求玩家按下一些指定方块(以下称co ...

  4. [代码审计]某开源商城前台getshell

    0x00 前言 这套系统搞了有点久了,漏洞是发现了,但一直卡在某个地方迟迟没拿下来. 下面就分享一下自己审这套系统的整个过程. 0x01 系统简介 略   0x02 审计入口 看到inc\functi ...

  5. read file into shell vars

    test.ksh value=$(<rosstest.txt)echo $value

  6. 日报 18/07/15 Java 性能优化

    尽量指定类和方法的final修饰符 带有final修饰符的类是不可派生的 在java核心api中 有许多应用final的例子 例如 java.lang.string整个类都是final的 为类指定fi ...

  7. requests https访问错误SSLError: certificate verify failed 及InsecureRequestWarning处理办法

    转自: https://blog.csdn.net/mighty13/article/details/78076258?locationNum=3&fps=1 在使用requests访问某网站 ...

  8. linux文件删除,剩余空间没变化

    centOS6.6,删除了一个13G的文件,但是使用df -h 查看,剩余空间没变化这个文件夹查看 du -h查看发现空间已经变少了.原因可能是删除文件时有进程在使用文件,导致空间未释放.yum in ...

  9. Java基础(1)JDK的安装与环境变量配置

    最近在复习Java基础,第一课就是JDK的安装配置以及环境变量的配置,不多废话,直接开始吧 (1)去Oracle官方网站下载JDK 1.8 Java的历史想必大家也清楚,Sun公司开发的一门面向对象的 ...

  10. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D. Bear and Two Paths 构造

    D. Bear and Two Paths 题目连接: http://www.codeforces.com/contest/673/problem/D Description Bearland has ...