C++, cv::Mat写入bin文件, 从bin文件读出cv::Mat

1. 将 cv::Mat 写入 bin 文件

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>

void saveMatToBinary(const cv::Mat& mat, const std::string& filename) {
	std::ofstream file(filename.c_str(), std::ios::binary);
	if (!file.is_open()) {
		std::cerr << "Error opening file for writing" << std::endl;
		return;
	}
	int rows = mat.rows;
	int cols = mat.cols;
	int type = mat.type();
	file.write((char*)&rows, sizeof(int)); // 在bin中写入第一个头信息 描述矩阵行数 占4个字节(即sizeof(int))
	file.write((char*)&cols, sizeof(int)); // 在bin中写入第二个头信息 描述矩阵列数 占4个字节(即sizeof(int))
	file.write((char*)&type, sizeof(int)); // 在bin中写入第三个头信息 描述矩阵类型(数据类型+通道数) 占4个字节(即sizeof(int))
	file.write((char*)mat.data, rows * cols * mat.elemSize()); // 在bin中写入矩阵数据
	file.close();
}

2. 从 bin 读出 cv::Mat 

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>

cv::Mat readMatFromBinary(const std::string& filename) {
	std::ifstream file(filename.c_str(), std::ios::binary);
	if (!file.is_open()) {
		std::cerr << "Error opening file for reading" << std::endl;
		return cv::Mat();
	}
	int rows, cols, type;
	file.read((char*)&rows, sizeof(int)); // 从bin中读出前4个字节(即一个int的字节数)的信息 以获悉矩阵行数
	file.read((char*)&cols, sizeof(int)); // 再从bin中读出4个字节(即一个int的字节数)的信息 以获悉矩阵列数
	file.read((char*)&type, sizeof(int)); // 再从bin中读出4个字节(即一个int的字节数)的信息 以获悉矩阵数据类型和通道数
	cv::Mat mat(rows, cols, type); // 根据头信息读出的内容 初始化一个尺寸、数据类型、通道数一定的矩阵
	file.read((char*)mat.data, rows * cols * mat.elemSize()); // 读出bin的剩余信息 装填矩阵
	file.close();
	return mat;
}

3. 关于字节数大小的意义(即bin的大小)

3.1 前置知识:mat.type()

已知一个cv::Mat mat, 通过 :

int type = mat.type();

 可以获悉该矩阵的通道数以及数据类型,如下表所示:

mat.type()结果和数据类型对应表 (部分)
数据类型C1 (单通道)C3(三通道)
CV_8U (uchar) type = 0type = 16
CV_32S (int)type = 4type = 20
CV_32F (float)type = 5type = 21
CV_64F (double)type = 6type = 22

附:对于大于4通道的多通道矩阵,基于其通道数和数据类型,也会有对应的type值

3.2 前置知识:mat.elemSize()

已知一个cv::Mat mat, 通过 :

int elemSize = mat.elemSize()

可以得到一个值, 它是“矩阵数据类型所占的字节数”“矩阵通道数”的乘积。

比如:

某cv::Mat矩阵是由float组成的,那么其数据类型为float,而一个float占的字节数是4;

再假设该矩阵是三通道的,那么该矩阵的 elemSize 等于 4 * 3 等于 12

3.3 前置知识:如何获悉矩阵的通道数

int channels = mat.channels();

3.4 前置知识:某数据类型所占的字节数

通过代码 sizeof(某数据类型) 来获取,以下为示例:

std::cout << "uchar 字节数 = " << sizeof(uchar) << std::endl; //uchar 字节数 = 1
std::cout << "int 字节数 = " << sizeof(int) << std::endl; //int 字节数 = 4
std::cout << "float 字节数 = " << sizeof(float) << std::endl; //float 字节数 = 4
std::cout << "double 字节数 = " << sizeof(double) << std::endl; //double 字节数 = 8

3.5 输出bin的大小是如何得出的

对于一个由cv::Mat转成的bin文件,其大小满足:

bin文件大小 (字节数) = 头信息字节数 + 矩阵数据字节数

  • 其中,头信息字节数根据bin写入方式的不同会有多种可能,如果使用我给的代码,则满足:

头信息字节数 = 12 (这是由于该头信息是用三个int值描述的,而一个int占4个字节)

  • 其中,矩阵数据字节数 = 矩阵行数 * 矩阵列数 * 矩阵数据类型字节数 * 矩阵通道数,即:

矩阵数据字节数 = mat.rows * mat.cols * mat.elemSize()

举例说明,如下图所示,是某输出的bin文件的大小,可以看到,其“大小”一栏中显示:1392字节

下面展示,生成该bin文件的代码:

int main() {
	cv::Mat mat = cv::Mat::zeros(5, 4, CV_64FC(12));
	saveMatToBinary(mat, "./Input/matrix.bin");  // 保存bin文件
	std::cout << "mat.elemSize()=" << mat.elemSize() << std::endl; // mat.elemSize()=96
	std::cout << "mat.type()=" << mat.type() << std::endl;  // mat.type()=94
	std::cout << "mat.rows=" << mat.rows << std::endl; // mat.rows=5
	std::cout << "mat.cols=" << mat.cols << std::endl; // mat.cols=4
	std::cout << "mat.channels()=" << mat.channels() << std::endl; // mat.channels()=12
	return 0;
}

由上述代码可知,该矩阵 mat 有 5412个通道,且数据类型是double(一个double占8个字节);再加上头信息由12个字节,因此:

12 + 5 *4 * 8 * 12 = 1932 个字节

  • 23
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值