rosscova rosscova - 11 months ago 53
R Question

Read image data into R piece-by-piece

I'm working with some fairly large image files (aerial survey mosaics, generally > 1 billion pixels), such that loading an entire image into memory would be a problem on my system. I would like to bring them into R piece-by-piece, such that I can process them in "grid-wise" sections.

NOTE: I'm not tied to a particular image format, so

etc would all be fine as inputs.

I can do something along these lines with
, but this requires loading the entire file into memory first, so it doesn't really solve my problem, but hopefully shows what I'm trying to achieve.

image.file <- "~/Desktop/penguins.jpg"

grid.size <- 100
v <- 3
h <- 1

library( jpeg )
image <- readJPEG( image.file )[ (v-1)*grid.size+1, (v)*grid.size, 1 ), (h-1)*grid.size+1, h*grid.size, 1 ), ]

The above loads in only a sample of the image, designated by
, and
, such that it would be easy to build this into a loop to analyse an image in sections.

Is it possible to achieve this without loading the entire image into memory? Something like
, making use of the
parameters would be reasonable (it would at least only load the vertical sections one at a time, so much less memory needed than

Answer Source

If you have ImageMagick installed, you can crop the image from the command line before reading it into R. An example using this image:

To create the cropped image:

x <- 800  ## x and y are offsets
y <- 400
w <- 200  ## width and height of cropped image
h <- 100
filename <- "worldpoliticallarge.jpg"
outname <- "crop.jpg"
cmd <- sprintf("jpegtran -crop %dx%d+%d+%d -copy none %s > %s", w, h, x, y, filename, outname)

Check to see if the new image contains the region we want:

original <- readJPEG(filename)
cropped <- readJPEG(outname)
all.equal(original[(y+1):(y+h), (x+1):(x+w), ], cropped)
# [1] TRUE