I recently came across this short fun post on R-bloggers that demonstrated how to use the
image.ContourDetector package (available on CRAN) to extract contours from an image. The image of the contours looked really cool so I thought I would try it out for myself!
As an example, I wanted to extract the contours from the image below:
Here is the code taken from the R-bloggers post (slightly modified):
library(magick) library(image.ContourDetector) img_path <- paste0("https://resources.premierleague.com/premierleague/", "photo/2018/11/27/d7e922c7-8e8e-4eff-b1c1-1a6678295257/", "EPL-Instagram-Article.png") img <- magick::image_read(img_path) mat <- magick::image_data(img, channels = "gray") mat <- drop(as.integer(mat, transpose = TRUE)) contourlines <- image_contour_detector(mat) plot(contourlines)
And here is the result. Not bad for a little chunk of code!
Not bad, but can we do better? In particular, we can’t really see any of the facial features of the players.
It turns out that the
image_contour_detector() function has a function option
Q, which (according to the documentation) represents “numeric value with the pixel quantization step”. This is discussed in Section 5 of the paper introducing the method. My high-level understanding of the issue is that in digital image processing, the pixel values are usually quantized to integers while the algorithm was designed to work on pixels with real values. As a result, the algorithm can produce some artifacts. The paper gives the figure below as an example:
… I actually like the artifacts! The default value of the parameter is
Q = 2. To get more contours, we could set
Q = 0, i.e. change the second-last line above to
contourlines <- image_contour_detector(mat, Q = 0) plot(contourlines)
I think it’s a bit better! Here are the contours for 3 different Q values, placed side by side: