您的位置:首页 > 运维架构

opencv之局部方向模式(LDP)

2015-12-05 15:20 357 查看
人脸图像的局部方向模式基本思想是图像每个相素点都有一个局部3×3 邻域像素灰度值,该相素处于邻域中心。将该局部与3×3 邻域的灰度值与8 个Kirsch 模板卷积得到相应方向的边缘梯度值(i=0,1,…,7),将边缘梯度值的绝对值 进行排序,求出第k大的值 并将大于等于 的 对应的第i位二进制数设置为1,剩余8-i位置为0,得到一个八位的二进制编码,然后根据不同位置进行加权求和,所得的十进制数即为该像素点的 LDP 特征值。八个方向的 Kirsch 模板(M0~M7)如图 1 所示,LDP 特征提取流程如图 2 所示。源码如下:完整的Qt工程下载:http://download.csdn.net/detail/j_d_c/9328865main.cpp
#include"ldp.h"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc,char *argv[])
{
int R=1;
Mat grayImg,ldpImg;
Mat pImg = imread("F:/MyQt/Gaussian/1.bmp",1);
grayImg.create(pImg.rows,pImg.cols,CV_8UC1);
cvtColor(pImg,grayImg,CV_RGB2GRAY);//转换成灰度图像
imshow("oringe",pImg);
LDP ldp;
ldp.ldppattern(grayImg,ldpImg,R);
namedWindow("ldpImg",WINDOW_AUTOSIZE);
imshow("ldpImg",ldpImg);
waitKey(0);
}
ldp.cpp
#include "ldp.h"
#include <qDebug>
#include <iostream>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
typedef struct
{
int position;
long point_value;
} PAIR;
/*按照降序排列*/
bool operator<(const PAIR &x, const PAIR &y)
{
return x.point_value > y.point_value;
}
LDP::LDP()
{
}
void  LDP::ldpEdirect(Mat &Ein,Mat &Eout)//Kirsch卷积模板
{
Mat dst=Mat::zeros(3,3,CV_32F);
//kirsch
Mat M0 = (Mat_<float>(3,3) << -3,-3,5,-3,0,5,-3,-3,5);
Mat M1 = (Mat_<float>(3,3) << -3,5,5,-3,0,5,-3,-3,-3);
Mat M2 = (Mat_<float>(3,3) << 5,5,5,-3,0,-3,-3,-3,-3);
Mat M3 = (Mat_<float>(3,3) << 5,5,-3,5,0,-3,-3,-3,-3);
Mat M4 = (Mat_<float>(3,3) << 5,-3,-3,5,0,-3,5,-3,-3);
Mat M5 = (Mat_<float>(3,3) << -3,-3,-3,5,0,-3,5,5,-3);
Mat M6 = (Mat_<float>(3,3) << -3,-3,-3,-3,0,-3,5,5,5);
Mat M7 = (Mat_<float>(3,3) << -3,-3,-3,-3,0,5,-3,5,5);
filter2D(Ein,dst,dst.depth(),M0,Point(-1,-1));
Eout.ptr<float>(1)[2] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M1,Point(-1,-1));
Eout.ptr<float>(0)[2] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M2,Point(-1,-1));
Eout.ptr<float>(0)[1] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M3,Point(-1,-1));
Eout.ptr<float>(0)[0] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M4,Point(-1,-1));
Eout.ptr<float>(1)[0] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M5,Point(-1,-1));
Eout.ptr<float>(2)[0] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M6,Point(-1,-1));
Eout.ptr<float>(2)[1] = dst.ptr<float>(1)[1];
filter2D(Ein,dst,dst.depth(),M7,Point(-1,-1));
Eout.ptr<float>(2)[2] = dst.ptr<float>(1)[1];
}
void LDP::ldppattern(Mat &srcImg,Mat &ldpImg,int r)
{
int L = 2*r+1;
ldpImg.create(srcImg.rows,srcImg.cols,CV_8UC1);
Mat borderImg;
copyMakeBorder(srcImg,borderImg,L/2,L/2,L/2,L/2,BORDER_CONSTANT,Scalar::all(0));//卷积前对原图像上下左右进行扩展
Mat A,m;
A.create(L,L,CV_8U);
m = Mat::zeros(3,3,CV_32F);
int t[8];
for(int y=L/2;y<=borderImg.rows-L;y++)//行数变化
{ if(y>(borderImg.rows-L)) break;
for(int x=L/2;x<=borderImg.cols-L;x++)//列变化
{ if(x>(borderImg.cols-L)) break;//该语句是为了防止超过边界值
A = borderImg(Rect(x-L/2,y-L/2,L,L));
ldpEdirect(A,m);
t[0] = m.ptr<float>(1)[2];
t[1] = m.ptr<float>(0)[2];
t[2] = m.ptr<float>(0)[1];
t[3] = m.ptr<float>(0)[0];
t[4] = m.ptr<float>(1)[0];
t[5] = m.ptr<float>(2)[0];
t[6] = m.ptr<float>(2)[1];
t[7] = m.ptr<float>(2)[2];
PAIR pair[8];
vector<PAIR> vec;
int codebit[8]={0};
for(int i=0;i<8;i++)
{
pair[i].position = i;
pair[i].point_value = t[i];
vec.push_back(pair[i]);
}
sort(vec.begin(), vec.end());
// cout << "排序的结果为:" << endl;
//将最大的前三个值对应位置置1
for(vector<PAIR>::iterator it = vec.begin(); it < vec.begin()+3; ++it) {
codebit[it->position] = 1;
}
ldpImg.ptr<uchar>(y-L/2)[x-L/2] = codebit[7]*pow(2.0,7.0)+codebit[6]*pow(2.0,6.0)+codebit[5]*pow(2.0,5.0)+codebit[4]*pow(2.0,4.0)
+ codebit[3]*pow(2.0,3.0)+codebit[2]*pow(2.0,2.0)+codebit[1]*pow(2.0,1.0)+codebit[0]*pow(2.0,0.0);
}
}
}
运行结果:(1)卷积后取绝对值(1)卷积后不取绝对值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: