具有应用功能的高效rbind替代品

时间:2018-08-23 17:30:58

标签: r image-processing

要退后一步,我的最终目标是将大约130,000张图像读入R,像素大小为HxW,然后制作一个数据帧/数据表,其中包含新行中每个图像的每个像素的rgb。所以输出将是这样的:

    > head(train_data, 10)
         image_no          r         g         b pixel_no
 1: 00003e153.jpg 0.11764706 0.1921569 0.3098039        1
 2: 00003e153.jpg 0.11372549 0.1882353 0.3058824        2
 3: 00003e153.jpg 0.10980392 0.1843137 0.3019608        3
 4: 00003e153.jpg 0.11764706 0.1921569 0.3098039        4
 5: 00003e153.jpg 0.12941176 0.2039216 0.3215686        5
 6: 00003e153.jpg 0.13333333 0.2078431 0.3254902        6
 7: 00003e153.jpg 0.12549020 0.2000000 0.3176471        7
 8: 00003e153.jpg 0.11764706 0.1921569 0.3098039        8
 9: 00003e153.jpg 0.09803922 0.1725490 0.2901961        9
10: 00003e153.jpg 0.11372549 0.1882353 0.3058824       10

我目前有一段代码可以执行此操作,在该代码中,我应用了一个函数来获取指定图像的每个像素的RGB,并在数据帧中返回结果:

#function to get rgb from image file paths
get_rgb_table <- function(link){

  img <- readJPEG(toString(link))

  # Creating the data frame
  rgb_image <- data.frame(r = as.vector(img[1:H, 1:W, 1]),
                          g = as.vector(img[1:H, 1:W, 2]),
                          b = as.vector(img[1:H, 1:W, 3]))
  #add pixel id
  rgb_image$pixel_no <- row.names(rgb_image)

  #add image id
  train_rgb <- cbind(sub('.*/', '',link),rgb_image)
  colnames(train_rgb)[1] <- "image_no"
  return(train_rgb)
}

我在另一个包含所有图像链接的数据框上调用此函数:

train_files <- list.files(path="~/images/", pattern=".jpg",all.files=T, full.names=T, no.. = T)
train <- data.frame(matrix(unlist(train_files), nrow=length(train_files), byrow=T))

火车数据帧如下:

> head(train, 10)
                               link
1  C:/Documents/image/00003e153.jpg
2  C:/Documents/image/000155de5.jpg
3  C:/Documents/image/00021ddc3.jpg
4  C:/Documents/image/0002756f7.jpg
5  C:/Documents/image/0002d0f32.jpg
6  C:/Documents/image/000303d4d.jpg
7  C:/Documents/image/00031f145.jpg
8  C:/Documents/image/00053c6ba.jpg
9  C:/Documents/image/00057a50d.jpg
10 C:/Documents/image/0005d01c8.jpg

我最终通过以下循环获得了想要的结果:

for(i in 1:length(train[,1])){
  train_data <- rbind(train_data,get_rgb_table(train[i,1]))
}

但是,这最后的代码效率很低。优化如何应用功能和/或rbind将会有所帮助。我认为函数get_rgb_table()本身很快,但是问题在于循环和rbind。我尝试使用apply(),但无法在每一行上都这样做,并且将结果放在一个数据帧中而不会耗尽内存。任何帮助都会很棒。谢谢!

1 个答案:

答案 0 :(得分:1)

鉴于问题的含糊不清,这很难回答,但我将举一个可重复的示例,说明我在想什么,并给出解决方案。

说我有一个返回数据帧的函数:

MyFun <- function(x)randu[1:x,]

我有一个数据框df,它将充当该函数的输入。

#     a  b
# 1   1 21
# 2   2 22
# 3   3 23
# 4   4 24
# 5   5 25
# 6   6 26
# 7   7 27
# 8   8 28
# 9   9 29
# 10 10 30

从您的问题来看,似乎只有一栏将用作输入。因此,我使用lapply将函数应用于此数据帧的每一行,然后使用do.callrbind将结果绑定在一起,如下所示:

do.call(rbind, lapply(df$a, MyFun))