[update: imager is now on CRAN. install via install.packages(“imager”)]
I’ve written a package for image processing in R, with the goal of providing a fast API in R that lets you do things in C++ if you need to. The package is called imager, and it’ on Github.
The whole thing is based on CImg, a very nice C++ library for image processing by David Tschumperlé.
Features:
- Handles images in up to 4 dimensions, meaning you can use it for volumetric/hyperspectral/data or short videos
- Facilities for taking subsets of images, pixel neighbourhoods, etc.
- All the usual image processing stuff (filters, morphology, transformations, interpolation, etc.)
- Easy access to the C++ API via Rcpp
The package is still in an early phase but it can already do a lot of useful things as you’ll see from the documentation.
Example code:
library(imager) im <- load.image(system.file('extdata/parrots.png',package='imager')) layout(t(1:3)) plot(im,main="Original image") grad <- grayscale(im) %>% get_gradient("xy") names(grad) <- paste("Gradient along",c("x","y")) l_ply(names(grad),function(n) plot(grad[[n]],main=n))
Visit the website for more information.
nice work, thanks!
Random tip: use setNames to keep your piping mojo flowing, ie. Instead of
x %
that(y)
names(x) <- z
do
x %
that(y) %>%
setNames(z)
🙂
Yikes, either iPhone typo or the comment box doesn’t like the first assignment operator, take 2 with “=”
x = this(x) %>%
that(y) %>%
setNames(z)
Much nicer, thank you Steve!
Nice project, Simon (Hans just told be about it)! Works beautifully, as does imagerstreams–first time that I’ve seem live video in R. I noticed that the latter is wrapping small parts of OpenCV. Any plans on extending it?
Thanks Jochen, glad you like it. It’s definitely possible to wrap larger parts of OpenCV, I’ll do it if the need arises. The problem with OpenCV is that the API is a lot messier than CImg’s, and it’s hell to install on non-Linux systems. Ideally I’d have to find a way of providing a package with statistically-linked binaries, and it sounds like a lot of work.
Well, installing and using your packages worked fine on my Mac, using OpenCV 3.0 which I had previously installed from source for some other project… I just checked, and it is now also available from Homebrew and MacPorts, so installing should be easy.
You could try hosting it on github and declare it as experimental–use at your own risk, no installation support. But it would be very nice to see some of, e.g., features2D wrapped. I agree that it would be quite some effort, but you seem to be on the right track.
I didn’t know features2D, you’re right, it does look useful and CImg doesn’t provide any of these algorithms directly.
Hi Simon,
I’m coming late to the party. I just discovered this package after working hard on building my own computer vision library for R (on Github here https://github.com/swarm-lab/videoplayR and vignette on Rpubs here http://rpubs.com/sjmgarnier/videoplayR). It’s a lot less developed than imager but I was planning on adding more and more features to it as the needs of my lab develop… until I found out about your package.
I briefly tested imager yesterday to see if it could suit our needs. I must say that I’m very impressed by the richness of the package and its ease of use. However I ran into a little problem when trying to process videos. It seems that imager loads all the video frames in memory, which takes a very long time if the video is a bit big (I tried loading a 20 minutes long HD video with the load.image function, it was still not done after 5 minutes). I wanted to know if there was another option to work with videos that would not require loading all the frames in memory. For instance, the package that I developed creates wrappers around OpenCV VideoCapture pointers, which means that I don’t need to load the video in memory to grab individual frames from it (the disadvantage being that these are not typical R objects and I need to write all the methods to manipulate them in C++ instead of using all the R goodies).
I took a quick look at your source code, and it seems that you load the videos in a special R object, which is essentially a big array if I’m not wrong. This would explain why it would be difficult to process HD videos that are more than a few minutes long, but maybe I missed something.
Anyway, your package is really impressive. If the “off-R-memory video processing” thing is not something that can easily be solved on your end, your package will certainly be a source of inspiration for me to implement more advanced functions in my package.
Cheers,
Another Simon
Hi Simon! It’s a pity, looks like there’s been some duplication of effort indeed. You’re right, imager loads everything into memory, that puts a strong limit on how much video it can process. I have another package that enables frame-by-frame video processing, it’s here:
https://github.com/dahtah/imagerstreams
I haven’t advertised it much because it’s experimental but it’s the same idea you’ve had (use OpenCV to grab frames, interface with Rcpp). I’m getting in touch by email so we can coordinate better in the future.
Also very late to the party and thanks to other Simon for pointing this library out. I’ve been playing with imager this week and it seems really nice. I mainly use ImageJ for image processing, but I process all my data in R. I ran your pmax/pmin example and upped the neighborhood for fun and it did take a while to process, but I have a quad-core chip and only a single processor was doing anything (R’s fault mostly, it wasn’t written with that in mind). Is it possible to use foreach or other multicore-ready processing steps to process the filtering steps.
I have a few more questions as well. One of the great things about ImageJ is that there’s an interface and you can tune settings on the fly and preview the results. Is this possible with imager? Related, could you create a script that allows you to interact with a filter or threshold live, then submit for further processing, or do you need a fully automated pipeline?
I notice you’re using alply a lot, is there no dplyr equivalent?
You could build your own GUI around imager using Shiny.
Glad you like imager!
Parallelisation: CImg supports it (with pthreads), so it could be enabled with just a compiler flag. I’ve yet to experiment with it, to be honest. You can parallelise things on the R side of things as well, using the usual tricks. Not sure the max-filter is easy to parallelise in pure R, though. Under the hood it uses the pmax function which is trivial to parallelise, but I don’t think R’s version supports it.
Generally speaking if speed is paramount I’d recommend calling CImg’s API directly, which is very easy to do if you know some C++. I have a example here.
GUIs: I agree with Simon, Shiny looks pretty good.
Plyr: alply is a plyr function, do you mean apply?
Hey, I found this package very useful for my school project. I have successfully installed it but it couldn’t load when I tried loading it using library(imager). Please is there a solution to this problem? I am using mac OS 10.11.6
Hi Henry. You need to tell me more about the problem – what error message are you seeing?