所以我有超过150,000张巨大的GeoTIFF图像(每张2.4 GB(,我需要运行图像平滑和边缘检测(LoG滤波器(才能获得锐化的图像。我使用 Gdal 读取图像,对其进行平滑处理、子采样,创建一个高通滤波器(级别 5(并重建图像。
这对于普通的.jpg文件工作正常。
但是对于一个巨大的 TIFF 文件,我无法完成此操作,因为即使使用 32 GB RAM 8 核心处理器和 4 TB 磁盘空间,我也会遇到内存错误。
在Python 3.6 Ubuntu 18 LTS上进行重量级图像处理/图像分割的最佳方法是什么?
pyvips 可以在很少的内存中快速处理巨大的图像。它是LGPL,运行在Linux,macOS和Windows上,适用于每个版本的Python。大多数Linux(包括Ubuntu(在包管理器中都有它。
它是一个需求驱动的流式图像处理库。它不是在单个巨大的块中处理图像,而是在您的背后构建一个图像处理运算符网络,并且像素通过创建输出的需要在小区域中通过计算机的内存拉动。
例如,我可以运行这个程序:
import sys
import pyvips
# access='sequential' puts pyvips into streaming mode for this image
im = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
im = im.crop(100, 100, im.width - 200, im.height - 200)
# 10% shrink, lanczos3 (by default)
im = im.resize(0.9)
mask = pyvips.Image.new_from_array([[-1, -1, -1],
[-1, 16, -1],
[-1, -1, -1]], scale=8)
# integer convolution ... you can use large float masks too, canny,
# sobel, etc. etc.
im = im.conv(mask, precision='integer')
im.write_to_file(sys.argv[2])
在 40k x 30k 像素的 GeoTIFF 图像上:
$ vipsheader SAV_X5S_transparent_mosaic_group1.tif
SAV_X5S_transparent_mosaic_group1.tif: 42106x29852 uchar, 4 bands, srgb, tiffload
在这台2015年的笔记本电脑上,运行方式如下:
$ /usr/bin/time -f %M:%e python3 bench.py SAV_X5S_transparent_mosaic_group1.tif x.tif
257012:101.43
即 260MB 的内存,101 秒的经过时间。在您的大型机器上,它应该会快得多。
您可能遇到的一个问题是 GeoTIFF 标签:它们不会被 pyvips 保留。也许您在以后的处理中不需要它们。
通常,此类大图像是按图块处理的。这个想法是将图像分成几个图块,独立读取每个图块,有足够的"重叠"来考虑应用的过滤,处理它并将其写入文件。
TIFF标准知道"平铺"格式(我相信GeoTIFF文件通常以平铺格式存储(。此格式经过明确设计,使其易于在图像的小窗口中阅读,而无需将整个文件中的零碎内容拼凑在一起。TIFF 文件中的每个切片都可以按位置编制索引,并独立编码和压缩,因此一次可以轻松读入和写出一个切片。
所需的重叠取决于应用的筛选。例如,如果您应用具有 9x9 窗口(超过中心像素 4 像素(的高斯拉普拉斯滤波器,然后重叠只需要 4 个像素。如果链接筛选器,通常需要添加每个筛选器的覆盖范围以获得总重叠值。
接下来,将图像划分为 TIFF 文件中磁贴大小的若干倍数。假设文件具有 512x512 像素的磁贴。您可以选择一次处理 8 个图块,该区域为 2048x2048 像素。
现在在每个维度上以 2048 为步长循环图像。读取 8 个图块,并包括相邻的图块,您将对其进行裁剪,以便获得 2048+2*4 像素的正方形图像。处理子图像,删除重叠区域,并将其余部分写入输出 TIFF 文件中的相应图块。输出 TIFF 文件的设置方式应与输入 TIFF 文件相同。
我确信有软件可以自动化这个过程,但我不知道 Python 中有任何软件。如果您自己实现这一点,则需要学习如何在 TIFF 文件中读取和写入单个磁贴。一种选择是pylibtiff。