opencv之局部方向模式(LDP)

来源:互联网 发布:华为路由器设置mac地址 编辑:程序博客网 时间:2024/06/05 03:08

    人脸图像的局部方向模式基本思想是图像每个相素点都有一个局部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/9328865

main.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)卷积后不取绝对值




0 0