此文档主要是记录图像与二进制互相转换的方法,此文档记录于20220811
进行图片和二进制的互相转换
若想转为base64,可以看 图像与base64互转 的内容。
资料:python 图片和二进制转换的三种方式_脸不大的CVer的博客-CSDN博客_python 二进制转图片
环境: python 3.8
import cv2
import numpy as np
import base64
def imgTobyte_cv2(img, img_type="jpg"):
'''
将opencv 读取的图像(numpy矩阵)转为二进制格式
:param img opencv 读取的BGR图像
:param img_type 图片的原始后缀, 如 jpg/jpeg/png等
:return 图像的base64编码字符,不带base64头的
'''
# 对数组的图片格式进行编码
# success, encoded_image = cv2.imencode(f".{img_type}", img)
encode_image = cv2.imencode(f".{img_type}", img)[1] # 用cv2压缩/编码,转为一维数组
byte_data = encode_image.tobytes() # 转换为二进制
return byte_data
def byteToImg_cv2(byte_data):
'''
将二进制格式图像转为opencv图像
:param byte_data 传入为BGR格式下的二进制数据
:reurn 传出BGR格式的numpy矩阵
'''
encode_image = np.asarray(bytearray(byte_data), dtype="uint8") # 二进制转换为一维数组
img_array = cv2.imdecode(encode_image, cv2.IMREAD_COLOR) # 用cv2解码为三通道矩阵
return img_array
if __name__ == '__main__':
img_type = "jpg"
img_path = "../imgs/car.jpg"
img_cv2 = cv2.imread(img_path)
byte_cv2 = imgTobyte_cv2(img_cv2, img_type)
img_cv2_new = byteToImg_cv2(byte_cv2)
cv2.imshow("img_cv2", img_cv2)
cv2.imshow("img_cv2_new", img_cv2_new)
cv2.waitKey(0)
from io import BytesIO
from PIL import Image
def imgToByte_PIL(image, img_type="jpeg"):
# 输入为PIL读取的图片,输出为base64格式
byte_data = BytesIO()# 创建一个字节流管道
image.save(byte_data, format=img_type)# 将图片数据存入字节流管道,format按照具体文件的格式填写
byte_data = byte_data.getvalue()# 从字节流管道中获取二进制
return byte_data
def byteToImg_PIL(byte_data):
# 输入为base64格式字符串,输出为PIL格式图片
image = Image.open(BytesIO(byte_data)) # 将二进制转为PIL格式图片
return image
if __name__ == '__main__':
img_type = "jpeg" ##jpg需要使用jpeg的后缀
img_path = "../imgs/car.jpg"
img_pil = Image.open(img_path)
byte_data_pil = imgToByte_PIL(img_pil, img_type)
img_pil_new = byteToImg_PIL(byte_data_pil)
img_pil.show("img")
img_pil_new.show("img_new")
import cv2
import numpy as np
def imgFileToByte(img_path):
'''
本地图片转为二进制数据
:param path 本地图像路径
:return 图像的base64数据, 格式为str
'''
with open(img_path,"rb") as f: ##以二进制方式读取图像文件
byte_data = f.read()
return byte_data
def byteToImgFile(img_byte_data, save_path):
'''
二进制数据保存为本地图片
:param img_byte_data 图像的二进制数据
:param save_path 保存的图像路径
'''
# 将图片保存为文件
with open(save_path, 'wb') as f:
f.write(img_byte_data)
f.close()
def readByteFromTxt(txt_path):
'''
从txt文件读取图像的二进制数据
'''
with open(txt_path, 'rb') as f: ##以二进制方式读
img_type = f.read()
return img_type
def saveByteToTxt(img_byte_data, txt_path):
'''
将图像的二进制数据写到TXT文件中
'''
with open(txt_path, 'wb') as f: ##以二进制方式写
f.write(img_byte_data)
f.close()
def byteToImg_cv2(byte_data):
'''
将二进制格式图像转为opencv图像
:param byte_data 传入为BGR格式下的二进制数据
:reurn 传出BGR格式的numpy矩阵
'''
encode_image = np.asarray(bytearray(byte_data), dtype="uint8") # 二进制转换为一维数组
img_array = cv2.imdecode(encode_image, cv2.IMREAD_COLOR) # 用cv2解码为三通道矩阵
return img_array
if __name__ == '__main__':
img_type = "jpg"
img_path = "../imgs/car.jpg"
byte_data = imgFileToByte(img_path)
img_new_path = "/d/byte.jpg"
img_cv2_new = byteToImgFile(byte_data, img_new_path)
txt_path = "/d/byte.txt"
saveByteToTxt(byte_data, txt_path)
byte_data_new = readByteFromTxt(txt_path)
img = byteToImg_cv2(byte_data_new)
cv2.imshow("img", img)
cv2.waitKey(0)
//
// Created by fwq on 2023/7/20.
//
#include
#include
#include "opencv2/opencv.hpp"
/**
* cv::Mat转二进制;二进制转cv::Mat;二进制保存为文件;读取二进制文件转cv::Mat都测试成功
*
* ps1:这里转为的二进制都以std::vector存储, 其余的 std::vector/std::vector 等其实都是一样的
*/
/*
* 将二进制图像转为cv::Mat
*/
cv::Mat binaryImageToCvMat(std::vector<uchar>& binaryImage)
{
// 这里根据需要选择flags, 详细的自己看
// BGR图像都是cv::IMREAD_COLOR
// gray图像是:cv::IMREAD_GRAYSCALE
cv::Mat img = cv::imdecode(binaryImage, cv::IMREAD_COLOR);
return img;
}
/**
* 将cv::Mat 图像转为二进制数据
* @param img cv::Mat图像
* @param imgType 编码的图像格式
* @return
*/
std::vector<uchar> cvMatToBinaryImage(cv::Mat& img, const std::string &imgType = "jpg")
{
assert(!img.empty());
assert(imgType == "jpg" || imgType == "png" || imgType == "jpeg" || imgType == "bmp");
std::string img_data;
std::vector<uchar> vecImg;
std::vector<int> vecCompression_params;
vecCompression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
vecCompression_params.push_back(50); //值越大,编码质量越高
// 若不需要设置编码方式,直接去掉vecCompression_params即可。
cv::imencode("." + imgType, img, vecImg, vecCompression_params);
// cv::imwrite("/d/50-50-2r.jpg", img, vecCompression_params); //将图片vecCompression_params处理后的数据保存为图像
return vecImg;
}
/**
* 将编码后的二进制图像数据写入文件中
* @param binaryImage
* @param file_name
* @return
*/
bool saveBinaryImageTofile(std::vector<uchar>& binaryImage, std::string file_name)
{
// 将编码后的数据写入文件
std::ofstream outputFile(file_name, std::ios::binary);
if (!outputFile) {
return false;
}
outputFile.write(reinterpret_cast<const char*>(binaryImage.data()), binaryImage.size());
outputFile.close();
return true;
}
/**
* 读取图像二进制数据生成的二进制文件,并转为cv::Mat
* @param file_name
* @return
*/
cv::Mat binaryFileToCvMat(const std::string& file_name)
{
std::ifstream inputFile(file_name, std::ios::binary);
if (!inputFile) {
return cv::Mat(); // 返回空的cv::Mat对象表示失败
}
// 获取文件大小
inputFile.seekg(0, std::ios::end);
std::streampos fileSize = inputFile.tellg();
inputFile.seekg(0, std::ios::beg);
// 读取文件数据到缓冲区
std::vector<uint8_t> buffer(fileSize);
inputFile.read(reinterpret_cast<char*>(buffer.data()), fileSize);
inputFile.close();
// 将二进制数据解码为cv::Mat对象
cv::Mat image;
image = cv::imdecode(buffer, cv::IMREAD_COLOR); // 或者使用cv::IMREAD_GRAYSCALE,取决于图像的颜色格式
return image;
}
int main()
{
std::string img_path = "/home/fwq/Projects/MyGiteeProjects/MyCppOpenCVStudy/test_files/1.jpg";
cv::Mat img = cv::imread(img_path);
std::vector<uchar> binaryImage = cvMatToBinaryImage(img);
cv::Mat new_img = binaryImageToCvMat(binaryImage);
std::string save_file = "/home/fwq/Projects/MyGiteeProjects/MyCppOpenCVStudy/test_files/1.bin";
bool ret = saveBinaryImageTofile(binaryImage,save_file);
if (!ret)
{
std::cout << "保存编码文件失败\n";
return 0;
}
cv::Mat new_img2 = binaryFileToCvMat(save_file);
if (new_img2.empty())
{
std::cout << "读取编码文件转cv::Mat失败\n";
return 0;
}
cv::imshow("src_img", img);
cv::imshow("new_img", new_img);
cv::imshow("new_img2", new_img2);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}