0

问题随之而来。有必要处理非常大的二进制图像(100000x100000 像素)。最初是使用 Qt 的 QImage 类完成的,它支持 Format_Mono 格式,将图像存储为每像素 1 位。总的来说,一切都很好,直到事实证明 QPainter 具有有限的光栅化器并且无法绘制尺寸更短(32767x32767)的图像,它只是被切断了。

我无法组合超过 32767x32767 的图像。然后,我开始仔细研究各个图书馆。据我了解,OpenCV 不支持这种格式。关于 ImageMagick,它支持将图像构建为每像素一位,并以相同的格式保存。然而,在处理图像时,仍然以每像素 8 位的形式存储,因此会出现 RAM 短缺。然后我决定尝试 CImg,但它不支持 1bbp 格式,据我了解:

一个实例图像的已用内存的总大小(以字节为单位)为 'width x height x depth x dim x sizeof (T)

其中sizeof(T)当然不能小于sizeof(char)...

有趣的是,QImage 原则上如何与它的 Format_Mono 格式一起工作,但老实说,我被源代码所困扰。

所以,我有下一个问题。是否有一个库实现了创建和使用二进制图像的能力,在这种情况下,它们真的以每像素 1 位的形式存储在 RAM 中?

4

1 回答 1

2

libvips可以处理巨大的 1 位图像。它将它们解包到每个字节一个像素进行处理,但它只将当前正在处理的图像部分保留在内存中,所以你应该没问题。

例如,这个小程序制作了一个 100,000 x 100,000 像素的黑色图像,然后从命令行将所有图像粘贴到随机位置:

#!/usr/bin/env python

import sys
import random

import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips

# this makes a 8-bit, mono image of 100,000 x 100,000 pixels, each pixel zero
im = Vips.Image.black(100000, 100000)

for filename in sys.argv[2:]:
    tile = Vips.Image.new_from_file(filename, access = Vips.Access.SEQUENTIAL)

    im = im.insert(tile,
                   random.randint(0, im.width - tile.width),
                   random.randint(0, im.height - tile.height))

im.write_to_file(sys.argv[1])

我可以像这样运行程序:

$ vipsheader wtc.tif 
wtc.tif: 9372x9372 uchar, 1 band, b-w, tiffload
$ mkdir test
$ for i in {1..1000}; do cp wtc.tif test/$i.tif; done
$ time ./insert.py x.tif[bigtiff,squash,compression=ccittfax4] test/*.tif
real    1m31.034s
user    3m24.320s
sys 0m7.440s
peak mem: 6.7gb

[]输出文件名上设置图像写入选项。在这里,我启用传真压缩并设置squash选项。这意味着应该将 8 位单波段图像压缩到 1 位以进行写入。

峰值内存结果来自于 RES 中的观察top。不幸的是,6.7gb 相当大,因为它必须为 1,000 个输入图像中的每一个保留输入缓冲区。

如果您使用平铺的 1 位 tiff,则可以删除该access =选项并使用需要随机访问的运算符,例如旋转。如果您尝试旋转条形 tiff,vips 将不得不将整个图像解压缩到一个临时磁盘文件,这可能是您不想要的。

vips 具有合理范围的标准图像处理运算符,因此您只需将它们粘合在一起即可做您想做的事情。如果需要,您可以在 C 或 C++ 中添加新的运算符。

为简洁起见,该示例使用 Python,但如果您愿意,可以使用 Ruby、PHP、C、C++、Go、JavaScript 或命令行。它带有所有 Linux 和 BSD,它在 homebrew、MacPorts 和 fink 上,还有一个 Windows 二进制文件。

于 2017-02-02T19:00:16.703 回答