OpenCv_C++-PCA原理与应用

主成分分析PCA,最主要在数据处理中用来降维,比如说我们有1000组数据,每组数据有1000个样本,我们通过分析每组数据中的主要特征,剔除那些不必要的特征,使得数据的维度有所减少,以加快计算机计算的速度。进行PCA变化时主要有以下特征:
1、主成分不变;
2、有细微损失;
3、高维数据到低维数据。

进行PCA降维的主要步骤如下:
OpenCv_C++-PCA原理与应用_第1张图片
上图中的步骤比较抽象,其实就是经过一步步的矩阵运算得到最终的新的数据。具体公式如下:
OpenCv_C++-PCA原理与应用_第2张图片

实例代码:

#include
#include

using namespace cv;
using namespace std;

double calcPCAorientation(Mat &image, vectorpts);
int main(int argc, char** argv)
{
	Mat src = imread("D:/test/pca_test1.jpg");
	if (src.empty())
	{
		cout << "图片未找到..." << endl;
		return -1;
	}

	imshow("input image", src);
	Mat gray, binary;
	//转为灰度图
	cvtColor(src, gray, COLOR_BGR2GRAY);
	//转为二值图
	threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);//自动获取阈值
	imshow("binary image", binary);
	vector>contours;//存储轮廓点信息
	vectorhierachy;
	//轮廓发现
	Mat result = src.clone();
	findContours(binary, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE,Point());
	for (size_t t = 0; t < contours.size(); t++)
	{
		double area = contourArea(contours[t]);
		if (area > 100000 || area < 100)  //如果面积大于100000或小于100,则过滤掉该面积轮廓
			continue;
		drawContours(result, contours, t, Scalar(0, 0, 255), 2, 8);
		double theta = calcPCAorientation(result, contours[t]);
	}

	imshow("contours image", result);
	waitKey(0);
	return 0;
}

double calcPCAorientation(Mat & image, vector pts)
{
	int size = static_cast(pts.size());//获取数据点个数
	Mat data_pts = Mat(size, 2, CV_64FC1);//定义一个n行2列的矩阵

	for (int i = 0; i < size; i++)
	{
		data_pts.at(i, 0) = pts[i].x;//矩阵的第一列数据
		data_pts.at(i, 1) = pts[i].y;//矩阵的第二列数据
	}

	//PCA分析处理
	PCA pca_analysis(data_pts, Mat(), PCA::DATA_AS_ROW);
	Point cnt = Point(static_cast(pca_analysis.mean.at(0, 0)),//求均值,第一列一行
		             static_cast(pca_analysis.mean.at(0, 1)));//第一列第二行

	
	circle(image, cnt, 2, Scalar(0, 255, 0), 2, 8, 0);
	vectoreigen_vectors(2);//2个特征向量
	vectoreigen_vals(2);//2个特征值

	for (int i = 0; i < 2; i++)
	{
		eigen_vals[i] = pca_analysis.eigenvalues.at(i, 0);
		eigen_vectors[i] = Point2d(pca_analysis.eigenvectors.at(i, 0),
			                     pca_analysis.eigenvectors.at(i, 1));
	
		cout << "第" << i << "个特征值为:" << eigen_vals[i] << endl;
		
	}
	
	Point p1 = cnt + 0.02*Point(static_cast(eigen_vectors[0].x*eigen_vals[0]), static_cast(eigen_vectors[0].y*eigen_vals[0]));
	Point p2 = cnt - 0.05*Point(static_cast(eigen_vectors[1].x*eigen_vals[1]), static_cast(eigen_vectors[1].y*eigen_vals[1]));
	double angle = atan2(eigen_vectors[0].y ,eigen_vectors[0].x); //反三角函数求角度
	cout << "偏转角度=" << angle*(180/CV_PI) << endl;
	cout << "-------------------------------" << endl;
	cout << "-------------------------------" << endl;
	line(image, cnt, p1, Scalar(255, 0, 0), 2, 8, 0);
	line(image, cnt, p2, Scalar(255, 125, 0), 2, 8, 0);
	/*
	cout << "cnt=" << cnt << endl;
	cout << "p1=" << p1 << endl;
	cout << "p2=" << p2 << endl;
	cout << "-----------------------" << endl;
	*/
	return 0;
}

运行结果:
OpenCv_C++-PCA原理与应用_第3张图片
OpenCv_C++-PCA原理与应用_第4张图片

你可能感兴趣的:(OpenCv-C++学习记录)