图像与二进制数据间的转换

概述

此文档主要是记录图像与二进制互相转换的方法,此文档记录于20220811

进行图片和二进制的互相转换
若想转为base64,可以看 图像与base64互转 的内容。

Python

资料:python 图片和二进制转换的三种方式_脸不大的CVer的博客-CSDN博客_python 二进制转图片

环境: python 3.8

– OpenCV图像(numpy数组)与二进制转换

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)

– PIL格式图像与二进制互转

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)

C++

– cv::Mat 转二进制 + 二进制转cv::Mat

//
// 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;
}

你可能感兴趣的:(算法代码块,算法,python,c++)