文章目录
- 简述
- 演示
简述
在机器学习中,我们需要对数据进行特征提取,然后使用提取的数据特征进行训练,实现分类,回归等操作来对未知数据进行预测。为了提升模型的准确率和减少推理的计算量,所以我们需要对提取的特征进行评估,是否有重复特征或者白噪声,而这些特征往往是人下意思无法发现的,高维度数据会使得有效数据密度降低,使分类器的分类效果变差,从而需要更多的数据集。
1 通过对高维数据分析发现他们的相同与不同表达为一个低维数据模式,
2 主成分不变
3 细微损失
4 高维数据到低维数据
PCA主成分分析流程
- 获取数据矩阵
- 减去均值(归一化)
- 计算协方差矩阵
- 计算特征值与特征向量
- 根据特征值排序保留前K个主成分特征向量
- 形成新的数据样本
头文件 FaceRecognize.h
:
#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
class FaceRecognize {
public:
void PCA_demo(Mat& image);
void PCA_test_demo(Mat& image);
};
主函数main.cpp
#include "FaceRecognize.h"
int main(int argc, char**argv) {
const char* input_path = "D:/Desktop/222222.png";
Mat image = imread(input_path);
if (image.empty()) {
printf("Read image failed!");
exit(-1);
}
FaceRecognize face_recognize;
face_recognize.PCA_demo(image);
face_recognize.PCA_test_demo(image);
waitKey(0);
destroyAllWindows();
return 0;
}
演示
double calcPCAOrientation(vector<Point>& pts, Mat& image) {
int size = static_cast<int>(pts.size());
Mat data_pts = Mat(size, 2, CV_64FC1);
for (int i = 0; i < size; i++) {
data_pts.at<double>(i, 0) = pts[i].x;
data_pts.at<double>(i, 1) = pts[i].y;
}
// 主成分分析投影 (均值->特征值->特征向量)
PCA pca_analysis(data_pts, Mat(), 0);
Point cnt = Point(
static_cast<int>(pca_analysis.mean.at<double>(0, 0)),
static_cast<int>(pca_analysis.mean.at<double>(0, 1))
);
// 可视化contours[i]的中心点(均值)
circle(image, cnt, 2, Scalar(0, 0, 255), 2, 8, 0);
vector<Point2d> vecs(2);
vector<double> vals(2);
for (int i = 0; i < 2; i++) {
vals[i] = pca_analysis.eigenvalues.at<double>(i, 0);
vecs[i] = Point2d(
pca_analysis.eigenvectors.at<double>(i, 0),
pca_analysis.eigenvectors.at<double>(i, 1)
);
}
Point p1 = cnt + 0.02 * Point(static_cast<int>(vecs[0].x * vals[0]), static_cast<int>(vecs[0].y * vals[0]));
Point p2 = cnt - 0.05 * Point(static_cast<int>(vecs[1].x * vals[1]), static_cast<int>(vecs[1].y * vals[1]));
line(image, cnt, p1, Scalar(255, 0, 0), 2, 8, 0);
line(image, cnt, p2, Scalar(255, 255, 0), 2, 8, 0);
double angle = atan2(vecs[0].y, vecs[0].x);
printf("angle[0] : %.2f\n", 180 * (angle / CV_PI));
return angle;
}
void FaceRecognize::PCA_demo(Mat& image){
/// <summary>
/// 这个示例对图像的轮廓数据(点集=Xi,Yi)进行PCA主成分分析
/// </summary>
/// <param name="image"></param>
Mat gray, binary;
cvtColor(image, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
vector<Vec4i> hireachy;
vector<vector<Point>> contours;
findContours(binary, contours, hireachy, RETR_LIST, CHAIN_APPROX_NONE);
Mat result = image.clone();
for (int i = 0; i < contours.size(); i++) {
double area = contourArea(contours[i]);
if (area > 1e5 || area < 1e2) continue;
drawContours(result, contours, i, Scalar(0, 0, 255), 2, 8);
double theta = calcPCAOrientation(contours[i], result);
}
imshow("contours result", result);
}
void FaceRecognize::PCA_test_demo(Mat& image) {
Mat gray_img;
cvtColor(image, gray_img, COLOR_RGB2GRAY);
int top_k = 120;
PCA pca(gray_img, Mat(), PCA::DATA_AS_ROW, top_k);
cout << "pca.mean.size() = " << pca.mean.size() << endl;
cout << "pca.mean.size() = " << pca.eigenvalues.size() << endl;
cout << "pca.mean.size() = " << pca.eigenvectors.size() << endl;
Mat pca_after = pca.project(gray_img); // 降维后
Mat pca_remake = pca.backProject(pca_after); // 重构回来
cv::imshow("pca_after", pca_after);
cv::imshow("pca_remake", pca_remake);
}
//===================
//pca.mean.size() = [270 x 1]
//pca.mean.size() = [1 x 120]
//pca.mean.size() = [270 x 120]
关于特征保存: