图像处理之PCA(C++)

server/2024/9/23 0:31:40/

图像处理之PCA(C++)


文章目录

  • 图像处理之PCA(C++)
  • 前言
  • 一、PCA原理
    • 1.原理思想
    • 2.实现步骤
  • 二、代码实现
  • 总结


前言

在科研、工程应用中,我们往往所获取的数据都包含着很多冗余的信息,这些冗余的信息会对我们分析数据造成干扰。因此,我们可以采用PCA(主成分分析法)去除冗余信息,抓住主要特征,减少数据量。


一、PCA原理

1.原理思想

PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据降维算法。PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。
PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴,新的坐标轴的选择与数据本身是密切相关的。其中,第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。
主要的应用是:数据压缩(降维)、可视化高维特征、缓解维度灾难、特征独立、降噪、计算物体的方向

2.实现步骤

假设m条n维数据。(使用PCA主成分分析得到的结果就是得到降维后的m条k维数据)

  1. 将原始数据按列组成n行m列矩阵X0(n*m)
  2. 将矩阵X0的每一行进行零均值化,得到矩阵X(n*m),即减去这一行的均值
  3. 求出协方差矩阵C(n*n)(m为矩阵X0的列数)
    协方差矩阵
  4. 求出协方差矩阵的特征值及其对应的特征向量。得到n个特征值,对应n个特征向量,其中每个特征向量的长度又为n,也即所有特征向量组成n行n列的矩阵。
  5. 将特征向量按照特征值从大到小的顺序从上到下排列成矩阵,取前k行组成矩阵P(k*n)
  6. 根据Y=PX即可获得降维到k维后的数据矩阵Y(k*m)

二、代码实现

#include <iostream>
#include <opencv.hpp>
using namespace std;
using namespace cv;/*
* @param cv::Mat src 输入图像
* @param cv::Mat pca 输出图像
* @param int	k	 降维后的维度
* @brief pca主成分分析法降维
*/
void do_pca(cv::Mat src,cv::Mat& pca,int k)
{if (src.rows <= 1 || src.cols <= 1){return;}k = k > src.rows ? src.rows : k;		//取src.rows和k的较小值int h = src.rows;int w = src.cols;// 1.求每一行的平均值std::vector<float> meanVec(src.rows,0);for (int i = 0; i < h; i++){for (int j = 0; j < w; j++){meanVec[i] += src.at<uchar>(i, j);}meanVec[i] /= w;}// 2.去平均处理src.convertTo(src, CV_32F);for (int i = 0; i < h; i++){for (int j = 0; j < w; j++){src.at<float>(i, j) -= meanVec[i];}}// 3.计算协方差矩阵cv::Mat covMat;covMat = src * src.t()/w;// 4\5.求出协方差矩阵的特征值和对应的特征向量cv::Mat eigenValues;	//特征值cv::Mat eigenVectors;	//特征值对应的特征向量cv::eigen(covMat, eigenValues, eigenVectors);	//cv::eigen()输入必须是CV_32F或者CV_64F类型的对称矩阵,//且该函数输出的eigenValues和eigenVectors已经按照从大到小的顺序排列// 5.取前k行的矩阵Pcv::Mat kMat;eigenVectors(cv::Rect(0, 0, eigenVectors.cols, k)).copyTo(kMat);// 6.获得降维后的矩阵Ycv::Mat yMat;yMat = kMat * src;pca = yMat.clone();		//数据类型CV_32FC1
}int main()
{string path = "F://work_study//algorithm_demo//";cv::Mat src = cv::imread(path + "baby.jpg", cv::IMREAD_GRAYSCALE);if (src.empty())return -1;//自己实现的pcacv::Mat pca_dst;int k = 100;	//降维后维度do_pca(src, pca_dst, k);//opencv实现的pcacv::PCA pca(src, Mat(), PCA::DATA_AS_COL, k);cv::Mat dst = pca.project(src);imshow("pca", pca_dst);imshow("opencv_pca", dst);cv::waitKey(0);return 0;
}

原图
自己实现的pca
自己实现的pca
opencv实现的pca
opencv实现的pca


总结

本文使用C++借助opencv实现了pca算法,介绍了pca原理、计算过程以及源代码的实现,主要核心是利用opencv中的cv::eigen()对协方差矩阵进行特征值和特征向量的计算,欢迎大家提出问题。
本文代码均已经在本地运行成功,欢迎阅读交流。


http://www.ppmy.cn/server/39554.html

相关文章

本安防爆手机在电力行业中的应用

在电力行业这一充满挑战与风险的领域中&#xff0c;安全始终是最为首要的考量。电力巡检、维修等作业往往涉及易燃、易爆环境&#xff0c;这就要求工作人员配备能够在极端条件下保障通讯和作业安全的专业设备。防爆手机应运而生&#xff0c;以其独特的设计和卓越的性能&#xf…

vue3 antd-vue 超简单方式实现a-table跨页勾选

一、效果如下&#xff1a; 第一页勾选了2&#xff0c; 3&#xff0c; 4 翻到第三页勾选24&#xff0c; 25 回显&#xff0c;如比返回第一页的时候触发分页改变&#xff0c; 在映射中的第一页的数据给到a-table绑定的state.selectedRowKeys即可&#xff0c;如下方法 二、勾选思路…

开源高性能的分布式时序数据库:Lindb

Lindb&#xff1a;为大数据时代量身打造的高性能时序数据库&#xff0c;让海量数据存储与实时分析触手可及。- 精选真开源&#xff0c;释放新价值。 概览 Lindb 是一款开源的分布式时序数据库&#xff0c;它以其高性能和可伸缩性在海量数据存储及快速查询计算方面展现出独特的…

Jupyter配置远程访问的密码

安装 下载Anaconda的.sh文件后&#xff0c;上传到服务器&#xff0c;然后进行安装&#xff1a; chmod x anaconda.sh ./anaconda.sh创建虚拟环境 可以指定Python版本创建虚拟环境&#xff1a; conda create --name langchain python3.11.7 conda activate langchain conda …

Rust - 终端输入、文件读写

文章目录 查看参数接收终端输入读取文件写入文件 查看参数 fn main() { let args std::env::args();println!("{:?}", args); // Args { inner: ["target/debug/rt"] }for arg in args {println!("{}", arg);} }接收终端输入 use std::io:…

数据库基础语法二

一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo mysql -uroot -p #登陆数据库 create database zoo; #创建数据库zoo alter database zoo character set gbk collate gbk_…

【强训笔记】day17

NO.1 思路&#xff1a;用一个字符串实现&#xff0c;stoi函数可以转化为数字并且去除前导0。 代码实现&#xff1a; #include <iostream> #include<string> using namespace std;string s;int main() {cin>>s;for(int i0;i<s.size();i){if(s[i]%20) s[…

iOS 沙盒图片的存取

简介&#xff1a; 图片的沙盒读存操作主要是增、删、查&#xff0c;一般不涉及改的操作&#xff0c;这里直接以代码演示 常用代码&#xff1a; 增 /*** 存储缩略图到沙盒中*/ (BOOL)saveImageToPath:(NSString *)imageFilePath image:(UIImage *)image{return [UIImageJPEG…