OpenCV实现主成分分析(PCA)

5 篇文章 0 订阅
3 篇文章 0 订阅

这几天将大学期间做的项目,尝试将MATLAB代码转为C++。
这里对主成分做一个备忘。
这里先简单说一下我对主成分的理解,就是将数据降维。一组数据间的各个元素可能存在一定的关联。比如:一组数据[1 2 3],那么3可以由1+2表示,那么就可以用[1 2]来表示[1 2 3]这组数据,这样在实际数据处理时,就可以只用处理2维的数据,不用处理3维数据,可以提高程序效率。详细的原理讲解,网上大神们讲得都很好。我这里就主要说代码。

在实际工程中,PCA处理一般分为两步:1、获取数据均值、特征值、特征向量;2、利用第一步的特征值获取输入参量的主成分。
我这里只要用OpenCV来实现。

环境:WIN10+VS2015+OpenCV3.1.0

第一步:获取特征向量

#include <opencv2/opencv.hpp>
#include <fstream>

using namespace cv;
using namespace std;


// data:输入数据
// T:主成分百分比;范围0--1
// path:数据保存路径
int My_PCA(Mat data, float T, String path)
{
    PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW);

    Mat latent = pca.eigenvalues.t();

    double latent_sum = sum(latent).val[0];
    int len = latent.cols;

    float flag_sum = 0;
    int i = 0;
    while (flag_sum <= T && i < len)                    // 计算达到要求的主成分数
    {
        flag_sum = flag_sum + latent.ptr<float>(0)[i]/ latent_sum;
        i++;
    }

    Mat _coeff = pca.eigenvectors;
    Mat coeff = _coeff(Range(0, i), Range::all());          // 获取主要成分

    FileStorage f_pca("path", FileStorage::WRITE);          // 主要参数
    f_pca << "num" << i;
    f_pca << "mean" << pca.mean;
    f_pca << "coff" << coeff;
    f_pca.release();

    latent.release();
    _coeff.release();
    coeff.release();

    return 0;
}

其中将获取后的数据进行保存,方便以后使用。

第二步:主成分分析

#include <opencv2/opencv.hpp>
#include <fstream>

using namespace cv;
using namespace std;


// data:输入数据
// path:数据保存路径
Mat My_PCAs(Mat data, String path)
{
    FileStorage f_pca("path", FileStorage::READ);           
    int num;
    Mat mean, coff;

    f_pca["num"] >> num;
    f_pca["mean"] >> mean;
    f_pca["coff"] >> coff;

    f_pca.release();

    Mat result = (data - mean)*(coff.t());

    mean.release();
    coff.release();

    return result;

}

这里需要加载第一步获取的主成分数据。

主程序:

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace cv;
using namespace std;

int My_PCA(Mat data, float T, String path);
Mat My_PCAs(Mat data, String path);

#define DIMENTIONS 7
#define SAMPLE_NUM 31 
float Coordinates[DIMENTIONS*SAMPLE_NUM] = {
    101.5, 100.4, 97.0, 98.7, 100.8, 114.2, 104.2
    , 100.8, 93.5, 95.9, 100.7, 106.7, 104.3, 106.4
    , 100.8, 97.4, 98.2, 98.2, 99.5, 103.6, 102.4
    , 99.4, 96.0, 98.2, 97.8, 99.1, 98.3, 104.3
    , 101.8, 97.7, 99.0, 98.1, 98.4, 102.0, 103.7
    , 101.8, 96.8, 96.4, 92.7, 99.6, 101.3, 103.4
    , 101.3, 98.2, 99.4, 103.7, 98.7, 101.4, 105.3
    , 101.9, 100.0, 98.4, 96.9, 102.7, 100.3, 102.3
    , 100.3, 98.9, 97.2, 97.4, 98.1, 102.1, 102.3
    , 99.3, 97.7, 97.6, 101.1, 96.8, 110.1, 100.4
    , 98.7, 98.4, 97.0, 99.6, 95.6, 107.2, 99.8
    , 99.7, 97.7, 98.0, 99.3, 97.3, 104.1, 102.7
    , 97.6, 96.5, 97.6, 102.5, 97.2, 100.6, 99.9
    , 98.0, 98.4, 97.1, 100.5, 101.4, 103.0, 99.9
    , 101.1, 98.6, 98.7, 102.4, 96.9, 108.2, 101.7
    , 100.4, 98.6, 98.0, 100.7, 99.4, 102.4, 103.3
    , 99.3, 96.9, 94.0, 98.1, 99.7, 109.7, 99.2
    , 98.6, 97.4, 96.4, 99.8, 97.4, 102.1, 100.0
    , 98.2, 98.2, 99.4, 99.3, 99.7, 101.5, 99.9
    , 98.5, 96.3, 97.0, 97.7, 98.7, 112.6, 100.4
    , 98.4, 99.2, 98.1, 100.2, 98.0, 98.2, 97.8
    , 99.2, 97.4, 95.7, 98.9, 102.4, 114.8, 102.6
    , 101.3, 97.9, 99.2, 98.8, 105.4, 111.9, 99.9
    , 98.5, 97.8, 94.6, 102.4, 107.0, 115.0, 99.5
    , 98.3, 96.3, 98.5, 106.2, 92.5, 98.6, 101.6
    , 99.3, 101.1, 99.4, 100.1, 103.6, 98.7, 101.3
    , 99.2, 97.3, 96.2, 99.7, 98.2, 112.6, 100.5
    , 100.0, 99.9, 98.2, 98.3, 103.6, 123.2, 102.8
    , 102.2, 99.4, 96.2, 98.6, 102.4, 115.3, 101.2
    , 100.1, 98.7, 97.4, 99.8, 100.6, 112.4, 102.5
    , 104.3, 98.7, 100.2, 116.1, 105.2, 101.6, 102.6
};
float Coordinates_test[DIMENTIONS] = {
    104.3, 98.7, 100.2, 116.1, 105.2, 101.6, 102.6
};

int main()
{
    Mat pcaSet(SAMPLE_NUM, DIMENTIONS, CV_32FC1);    //原始数据
    Mat Coordinates1(1, DIMENTIONS, CV_32FC1, Coordinates_test);

    for (int i = 0; i < SAMPLE_NUM; i++)
    {
        for (int j = 0; j < DIMENTIONS; j++)
        {
            pcaSet.at<float>(i, j) = Coordinates[i*j + j];
        }
    }
    My_PCA(pcaSet, 0.9, "pca");//第一步,这里设置占主成分90%以上。

    Mat data = My_PCAs(Coordinates1, "pca");//第二步
    cout << "data: " << data << endl;

    system("pause");

}

C++处理结果:
这里写图片描述

MATLAB处理结果:
这里写图片描述

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值