Wednesday, February 8, 2017

Sampling Points Proportional to Intensity in an Image

A few months ago Aaron Lun shared some code with me to sample points based on intensity of pixels in an image. With his permission, I thought it would be fun to share it here!

The idea is you start with some image (either in a JPEG or PNG format). Here I'm using Rafa's twitter profile picture in a JPEG format.

I'm using the readJPEG() function from the R jpeg package to read in the JPEG image. Alternatively, you can use the readPNG() function from the R png package to read in a PNG image. If you read the help file of readJPEG(), it says it "reads an image from a JPEG file/content into a raster array". OK, first off what do we mean by raster? You can think of a raster image as a rectangular grid of pixels. In the help file for the readJPEG() function, it states "most common files decompress into RGB channels (3 channels)" where RGB stands for red, green and blue.

So, this means for each pixel in the original image, we should expect 3 values (one for red, green and blue). These values range between 0 and 1 and can be thought of the intensity of each color in the image. Below, I'm showing the intensity values from the three channels colored on the same scale (top row) and colored in the red, green and blue scales (bottom row).

To get the intensity of how light a particular pixel is, we can just average the values across the three channels. Next, we flip the intensity scale by subtracting the intensity scale from 1 to see how dark/black a particular pixel is. This makes the previously dark areas now light and vice versa (top left figure below). To control the contrast of intensity, you can just take powers of the intensity values. The lighter the background, the better the contrast will be between the individual and background on the original scale. Depending on the background in the original image, the skin tone, etc you may need to tinker with the contrast. I've shown the original scale and powers of 2, 4, and 8 below.

Next, we sample points proportional to the (powered) intensity level, add a bit of random noise and then plot the sample points along the x and y axis. In the picture below, you can really see how the power is very important to control the contrast levels.

Happy sampling!


  1. Is there a reason you'd want to sample based off an image? What information would you have that's stored in the form of an image?

    1. I came across this as a fun way to make a caricature from a picture of someone. :p On a more scientific note, I can imagine something like in neuroimaging you may be interested in sampling points from the intensity as a form of simulation, but then again I don't work in that area.