opencv pca主成分分析使用样例:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
#define DIMENTIONS 512 // 特征向量维数
#define SAMPLE_NUM 16204 // 样本个数
#define PCA_DIMS 64 // PCA降维特征值数量
#define PCA_MEAN "mean"
#define PCA_EIGEN_VECTOR "eigen_vector"
cv::Mat read_csv(const char *filepath, cv::Size img_size, int img_type);
int main()
{
// 1 读特征向量
std::string lfwFeature = "./imgfeatures.csv";
cv::Mat SampleSet = read_csv(lfwFeature.c_str(), cv::Size(DIMENTIONS, SAMPLE_NUM), CV_32FC1);
// 2 Training
PCA *pca = new PCA(SampleSet, Mat(), CV_PCA_DATA_AS_ROW);
// 特征值求和
float sum_eigVal = 0.0f;
for (int i = 0; i < DIMENTIONS; ++i)
{
sum_eigVal += pca->eigenvalues.at<float>(i, 0);
}
//
Mat eigenvetors_d;
float save_eigenVal = 0.0f;
eigenvetors_d.create(PCA_DIMS, DIMENTIONS, CV_32FC1); // eigen values of decreased dimension
for (int i = 0; i < PCA_DIMS; ++i)
{
pca->eigenvectors.row(i).copyTo(eigenvetors_d.row(i)); // 特征向量保存到eigenvetors_d
save_eigenVal += pca->eigenvalues.at<float>(i, 0);
}
printf("prePCA_DIMS %.4f percentage\n", save_eigenVal*1.0 / sum_eigVal);
//cout << "eigenvectors" << endl << eigenvetors_d << endl;
FileStorage fs_w("config.xml", FileStorage::WRITE); // write mean and eigenvalues into xml file
fs_w << PCA_MEAN << pca->mean;
fs_w << PCA_EIGEN_VECTOR << eigenvetors_d;
fs_w.release();
//Encoding
PCA *pca_encoding = new PCA();
//Mat input(1, DIMENTIONS, CV_32FC1);//Test input
//for (int j = 0; j < DIMENTIONS; ++j)
//{
// input.at<float>(0, j) = rand() % 100;
//}
//FileStorage fs_r("config.xml", FileStorage::READ);
//fs_r[PCA_MEAN] >> pca_encoding->mean;
//fs_r[PCA_EIGEN_VECTOR] >> pca_encoding->eigenvectors;
//fs_r.release();
//
//Mat output_encode(1, pca_encoding->eigenvectors.rows, CV_32FC1); // 经pca变换后的特征向量
//pca_encoding->project(input, output_encode);
//delete pca;
delete pca_encoding;
system("pause");
return 0;
}
cv::Mat read_csv(const char *filepath, cv::Size img_size, int img_type)
{
cv::Mat image;
image.create(img_size, img_type);
string pixel;
std::ifstream file(filepath, std::ifstream::in);
if (!file)
std::cout << "CSV read fail" << std::endl;
int nl = image.rows; // number of lines
int nc = image.cols; // number of columns
int eolElem = image.cols - 1; //每行最后一个元素的下标
int elemCount = 0;
if (image.isContinuous())
{
nc = nc*nl; // then no padded pixels
nl = 1; // it is now a 1D array
}
for (int i = 0; i < nl; i++)
{
float* data = (float*)image.ptr<ushort>(i);
for (int j = 0; j < nc; j++)
{
if (elemCount == eolElem)
{
getline(file, pixel, '\n'); //任意地读入,直到读到delim字符 '\n',delim字符不会被放入buffer中
data[j] = (float)atof(pixel.c_str()); //将字符串str转换成一个双精度数值并返回结果
elemCount = 0; //计数器置零
}
else
{
getline(file, pixel, ','); //任意地读入,直到读到delim字符 ','delim字符不会被放入buffer中
data[j] = (float)atof(pixel.c_str()); //将字符串str转换成一个双精度数值并返回结果
elemCount++;
}
}
}
file.close();
return image;
}