PCA主成分分析OpenCV中实现图片降维分类

OpenCV中使用PCA主成分分析,将图片降维分类。用很多张手写数字0-9演示。

首先,使用终端到工作目录输入:ls num/*.png > num.dat  得到num.dat文件(存储所有图片路径)

采用PCA降维后可以看到,没有标签的图片有了大致形状,通过结合标签学习,把分类图片映射到basis空间后的相似度用于识别数字。


#include 
#include 
#include 
#include 
#include 
#include 

using namespace cv;
using namespace std;

class MyPCA
{
public:
	vector featuresImg;
	Mat result;
	PCA pca;

	MyPCA(const string filename, int show = 0, int maxComponents = 10, const string winName = "Features") {
		this->show = show;
		this->maxComponents = maxComponents;
		this->winName = winName;

		// Read in the data. This can fail if not valid
		try {
			read_imgList(filename, images);
		}
		catch (cv::Exception& e) {
			cerr << "Error opening file \"" << filename << "\". Reason: " << e.msg << endl;
			exit(1);
		}
		// Quit if there are not enough images for this demo.
		if (images.size() <= 1) {
			string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
			CV_Error(Error::StsError, error_message);
		}

		data = formatImagesForPCA(images);
		// perform PCA
		pca = PCA(data, cv::Mat(), PCA::DATA_AS_COL, maxComponents);
		pca.project(data, result);
		showAllFeatures();
	}

	// show the result feature images
	void showAllFeatures() {
	        Mat img;

	        for(int i = 0; i < result.rows; i++){
                        img = result.row(i);
                        img = img.reshape(images[0].channels(), images[0].rows);
                        featuresImg.push_back(img);
	        }

		if (show){
			for (int i = 0; i < featuresImg.size(); i++){
				imshow(winName+(char)i, featuresImg[i]);
			}
		}
	}

	void test() {
	        cout << "Data size " << data.size() << endl;
	        cout << "Result size " << result.size() << endl;
	        cout << "Features size "< images;

	// Reshape and stack images into a rowMatrix
	Mat data;
	int maxComponents;
	int ch;
	int rows;
	string winName;

	void read_imgList(const string& filename, vector& images) {
		std::ifstream file(filename.c_str(), ifstream::in);
		if (!file) {
			string error_message = "No valid input file was given, please check the given filename.";
			CV_Error(Error::StsBadArg, error_message);
		}
		string line;
		while (getline(file, line)) {
			images.push_back(imread(line, 0));
		}
		cout << "Read success. " << images.size() << " pictures." << endl;
	}

	Mat formatImagesForPCA(const vector &data) {
		Mat dst(static_cast(data.size()), data[0].rows*data[0].cols, CV_32F);
		for (unsigned int i = 0; i < data.size(); i++)
		{
			Mat image_row = data[i].clone().reshape(1, 1);
			Mat row_i = dst.row(i);
			image_row.convertTo(row_i, CV_32F);
		}
		return dst;
	}

	Mat toGrayscale(InputArray _src) {
		Mat src = _src.getMat();
		// only allow one channel
		if (src.channels() != 1) {
			CV_Error(Error::StsBadArg, "Only Matrices with one channel are supported");
		}
		// create and return normalized image
		Mat dst;
		cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
		return dst;
	}
};


int main()
{
	string filename = "num.dat";
	MyPCA pca(filename, 1);
	pca.test();

	int key = 0;
	while (key != 'q')
		key = waitKey();

        //delete pca;
	return 0;
}

运行结果:

PCA主成分分析OpenCV中实现图片降维分类_第1张图片



你可能感兴趣的:(opencv)