使用 EBImage 或类似工具将 TIFF 中的单个帧加载到 R 中

Load a single frame from a TIFF into R with EBImage or similar

我正在用 R 分析一个 TIFF 文件。TIFF 只有一个 colour/channel,但它来自一部电影,大约有 1000 帧,因此非常大。我尝试使用以下命令和 EBImage 将图像数据作为矩阵加载到 R:

img <- readImage(file, as.is = TRUE)

但是计算机的 RAM 被巨大的文件完全超载,我收到以下错误消息:

Error: cannot allocate vector of size 22.4 Gb
In addition: Warning messages:
1: In readTIFF(x, all = all, ...) :
  TIFFReadDirectory: Unknown field with tag 50838 (0xc696) encountered
2: In readTIFF(x, all = all, ...) :
  TIFFReadDirectory: Unknown field with tag 50839 (0xc697) encountered
3: In array(unlist(arg.list, use.names = FALSE), dim = c(arg.dim[-along,  :
  Reached total allocation of 65170Mb: see help(memory.size)
4: In array(unlist(arg.list, use.names = FALSE), dim = c(arg.dim[-along,  :
  Reached total allocation of 65170Mb: see help(memory.size)
5: In array(unlist(arg.list, use.names = FALSE), dim = c(arg.dim[-along,  :
  Reached total allocation of 65170Mb: see help(memory.size)
6: In array(unlist(arg.list, use.names = FALSE), dim = c(arg.dim[-along,  :
  Reached total allocation of 65170Mb: see help(memory.size)

我建议的解决方案是创建一个循环,单独打开每个帧,执行并存储我的分析,然后移动到下一张图像。 EBImage 调用的 TIFF 包提供了仅打开第一帧 (all = FALSE) 的选项,但不打开自己选择的帧。有什么方法可以单独打开每个框架吗?

RBioFormats 提供了一种解决方案,可以只从较大的图像堆栈中读取选定的帧。它连接 BioFormats Java 库而不是 R 包 tiff。

从 GitHub、运行

安装包
# install.packages("devtools")
devtools::install_github("aoles/RBioFormats")

然后您可以使用 read.image()subset 参数来指定要读取的帧。结果对象是 class AnnotatedImage,如果 EBImage Image class,它是一个子class .有关详细信息,请参阅 package vignette,并查看以下子集方法的示例。

library(EBImage)
library(RBioFormats)

f <- system.file("images", "nuclei.tif", package="EBImage")

metadata <- read.metadata(f)

frames <- metadata$coreMetadata$sizeT

for(i in 1:frames) {
  frame <- read.image(f, subset=list(T=i))
  frame <- resize(frame, 128)
  display(frame)
}

我经常这样做。如果您使用 ffmpeg 将 1000 帧电影分成 1000 个 tiff 文件:

 ffmpeg -i $name_of_movie ./directory_of_tiff_frames/%04d.tiff

您可以像您所说的那样使用循环轻松地将每个 tiff 文件读入 R。我建议使用您已经安装的 TIFF 包,其中包含以下内容:

library(tiff)

## cd to the directory with the tiff files
setwd('./directory_of_tiff_frames')

## read in a character string of all the names of the frames
frames = list.files(pattern=*.tiff) ## in case there are non tiff files

i=1
while(i<=length(frames)) {
    ## read in the current frame
    cur.frame = readTIFF(frame[i])
    ## now you can perform any number of operations

    ## save your altered matrix as a .tiff 
    tiff('name_your_tiff_file')

    i=i+1
}