C++ PCA变换
创建PCA类和其成员函数,调用了eigen库(报错毫不含糊)
#pragma once
#include<iostream>
#include<Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <opencv.hpp>
#include<opencv2/core/eigen.hpp>
using namespace Eigen;
using namespace std;
class MYPCA
{
public:
float mycov(MatrixXf x1, MatrixXf x2);
MatrixXf KL(float** data, int lines, int column);
};
float MYPCA::mycov(MatrixXf x1, MatrixXf x2)//求得两个列向量之间的协方差
{
float Re = 0;
MatrixXf mean1, Mean1, mean2, Mean2, re, mul1(x1.rows(), 1), mul2(x1.rows(), 1);
mean1 = x1.colwise().mean();//生成x1.rows()*1的全为1矩阵
mean2 = x2.colwise().mean();
Mean1 = MatrixXf::Ones(x1.rows(), 1) * mean1;
Mean2 = MatrixXf::Ones(x2.rows(), 1) * mean2;
mul1 = x1 - Mean1;//求差
mul2 = x2 - Mean2;
re = mul1.array() * mul2.array();//协方差
Re = re.mean();
return Re;
}
MatrixXf MYPCA::KL(float** data, int lines, int column)//主成分变换
{
MatrixXf m(lines, column), x(column, lines), eigenvalue, eigenvector, A, Y;
for (int i = 0; i < lines; i++)//存取数据至矩阵
{
for (int j = 0; j < column; j++)
{
m(i, j) = data[i][j];
}
}
x = m.transpose();//转置
MatrixXf covmat(x.cols(), x.cols());
for (int i = 0; i < x.cols(); i++)//按波段分别进行协方差计算
{
for (int j = 0; j < x.cols(); j++)
{
covmat(i, j) = mycov(x.col(i), x.col(j));
}
}
SelfAdjointEigenSolver<MatrixXf> eigensolver(covmat);//调用函数求取特征值和特征向量
if (eigensolver.info() != Success) abort();
eigenvalue = eigensolver.eigenvalues();
eigenvector = eigensolver.eigenvectors();
cout << "特征值:" << eigenvalue << " ";
cout << endl << "特征向量:" << endl << eigenvector << " ";
A = eigenvector.transpose();
Y = A * m;
MatrixXf temp(1, Y.cols());
//对矩阵进行调换,将第一主成分放在前面
for (int i = 0; i <= Y.rows() / 2; i++)
{
temp = Y.row(i);
Y.row(i) = Y.row(Y.rows() - i - 1);
Y.row(Y.rows() - i - 1) = temp;
}
return Y;
}
调用的时候需要配置opencv ,eigen,并且包含头文件:PCA.h
运行结果截图:
读取原始的影像。
由于代码原因,只选择显示第一主成分,后面可以考虑完善代码显示更多成分图像
计算过程中显示特征值和特征向量方便进行检查错误