图像处理之PCA(C++)

图像处理之PCA(C++)


文章目录


前言

在科研、工程应用中,我们往往所获取的数据都包含着很多冗余的信息,这些冗余的信息会对我们分析数据造成干扰。因此,我们可以采用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)

二、代码实现

cpp 复制代码
#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行的矩阵P
	cv::Mat kMat;
	eigenVectors(cv::Rect(0, 0, eigenVectors.cols, k)).copyTo(kMat);


	// 6.获得降维后的矩阵Y
	cv::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;

	//自己实现的pca
	cv::Mat pca_dst;
	int k = 100;	//降维后维度
	do_pca(src, pca_dst, k);

	//opencv实现的pca
	cv::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

opencv实现的pca


总结

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

本文代码均已经在本地运行成功,欢迎阅读交流。

相关推荐
Dongsheng_20192 分钟前
【汽车篇】AI深度学习在汽车零部件外观检测——刹车片中的应用
人工智能·汽车
LONGZETECH3 分钟前
【龙泽科技】汽车转向悬架与制动安全系统技术1+X仿真教学软件(1.2.3 -初级)
人工智能·科技·汽车·汽车仿真教学软件·汽车教学软件
JAVA学习通11 分钟前
PostgreSQL 的 hstore、arrays 数据类型
人工智能·自然语言处理
·心猿意码·33 分钟前
C++Lambda 表达式与函数对象
开发语言·c++
AKAMAI1 小时前
云成本困境:开支激增正阻碍欧洲AI创新
人工智能·云原生·云计算
大模型真好玩1 小时前
LangGraph实战项目:从零手搓DeepResearch(一)——DeepResearch应用体系详细介绍
人工智能·python·mcp
IT古董1 小时前
【第五章:计算机视觉-项目实战之生成式算法实战:扩散模型】3.生成式算法实战:扩散模型-(4)在新数据集上微调现有扩散模型
人工智能
嵌入式-老费1 小时前
Easyx图形库使用(潜力无限的图像处理)
图像处理·人工智能
JXY_AI2 小时前
AI问答与搜索引擎:信息获取的现状
人工智能·搜索引擎
B站_计算机毕业设计之家2 小时前
Python+Flask+Prophet 汽车之家二手车系统 逻辑回归 二手车推荐系统 机器学习(逻辑回归+Echarts 源码+文档)✅
大数据·人工智能·python·机器学习·数据分析·汽车·大屏端