将Numpy数组图像编码为图像类型(.png等),以便在没有OpenCV的GCloud Vision API中使用它

2024-06-16 08:43:02 发布

您现在位置:Python中文网/ 问答频道 /正文

在决定不使用OpenCV后,因为我只使用了其中的一个函数,所以我想用其他函数替换{}函数。目标是将2D Numpy数组转换为图像格式(如.png),并将其发送到GCloud Vision API。在

这是我到现在为止一直在用的东西:

content = cv2.imencode('.png', image)[1].tostring()
image = vision.types.Image(content=content)

现在我希望在不使用OpenCV的情况下实现同样的效果。

到目前为止我发现的事情:

  • Vision API需要base64编码数据
  • Imencode返回特定图像类型的编码字节

我认为值得注意的是,我的numpy数组是一个只有2维的二进制图像,所有函数都将在API中使用,因此避免将png保存到磁盘并重新加载。


Tags: 函数图像imagenumpyapi目标png图像格式
1条回答
网友
1楼 · 发布于 2024-06-16 08:43:02

纯Python中的PNG writer

如果您坚持使用或多或少纯python,那么下面的函数来自ideasman对this question的回答是有用的。在

def write_png(buf, width, height):
    """ buf: must be bytes or a bytearray in Python3.x,
        a regular string in Python2.x.
    """
    import zlib, struct

    # reverse the vertical line order and add null bytes at the start
    width_byte_4 = width * 4
    raw_data = b''.join(
        b'\x00' + buf[span:span + width_byte_4]
        for span in range((height - 1) * width_byte_4, -1, - width_byte_4)
    )

    def png_pack(png_tag, data):
        chunk_head = png_tag + data
        return (struct.pack("!I", len(data)) +
                chunk_head +
                struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head)))

    return b''.join([
        b'\x89PNG\r\n\x1a\n',
        png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
        png_pack(b'IDAT', zlib.compress(raw_data, 9)),
        png_pack(b'IEND', b'')])

将Numpy数组写入PNG格式的字节文本,编码为base64

为了将灰度图像表示为RGBA图像,我们将矩阵堆叠成4个通道并设置alpha通道。(假设你的二维数字阵列叫做“img”)。由于PNG坐标的工作方式,我们还垂直翻转numpy数组。在

^{pr2}$

测试编码是否正常工作

最后,为了确保编码正常,我们解码base64字符串并将输出作为“test”写入磁盘_输出.png". 检查这是否与您开始时使用的图像相同。在

with open("test_out.png", "wb") as fb:
   fb.write(base64.decodestring(data_enc))

备选方案:只需使用PIL

但是,我假设你是在使用一些库来真正地阅读你的图像?(除非您正在生成它们)。大多数用于读取图像的库都支持这种功能。假设您使用的是PIL,您也可以尝试以下代码片段(from this answer)。它只是将文件保存在内存中,而不是磁盘上,并使用它生成base64字符串。在

in_mem_file = io.BytesIO()
img.save(in_mem_file, format = "PNG")
# reset file pointer to start
in_mem_file.seek(0)
img_bytes = in_mem_file.read()

base64_encoded_result_bytes = base64.b64encode(img_bytes)
base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii')

相关问题 更多 >