and*_*rei 4 image image-processing itk vips
我正在寻找一个能够读取图像文件(任何格式)的某个区域而无需首先读取整个图像文件的库(任何语言)。
我遇到过一些选项,例如 vips,它确实不会将整个图像保留在内存中,但似乎仍然需要从头开始完整读取它。
我意识到这可能不适用于 jpeg 等压缩格式,但理论上听起来 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
Run Code Online (Sandbox Code Playgroud)
wtc.png
(这四个数字分别是要裁剪并写入的区域的 left、top、width、height x.jpg
)
但是底部附近的 100x100 像素区域相当慢,因为它必须读取并解压缩您想要到达文件中正确点的像素之前的像素:
$ time vips crop wtc.png x.jpg 0 9000 100 100
real 0m3.063s
user 0m2.884s
sys 0m0.181s
Run Code Online (Sandbox Code Playgroud)
JPG 和 strip TIFF 的工作方式相同,但不太明显,因为它们是更快的格式。
某些格式支持真正的随机访问读取。例如,平铺 TIFF 在任何地方都很快,因为 libvips 可以使用 libtiff 只读取它需要的图块:
$ 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
Run Code Online (Sandbox Code Playgroud)
OpenSlide、vips、平铺 OpenEXR、FITS、二进制 PPM/PGM/PBM、HDR、RAW、Analyze、Matlab 以及其他一些可能都支持像这样的真正的随机访问。
如果您对更多细节感兴趣,API 文档中有一章描述了 libvips 如何打开文件:
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)
Run Code Online (Sandbox Code Playgroud)
这access=
是一个标志,提示 libvips 可以流式传输此图像,以防底层文件格式不支持随机访问。对于支持随机访问的格式(例如平铺 TIFF),不需要此选项。
您不需要写入文件。例如,这将创建一个包含编码为 JPG 的文件的缓冲区对象:
buffer = tile.write_to_buffer('.jpg', Q=85)
Run Code Online (Sandbox Code Playgroud)
或者这将直接写入stdout
:
target = pyvips.Target.new_from_descriptor(0)
tile.write_to_target('.jpg', Q=85)
Run Code Online (Sandbox Code Playgroud)
这Q=85
是一个可选参数,用于设置 JPG Q 因子。您可以设置任何文件保存选项。