在Python中保存1位深的二进制图像

时间:2018-05-10 07:50:08

标签: python image binary computer-vision png

我在Python中有一个二进制图像,我想将它保存在我的电脑中。 一旦存储在我的计算机中,我需要它是一个1位深的png图像。 我怎样才能做到这一点?我尝试使用PIL和cv2,但我无法以1位深度保存它。

3 个答案:

答案 0 :(得分:3)

我发现自己处于需要创建大量二进制映像的情况,并且对在线可用信息感到沮丧。由于这里和其他地方的答案和评论,我找到了可以接受的解决方案。 @Jimbo的评论是迄今为止最好的。以下是一些代码,可重现我对将二进制图像保存在python中的某些方式的探索:

加载库和数据:

from skimage import data, io, util #'0.16.2'
import matplotlib.pyplot as plt #'3.0.3'
import PIL #'6.2.1'
import cv2 #'4.1.1'
check = util.img_as_bool(data.checkerboard())

skimage中的棋盘图像尺寸为200x200。如果没有压缩,则作为1位图像,应以(200 * 200/8)5000字节表示。

要使用skimage保存,请注意,如果数据不是uint,则程序包将抱怨,因此进行转换。保存图像平均需要2.8毫秒,文件大小为408字节

io.imsave('bw_skimage.png',util.img_as_uint(check),plugin='pil',optimize=True,bits=1)

使用matplotlib,4.2毫秒和693字节文件大小

plt.imsave('bw_mpl.png',check,cmap='gray')

使用PIL 0.5毫秒和164字节文件大小

img = PIL.Image.fromarray(check)
img.save('bw_pil.png',bits=1,optimize=True)

使用cv2,也抱怨输入bool。尽管进行了png压缩,但以下命令占用0.4ms的时间,导致文件大小为2566字节。

_ = cv2.imwrite('bw_cv2.png', check.astype(int), [cv2.IMWRITE_PNG_BILEVEL, 1])

PIL显然是速度和文件大小最好的。

我当然错过了一些优化,欢迎发表评论!

答案 1 :(得分:1)

使用:

cv2.imwrite(<image_name>, img, [cv2.IMWRITE_PNG_BILEVEL, 1])

(这仍将使用压缩,因此在实践中它很可能每像素少于1位)

答案 2 :(得分:0)

如果您不加载png或其他任何格式,则该格式的行为确实合理,只需编写即可。然后,您的代码就不需要PIL或各种导入方法,也不需要任何麻烦的导入方法。

import struct
import zlib
from math import ceil


def write_png_1bit(buf, width, height, stride=None):
    if stride is None:
        stride = int(ceil(width / 8))
    raw_data = b"".join(
        b'\x00' + buf[span:span + stride] for span in range(0, (height - 1) * stride, stride))

    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, 1, 0, 0, 0, 0)),
        png_pack(b'IDAT', zlib.compress(raw_data, 9)),
        png_pack(b'IEND', b'')])

改编自: http://code.activestate.com/recipes/577443-write-a-png-image-in-native-python/(麻省理工学院)

通过阅读png规范: https://www.w3.org/TR/PNG-Chunks.html

请记住,buf的1位数据应像png规范在正常非隔行扫描模式(我们声明的那样)中那样从左向右写入。多余的数据填充最后一位(如果存在),并且步幅是编码扫描线所需的字节数。此外,如果您希望这些1位具有调色板颜色,则必须编写一个PLTE块并将其类型切换为3而不是0。