opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

时间:2023-03-09 04:15:05
opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

本文部分内容转自  https://www.cnblogs.com/chaosimple/p/3182157.html

一、统计学概念

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

二、为什么需要协方差

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

三、协方差矩阵

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

注:上述协方差矩阵还需要除以除以(n-1)。MATLAB使用cov函数计算协方差时自动除以了(n-1),opencv使用calcCovarMatrix函数计算后还需要手动除以(n-1)

协方差具体计算

以学生成绩举例:有5名学生,参加数学、英语、美术考试,得分如图

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

1.计算均值矩阵M

均值是对每一列求平均值:means=【66,60,60】

则均值矩阵M为opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

2.原矩阵A-均值矩阵M=Y

Y=A-M=opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

3.Y转置×Y

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

4.最后将结果除以(n-1)

四、代码运行

1.MATLAB代码

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

2.opencv计算数字矩阵的协方差

#include<opencv2/opencv.hpp>
#include<iostream> using namespace cv;
using namespace std; void main()
{
Mat data = (Mat_<float>(, ) << , , , , , , , , , , , , , , );
cout << "data:" << endl << data << endl;
Mat covar1, means1;//协方差,均值
calcCovarMatrix(data, covar1, means1, CV_COVAR_NORMAL | CV_COVAR_ROWS);
cout << "---------------------------" << endl;
cout << "means:" << endl << means1 << endl;
cout << "covar:" << endl << covar1/ << endl;
getchar();
waitKey();//暂停按键等待
}

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

3.opencv计算图片的均值、标准差、协方差

(1)均值和标准差

#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std; void main()
{
Mat src = imread("E://1.jpg");
imshow("img", src); Mat means, stddev, covar;
meanStdDev(src, means, stddev);//计算src图片的均值和标准差
printf("means rows:%d,means cols %d\n", means.rows, means.cols);//RGB三通道,所以均值结果是3行一列
printf("stddev rows:%d,means cols %d\n", stddev.rows, stddev.cols); for (int row = ; row < means.rows; row++)
{
printf("mean %d = %.3f\n", row, means.at<double>(row));
printf("stddev %d = %.3f\n", row, stddev.at<double>(row));
}
  waitKey(0);
}

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

(2)均值和协方差

#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std; void show(Mat a,int i){
Mat covar, means;
calcCovarMatrix(a, covar, means, CV_COVAR_NORMAL | CV_COVAR_ROWS);//计算协方差,均值
cout << "mean " << i << " = " << means;
cout << "covar " << i << " = " << covar;
} void main()
{
Mat src = imread("E://1.png");
imshow("img", src); //通道分离
vector<Mat>channels;//定义Mat类型的向量
split(src, channels);//通道分离
//计算图片的协方差
show(channels.at(), );
show(channels.at(), );
show(channels.at(), ); waitKey();//暂停按键等待
}

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

之所以没用前面那张大图,是因为图片的协方差矩阵太大了,我随手画了个小图,输出都特别多

五、特征值和特征向量

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std; void main()
{
Mat data = (Mat_<double>(, ) <<
, ,
, ); //opencv求特征值和特征向量,输入矩阵必须是对称矩阵
Mat eigenvalue, eigenvector;
eigen(data, eigenvalue, eigenvector);
for (int i = ; i < eigenvalue.rows; i++)
cout << "eigen value " << i << " =" << eigenvalue.at<double>(i)<<endl;
cout << "eigen vector: "<< endl;
cout <<eigenvector<< endl; getchar();
}

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

当矩阵×2时,特征值翻倍,特征向量不变

opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量