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



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

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

image <- readJPEG('image.jpg')

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

如果您正在处理非常大的图像,libvips可能是您最好的选择。您可以使用system()R掏出它。

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

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

现在阈值为 50%,需要vips和检查内存:

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接口,将打开Tiffs,PNG,JPEG以及许多专有成像格式。

最新更新