opencv类:PCA降低数据的维度(主成分分析法的学习)

PCA降维的学习

以下代码是在opencv中的函数pca.cpp的基础上进行了一些更改,主要更改体现在读取

降维样本方面,并对代码加上了一些自己理解的注释:

    #include <iostream>
    #include <fstream>
    #include <sstream>  
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>  
    using namespace cv;
    using namespace std;

    ///
    // Functions    
    static  Mat formatImagesForPCA(const vector<Mat> &data)
    {
        Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32F);
        for(unsigned int i = 0; i < data.size(); i++)
        {
            Mat image_row = data[i].clone().reshape(1,1);
            Mat row_i = dst.row(i);
            image_row.convertTo(row_i,CV_32F);
        }
        return dst;
    }

    static Mat toGrayscale(InputArray _src) {
        Mat src = _src.getMat();
        // only allow one channel
        if(src.channels() != 1) {
            CV_Error(CV_StsBadArg, "Only Matrices with one channel are supported");
        }
        // create and return normalized image
        Mat dst;
        cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
        return dst;
    }

    struct params
    {
        Mat data;
        int ch;
        int rows;
        PCA pca;
        string winName;
    };

    static void onTrackbar(int pos, void* ptr)
    {
        cout << "Retained Variance = " << pos << "%   ";
        cout << "re-calculating PCA..." << std::flush;

        double var = pos / 100.0;

        struct params *p = (struct params *)ptr;

        p->pca = PCA(p->data, cv::Mat(), CV_PCA_DATA_AS_ROW, var);

        Mat point = p->pca.project(p->data.row(0));
        Mat reconstruction = p->pca.backProject(point);
        reconstruction = reconstruction.reshape(p->ch, p->rows);
        reconstruction = toGrayscale(reconstruction);

        imshow(p->winName, reconstruction);
        cout << "done!   # of principal components: " << p->pca.eigenvectors.rows << endl;
    }


    ///
    // Main
    int main()
        {   

        // vector to hold the images
        vector<Mat> images;//image将用于保存所有的人脸特征
        //循环读取15张人脸图像,并以此保存在images中
        for (int i = 1; i <= 15; i++)
        {
            string file;
            char fileName[200];
            sprintf(fileName,"D:\\1研究生\\Facial Expression Research\\表情识别\\Database\\Jaffe\\%d.tiff",i);
            file=fileName;
            Mat temp=imread(file,0);//temp矩阵的大小为:64*64
            images.push_back(temp);
        }              
    //如果只读入了一张照片,将会报错,PCA降维时至少要有两个人脸图片,也就是说只是要有两个样本。
        if(images.size() <= 1) {
            string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
            CV_Error(CV_StsError, error_message);
        }

        // Reshape and stack images into a rowMatrix
        //formatImagesForPCA:该函数实现的功能是将各个样本从矩阵变为一个行向量,向量元素个数是图片的行*列。在PCA降维时并不是对图片进行处理,而是将各个图片变为向量来处理。
        Mat data = formatImagesForPCA(images);//data矩阵大小为:15*(64*64)

        // perform PCA 
        PCA pca(data, cv::Mat(), CV_PCA_DATA_AS_ROW, 0.95); // trackbar is initially set here, also this is a common value for retainedVariance

        // 将PCA降维的效果用第一张人脸图片来显示出来。
        Mat point = pca.project(data.row(0)); // project into the eigenspace, thus the image becomes a "point"//将data.row(0)投射到PCA降维后的空间,经过投射后,数据的维度将会降低,学者可是试着输出point的列数来查看。
        Mat reconstruction = pca.backProject(point); // re-create the image from the "point"
        reconstruction = reconstruction.reshape(images[0].channels(), images[0].rows); // reshape from a row vector into image shape
        reconstruction = toGrayscale(reconstruction); // re-scale for displaying purposes
        //以下代码实现了在窗口中创建了一个滚动条,单击滚动条可以实现输出不同保留特征率下的降维后的主成分个数
        // init highgui window
        string winName = "Reconstruction | press 'q' to quit";
        namedWindow(winName, WINDOW_NORMAL);

        // params struct to pass to the trackbar handler
        params p;
        p.data = data;
        p.ch = images[0].channels();
        p.rows = images[0].rows;
        p.pca = pca;
        p.winName = winName;

        // create the tracbar
        int pos = 95;
        createTrackbar("Retained Variance (%)", winName, &pos, 100, onTrackbar, (void*)&p);

        // display until user presses q
        imshow(winName, reconstruction);

        int key = 0;
        while(key != 'q')
            key = waitKey();

       return 0;
    }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值