我正在分析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以及许多专有成像格式。