OpenCV学习(39) OpenCV中的LBP图像

本章我们学习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

时间: 2024-07-30 01:00:11

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

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

kmeans算法的原理参考:http://www.cnblogs.com/mikewolf2002/p/3368118.html 下面学习一下opencv中kmeans函数的使用.      首先我们通过OpenCV中的随机数产生器RNG,生成一些均匀分布的随机点,这些点的位置对应一副图像中的像素位置,然后使用kmeans算法对这些随机点进行分类,并计算出分类簇的中心点.      随机产生的簇的数量是2到5之间的值,采样点的数量范围是1-1000,一维矩阵centers存放kmeans算法结束

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

PCA算法的基本原理可以参考:http://www.cnblogs.com/mikewolf2002/p/3429711.html     对一副宽p.高q的二维灰度图,要完整表示该图像,需要m = p*q维的向量空间,比如100*100的灰度图像,它的向量空间为100*100=10000.下图是一个3*3的灰度图和表示它的向量表示: 该向量为行向量,共9维,用变量表示就是[v0, v1, v2, v3, v4, v5, v6, v7, v8],其中v0...v8,的范围都是0-255.    

OpenCV学习(2) OpenCV的配置

      下面我们在VS2010中编写一个简单的OpenCV程序,来看看如何在程序中使用OpenCV. 创建一个新的Win32 控制台程序,附加选项为空工程(empty project),并添加一个cpp源文件main.cpp,内容如下: #include <opencv2/core/core.hpp> #include <opencv2/highgui//highgui.hpp> int main() { cv::Mat img = cv::imread("lenna

OpenCV学习(3) OpenCV框架

      OpenCV是一个开源的视觉库,其中包括很多计算机视觉的算法实现.在版本2.2以后,OpenCV采用C++特征的API,在1.x版本中,OpenCV函数都是传统的C语言形式.       OpenCV采用模块化的结构,每个模块都是由一些动态和静态库组成,该模块会实现一些特定的计算机视觉算法.要使用某个特定的库,我们必须在程序中先包含该库的头文件,并把该库的lib作为链接库. 例如要使用core和highgui库,则必须在程序源文件中包含: #include <opencv2/core

OpenCV学习(1) OpenCV的安装

1. 下载文件 下载最新的OpenCV windows版本: 链接:http://sourceforge.net/projects/opencvlibrary/files/opencv-win/       我下载的版本是2.46,下载后得到OpenCV-2.4.6.0.exe,自解压该文件到目录D:\opencv2.31\opencv2.46.自解压之后,会生成一个opencv的子目录,所有的opencv文件都在这个目录中. 2.编译文件 我使用CMake2.8来编译OpenCV:      

(转) OpenCV学习笔记大集锦 与 图像视觉博客资源2之MIT斯坦福CMU

      首页 视界智尚 算法技术 每日技术 来打我呀 注册     OpenCV学习笔记大集锦 整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址:http://blog.csdn.net/column/details/opencv-manual.html 2:部分OpenCV的函数解读和原理解读 作者:梦想腾飞数量:20篇博文网址:http:/

如何利用opencv实现在视频中每隔固定的n像素列数取一副图像?

问题描述 如何利用opencv实现在视频中每隔固定的n像素列数取一副图像? 在视频中,视频向前播放,视频画面每隔固定的像素列数n后,取当前的画面.各位大神有没有思路? 解决方案 视频不是以帧的形式播放的吗?那怎么实现你这种方法哦.除非你的n个列数就是一幅图像列数

计算方差-请教大神在opencv中怎么计算图像局部方差

问题描述 请教大神在opencv中怎么计算图像局部方差 请教大神在opencv中怎么计算图像局部方差, 请教大神在opencv中怎么计算图像局部方差, 请教大神在opencv中怎么计算图像局部方差,谢谢 解决方案 你也在学opencv吗,可以交流下 解决方案二: 局部,是正常的矩形还是不规则区域 矩形: 坐标的x y即像素点的x y根据长宽遍历 不规则: 我暂时没有计算过 你图像是灰阶还是RGB 如果灰阶 按照灰阶度使用公式即可,如果是RGB建议先用cvmerxx 函数忘记了 把RGB通道合成之

OpenCV学习(9) 分水岭算法(3)

本教程我学习一下opencv中分水岭算法的具体实现方式. 原始图像和Mark图像,它们的大小都是32*32,分水岭算法的结果是得到两个连通域的轮廓图. 原始图像:(原始图像必须是3通道图像) Mark图像: 结果图像:       初始的mark图像数据如下,黄色的部分为我们的第一个mark区域,值为255,第二个区域为褐红色的区域,值为128,第三个绿色的区域,值为64.   opencv分水岭算法描述如下: 初始化mark矩阵,生成最初的注水区域. 1.设置mark图像的边框值为-1 2.