mnist文件解析(C语言)

本文介绍了一个C++ Demo,用于解析MNIST手写数字数据集,将归一化的图像信息解码并利用OpenCV保存为常规图像文件。源码可在GitHub找到,程序包括解码图像、解码图像对应的数值,以及将每个数值的20张图像合并成一个图像文件。运行此Demo需要Visual Studio 2012以上版本和OpenCV 2.4以上版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


点击查看 (人工智能) 系列文章


  mnist本身是将数字手写体图像,归一化后信息合成的文件,分训练集和测试集两部分,每部分包含图片和标签两个文件,本文使用C++写的Demo将文件解码,并通过opencv将数据存储为常规的图像文件。源码下载地址:https://github.com/zacSuo/mnist

  • t10k-images.idx3-ubyte
  • t10k-labels.idx1-ubyte
  • train-images.idx3-ubyte
  • train-labels.idx1-ubyte

使用说明

环境要求

  • visual studio 2012及以上版本
  • opencv 2.4及以上版本

配置

启动前先通过项目属性,设置本地opencv的路径。

执行结果

  在目录的两个文件夹,分别将测试集(test_images)和训练集(train_images)的图片保存到其中。

程序说明

解码图像

int read_Mnist(std::string filename, std::vector<cv::Mat> &vec)
{
	int number_of_images = 0;
	std::ifstream file(filename, std::ios::binary);
	if (file.is_open()) {
		int magic_number = 0;		
		int n_rows = 0;
		int n_cols = 0;
		file.read((char*)&magic_number, sizeof(magic_number));
		magic_number = ReverseInt(magic_number);
		file.read((char*)&number_of_images, sizeof(number_of_images));
		number_of_images = ReverseInt(number_of_images);
		file.read((char*)&n_rows, sizeof(n_rows));
		n_rows = ReverseInt(n_rows);
		file.read((char*)&n_cols, sizeof(n_cols));
		n_cols = ReverseInt(n_cols);

		for (int i = 0; i < number_of_images; ++i) {
			cv::Mat tp = cv::Mat::zeros(n_rows, n_cols, CV_8UC1);
			for (int r = 0; r < n_rows; ++r) {
				for (int c = 0; c < n_cols; ++c) {
					unsigned char temp = 0;
					file.read((char*)&temp, sizeof(temp));
					tp.at<uchar>(r, c) = (int)temp;
				}
			}
			vec.push_back(tp);
		}

		file.close();
	}
	return number_of_images;
}

解码图像对应数值

void read_Mnist_Label(std::string filename, std::vector<int> &vec)
{
	std::ifstream file(filename, std::ios::binary);
	if (file.is_open()) {
		int magic_number = 0;
		int number_of_images = 0;
		int n_rows = 0;
		int n_cols = 0;
		file.read((char*)&magic_number, sizeof(magic_number));
		magic_number = ReverseInt(magic_number);
		file.read((char*)&number_of_images, sizeof(number_of_images));
		number_of_images = ReverseInt(number_of_images);

		for (int i = 0; i < number_of_images; ++i) {
			unsigned char temp = 0;
			file.read((char*)&temp, sizeof(temp));
			vec[i] = (int)temp;
		}

		file.close();
	}
}

生成图像文件

int decodeDatabase(std::string filenameImages,std::string filenameLabels,std::string imagesPathSave)
{
	// read MNIST image into OpenCV Mat vector
	std::vector<cv::Mat> vec_train_images;
	int number_of_train_images = read_Mnist(filenameImages, vec_train_images);

	// read MNIST label into int vector
	std::vector<int> vec_train_labels(number_of_train_images);
	read_Mnist_Label(filenameLabels, vec_train_labels);

	if (vec_train_images.size() != vec_train_labels.size()) {
		std::cout << "parse MNIST train file error" << std::endl;
		return -1;
	}

	// save images
	int count_digits[10];
	std::fill(&count_digits[0], &count_digits[0] + 10, 0);

	for (int i = 0; i < vec_train_images.size(); i++) {
		int number = vec_train_labels[i];
		std::string image_name = GetImageName(number, count_digits);
		image_name = imagesPathSave + image_name + ".jpg";

		cv::imwrite(image_name, vec_train_images[i]);
	}
	return 0;
}

每个数值各选20张图像合并成一个图像文件

int mergeSomeImages()
{
	std::string images_path = ".././mnistFile/train_images/";
	int width = 28 * 20;
	int height = 28 * 10;
	cv::Mat dst(height, width, CV_8UC1);

	for (int i = 0; i < 10; i++) {
		for (int j = 1; j <= 20; j++) {
			int x = (j-1) * 28;
			int y = i * 28;
			cv::Mat part = dst(cv::Rect(x, y, 28, 28));

			std::string str = std::to_string(j);
			if (j < 10)
				str = "0000" + str;
			else
				str = "000" + str;

			str = std::to_string(i) + "_" + str + ".jpg";
			std::string input_image = images_path + str;

			cv::Mat src = cv::imread(input_image, 0);
			if (src.empty()) {
				fprintf(stderr, "read image error: %s\n", input_image.c_str());
				return -1;
			}

			src.copyTo(part);
		}
	}

	std::string output_image = images_path + "result.png";
	cv::imwrite(output_image, dst);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

具身小站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值