您的位置:首页 > 编程语言 > C语言/C++

【图像特征提取4】改进的圆形局部二值模式LBP特征描述符C++代码的实现

2017-03-16 11:16 585 查看
/********************************************************************************************************
文件说明:
改进的圆形LBP的C++代码实现
开发环境:
Win7 + OpenCv2.4.8 + VS2012
时间地点:
陕西师范大学 2017.3.16
作    者:
九 月
*********************************************************************************************************/
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>

using namespace std;
using namespace cv;

/********************************************************************************************************
函数说明:
改进的圆形局部二值模式特征LBP的C++代码实现
参数说明:
1)Mat img-----------输入图像说明
2)int radius--------圆形窗口的半径
3)int neighbours----圆形窗口邻域的采样点数
*********************************************************************************************************/
//圆形LBP
cv::Mat ELBP(Mat img, int radius, int neighbors)
{
cv::Mat result;
//【1】创建一个结果矩阵,这个矩阵包含矩阵头和矩阵体
result.create(img.rows-radius*2, img.cols-radius*2, img.type());
//【2】初始化这个矩阵的矩阵体
result.setTo(0);
//【3】计算圆形邻域内的局部二值模式的LBP特征
for(int n=0; n<neighbors; n++)
{
//【1】2.0*CV_PI/neighbors相当于把一个圆周的弧度值按照采样点的个数进行等分
float x = static_cast<float>(radius  * cos(2.0*CV_PI*n/static_cast<float>(neighbors)));
float y = static_cast<float>(-radius * sin(2.0*CV_PI*n/static_cast<float>(neighbors)));

int fx = static_cast<int>(floor(x));              //【2】floor的函数是向下取整
int fy = static_cast<int>(floor(y));              //【3】之所以向下取整,是因为我们以R为半径,以一个点为窗口中心,进行采样,
//     这样得到的笛卡尔坐标有可能不是整数
int cx = static_cast<int>(ceil(x));               //【4】向上取整函数,返回一个大于等于X的数
int cy = static_cast<int>(ceil(y));
// fractional part
float ty = y - fy;                                  //【5】计算坐标点的小数部分
float tx = x - fx;
// set interpolation weights
float w1 = (1 - tx) * (1 - ty);                     //【6】设置插值权重
float w2 =      tx  * (1 - ty);
float w3 = (1 - tx) *      ty;
float w4 =      tx  *      ty;
// iterate through your data
for(int i=radius; i < img.rows-radius;i++)
{
for(int j=radius;j < img.cols-radius;j++)
{
// calculate interpolated value
float t = static_cast<float>(w1*img.at<uchar>(i+fy,j+fx) + w2*img.at<uchar>(i+fy,j+cx) + w3*img.at<uchar>(i+cy,j+fx) + w4*img.at<uchar>(i+cy,j+cx));
// floating point precision, so check some machine-dependent epsilon
result.at<uchar>(i-radius,j-radius) += ((t > img.at<uchar>(i,j)) || (std::abs(t-img.at<uchar>(i,j)) < std::numeric_limits<float>::epsilon())) << n;
}
}
}
return result;
}

int main()
{
cv::Mat srcImg = cv::imread(".\\images\\crack.jpeg",0);
if(srcImg.empty())
{
std::cout<<"【NOTICE】NO valid inout image was given,please check the inoput image!"<<std::endl;
std::system("pause");
return -1;
}
cv::Mat resultMat = ELBP(srcImg,1,8);
cv::imshow("srcImg",srcImg);
cv::imshow("imgLBP",resultMat);
cv::waitKey(0);
return 0;
}




/********************************************************************************************************
文件说明:
改进的具有灰度不变性的局部二值模式的LBP特征-----代码稍微有点问题
开发环境:
Win7 + OpenCv2.4.8 + VS2012
时间地点:
陕西师范大学 2017.3.16
作    者:
九 月
*********************************************************************************************************/
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>

using namespace std;
using namespace cv;

/********************************************************************************************************
函数说明:
改进的x旋转不变性局部二值模式特征LBP的C++代码实现
参数说明:
Mat img-----------输入图像说明
*********************************************************************************************************/
cv::Mat RILBP(Mat img)
{
uchar   RITable[256];
int     temp = 0;
int     val  = 0;
cv::Mat result;
result.create(img.rows - 2, img.cols -2 , img.type());
result.setTo(0);
/******************************************************************************************************
核心模块:
下面这个模块是:旋转不变性局部二值模式LBP特征的核心思想
旋转不变:
我们把[0,255]这256个值当作256中LBP特征编码值,然后,对每一种特征编码值,先将这种特征编码值当作
一个八位的二进制数,并且这八位的二进制数组成了一个圆形;然后不断的对着八位二进制数按位右移,找
到这个过程中LBP特征编码所对应的最小的值,然后将这个值保存起来。
这块代码的作用,其实就相当于计算出了这256种LBP特征值编码所对应的旋转不变性的LBP特征编码值
******************************************************************************************************/
for(int i = 0; i<256; i++)
{
val = i;
for(int j =0; j<7; j++)
{
temp = i>>1;
if(val>temp)
{
val = temp;
}
}
RITable[i] = val;
}

for(int j=0;j<256;j++)
{
std::cout<<j<<"Value = "<<(int)RITable[j]<<std::endl;
}
for(int i = 1; i<img.rows - 1; i++)
{
for(int j = 1;j<img.cols -1; j++)
{
uchar center = img.at<uchar>(i, j);
uchar code = 0;

code |= (img.at<uchar>(i-1, j-1) >= center)<<7;               //按位或
code |= (img.at<uchar>(i-1, j)   >= center)<<6;
code |= (img.at<uchar>(i-1, j+1) >= center)<<5;
code |= (img.at<uchar>(i,   j+1) >= center)<<4;
code |= (img.at<uchar>(i+1, j+1) >= center)<<3;
code |= (img.at<uchar>(i+1, j)   >= center)<<2;
code |= (img.at<uchar>(i+1, j-1) >= center)<<1;
code |= (img.at<uchar>(i,   j-1) >= center)<<0;

result.at<uchar>(i -1, j -1) = RITable[code];
}
}
return result;
}

int main()
{
cv::Mat srcImg = cv::imread(".\\images\\crack.jpeg",0);
if(srcImg.empty())
{
std::cout<<"【NOTICE】NO valid inout image was given,please check the inoput image!"<<std::endl;
std::system("pause");
return -1;
}

cv::Mat resultMat = RILBP(srcImg);
cv::imshow("srcImg",srcImg);
cv::imshow("imgLBP",resultMat);
cv::waitKey(0);
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: