6

I want to work with the magick package for its fantastic image manipulations capabilities. Looking through here I can't seem to find out how to convert a 3D matrix (width x height x channels) to a magick object I can further manipulate, and vice versa.

  • There is no as.magick function
  • The as.matrix function does not work

But I would like something like:

height <- 100
width <- 80
X <- array(runif(height * width * 3, min = 0, max = 255), c(height, width, 3))

magick::as.magick(X) %>% magick::image_scale("500x400")

(Obviously I could write the matrix to disk as an image, then read it with magick::image_read, that would be an overkill)

What did I miss?

Community
  • 1
  • 1
Giora Simchoni
  • 3,487
  • 3
  • 34
  • 72

1 Answers1

12

You can use image_read() to read a matrix as well. However note that the convention is to scale the values between 0 and 1 in case of doubles. So you need to divide your X by 255. Try this:

img <- magick::image_read(X / 255) %>% magick::image_scale("500x400")

If you want to convert the magick object back to an array:

image_data(img, 'rgba')

Or just img[[1]] works as well.

knb
  • 9,138
  • 4
  • 58
  • 85
Jeroen Ooms
  • 31,998
  • 35
  • 134
  • 207
  • O. M. G. Thanks! – Giora Simchoni Dec 03 '17 at 11:25
  • This conversion from magick to a numeric 3D matrix does not work any more with the code from this answer as far as I can tell because magick stores the pixel values as hexadecimals (from 00 to ff) instead of decimals. – Droplet Oct 19 '18 at 11:08
  • 1
    @droplet yes it does, R just shows raw data in hex notation when you print it to the terminal. You probably want to use `as.integer(img[[1]])` if you don't understand how to use raw vectors. – Jeroen Ooms Oct 19 '18 at 13:39
  • @Jeroen thanks. I would like to ask a follow-up question. After`as.integer(img[[1]])`, I further make it a data.frame by `img[[1]] %>% as.integer %>% melt %>% dcast(Var1+Var2~Var3, value.var="value)`. After I'd done the manipulation of the data, how can I reassemble it back to magick object? – Grec001 Oct 29 '18 at 11:49
  • @Jeroen Sorry, I don't get it. After the manipulation, the DATA turned into data.frame, but image_read is for the image files, and image_data is for magick object. Simply throw the data.frame into the `image_read()` seemed not working. – Grec001 Oct 29 '18 at 17:44
  • Yes you need to convert it back into a matrix shape first, and then `image_read()`. – Jeroen Ooms Oct 29 '18 at 23:11
  • considering read_image also does not handle grayscale images very well, the easiest way is to do a `writePNG(matrix)` first – ivan866 Oct 24 '20 at 22:44