我正在寻找一种库(任何语言都可以),它能够在不必读取整个图像文件的情况下,读取图像文件的一个区域。我已经发现了一些选项,例如vips,它确实不会将整个图像保存在内存中,但似乎仍然需要最初完全读取它。我知道对于压缩格式如jpg,这可能不可行,但理论上来说,bmp或tiff应该允许进行这种类型的读取。
libvips会尽可能地只读取需要的部分。例如,如果你从一个大的PNG文件中裁剪出左上角的100x100像素,它会很快:
$ time vips crop wtc.png x.jpg 0 0 100 100
real 0m0.063s
user 0m0.041s
sys 0m0.023s
$ time vips crop wtc.png x.jpg 0 9000 100 100
real 0m3.063s
user 0m2.884s
sys 0m0.181s
$ vips copy wtc.png wtc.tif[tile]
$ time vips crop wtc.tif x.jpg 0 0 100 100
real 0m0.033s
user 0m0.013s
sys 0m0.021s
$ time vips crop wtc.tif x.jpg 0 9000 100 100
real 0m0.037s
user 0m0.021s
sys 0m0.017s
http://libvips.github.io/libvips/API/current/How-it-opens-files.md.html
这是使用pyvips在Python中进行裁剪和保存:
import pyvips
image = pyvips.Image.new_from_file(input_filename, access='sequential')
tile = image.crop(left, top, width, height)
tile.write_to_file(output_filename)
access=
是一个标志,提示libvips可以流式传输该图像,以防底层文件格式不支持随机访问。对于支持随机访问的格式(如平铺式TIFF),您不需要这个标志。buffer = tile.write_to_buffer('.jpg', Q=85)
或者这将直接写入 stdout
:
target = pyvips.Target.new_from_descriptor(0)
tile.write_to_target('.jpg', Q=85)
Q=85
是设置JPG Q因子的可选参数。你可以设置任何文件保存选项。
vips
写入 stdout
而不是像上面的 x.jpg
那样写入磁盘文件? - Mark Setchellstdout
:vips jpegsave_mime x.tif
,但你不能在命令行上与裁剪结合使用。你需要运行两个命令(将裁剪保存到文件,然后将文件作为mime写入),或者使用类似Python的东西。 - jcupittvips crop x.png .jpg 0 0 10 10 | cat > x.jpg
将裁剪并将其作为 JPG 写入标准输出。 - jcupittITK可以使用一些格式进行操作。有一种方法CanStreamRead,对于支持流式传输的格式,如MetaImageIO,它返回true。一个例子可以在这里找到。您可以在ITK的论坛上提出更详细的问题。
BMP格式(未压缩)足够简单,您可以自己编写函数。
TIFF格式稍微有点难度,因为有很多子格式。但是TIFF库(TIFFlib)支持“瓦片导向”I/O模式。http://www.libtiff.org/libtiff.html#Tiles
我不知道有这样的库解决方案。
低级别的文件读取访问是格式特定的,尤其是文件映射是操作系统特定的。
如果您可以访问原始字节,则假设您知道宽度、高度、深度和通道数等,则计算文件偏移量很容易,因此只需自己编写代码即可。
如果您正在通过网络传输提取的数据,则在将其发送到网络之前,如果提取的ROI相对较大,则可以考虑在内存中压缩它。