在 R 中只打开图像的一部分(JPEG/TIFF 等)

Open only part of an image (JPEG/TIFF etc.) in R

我正在用 R 分析非常大的图像,大约有数万像素见方。不幸的是,即使使用 64 GB RAM,这些图像有时也无法装入内存,而当它们装入内存时,我一次只能打开一个,从而无法并行化。

我目前的策略是使用 JPEG 或 TIFF 包加载它们。例如:

image <- readJPEG('image.jpg')

但是,由于我只执行可以逐个执行的简单数学操作(求和、阈值等),是否可以通过指定尺寸来一次只打开图像的一部分加载?如果是这样,我可以编写一个循环来打开 1024 x 1024 大小的图块。 JPEG 和 TIFF 包不提供执行此操作的选项。

如果您要处理非常大的图像,libvips 可能是您的最佳选择。您可以使用 system().

R shell 输出它

你的问题不是很具体,但让我们用 ImageMagick 制作一个 10,000x10,000 像素的 TIFF,它是一个黑白渐变:

convert -size 10000x10000 gradient: -depth 8 a.tif

现在 vips 将阈值设置为 50% 并检查所需的内存:

vips im_thresh a.tif b.tif 128 --vips-leak
memory: high-water mark 292.21 MB

很节俭,不是吗?相比之下,等效的 ImageMagick 命令需要 1.6GB 的 RAM:

/usr/bin/time -l convert a.tif -threshold 50% b.tif

示例输出

...
1603895296  maximum resident set size
...

使用 im_gadd 为每个像素添加 64 如何:

usage: vips im_gadd a in1 b in2 c out
where:
    a is of type "double"
    in1 is of type "image"
    b is of type "double"
    in2 is of type "image"
    c is of type "double"
    out is of type "image"
calculate a*in1 + b*in2 + c = outfile

所以我们使用:

vips im_gadd 1 a.tif 0 b.tif 64 c.tif --vips-leak
memory: high-water mark 584.41 MB

需要做一些统计吗?

vips im_stats c.tif
band    minimum     maximum         sum       sum^2        mean   deviation
all          64         319   1.915e+10 4.20922e+12       191.5     73.6206
 1           64         319   1.915e+10 4.20922e+12       191.5     73.6206

事实证明,有一个 R 包 - RBioFormats - 允许您指定正在打开的图像的一部分(尽管它在 CRAN 上不可用)。它可以从 Git 安装如下:

source("https://bioconductor.org/biocLite.R")
biocLite("aoles/RBioFormats") # You might need to first run `install.packages("devtools")`
library(RBioFormats)

无需打开图像即可从元数据中读取图像的尺寸:

metadata <- read.metadata('image.tiff')
xdim <- metadata@.Data[[1]]$sizeX
ydim <- metadata@.Data[[1]]$sizeY

假设我们要加载左上角的512 x 512像素,我们使用subset函数:

image <- read.image('image.tiff', subset = list(X = 1:512, y = 1:512))

据此编写一个循环来迭代处理整个大图像是微不足道的。 RBioFormats 是 Java BioFormats 库的 R 接口,可以打开 Tiff、PNG、JPEG 以及许多专有图像格式。