Search code examples
rimagecolorsanalysisquantization

Color extraction, quantification and analysis from image in R


I would like to quantifying colors in an image. I work on the iridescence of nacre (mother of pearl), and I want to quantifying three colors (red, yellow and green) on this shell (for example on the right picture on the link above).

Iridescence of nacre

So, I had test some packages (imager, ImageMagick, EBImage...), but I don't really find something that help me.

Well, I would like to make color quantification on R, with circles. The area of ​​the primitive in pixel may be expressed as that of a circle of equivalent surface area. The primitive is a contiguous area of neighboring pixels of similar color. The center of the circle can be the anchor pixel. So, there is the equation which I think it's ok to do this:

DeltaI = square root[(Ranchor - Ri)² - (Ganchor - Gi)² - (Banchor - Bi)²]

Where R,G and B are color components of a pixel, ranging from 0 to 255, anchor is the anchor pixel and i is any pixel around the anchor pixel which are the same equivalent color.

There is a image link to the expectation results (from Alçiçek & Balaban 2012):

Shrimp resulting equivalent circles

So there is my (bootable worked) code, but I have really no idea how to continue.. May be try to create a package ?

library(png)
nacre <-  readPNG("test.png")
nacre

dim(nacre)

# show the full RGB image
grid.raster(nacre)

# show the 3 channels in separate images
nacre.R = nacre
nacre.G = nacre
nacre.B = nacre

# zero out the non-contributing channels for each image copy
nacre.R[,,2:3] = 0
nacre.G[,,1]=0
nacre.G[,,3]=0
nacre.B[,,1:2]=0

# build the image grid
img1 = rasterGrob(nacre.R)
img2 = rasterGrob(nacre.G)
img3 = rasterGrob(nacre.B)
grid.arrange(img1, img2, img3, nrow=1)
# Now let’s segment this image. First, we need to reshape the array into a data frame with one row for each pixel and three columns for the RGB channels:


# reshape image into a data frame
df = data.frame(
red = matrix(nacre[,,1], ncol=1),
green = matrix(nacre[,,2], ncol=1),
blue = matrix(nacre[,,3], ncol=1)
  )


### compute the k-means clustering
K = kmeans(df,4)
df$label = K$cluster

### Replace the color of each pixel in the image with the mean 
### R,G, and B values of the cluster in which the pixel resides:

# get the coloring
colors = data.frame(
  label = 1:nrow(K$centers), 
  R = K$centers[,"red"],
  G = K$centers[,"green"],
  B = K$centers[,"blue"]
)

# merge color codes on to df
df$order = 1:nrow(df)
df = merge(df, colors)
df = df[order(df$order),]
df$order = NULL

# get mean color channel values for each row of the df.
R = matrix(df$R, nrow=dim(nacre)[1])
G = matrix(df$G, nrow=dim(nacre)[1])
B = matrix(df$B, nrow=dim(nacre)[1])

# reconstitute the segmented image in the same shape as the input image
nacre.segmented = array(dim=dim(nacre))
nacre.segmented[,,1] = R
nacre.segmented[,,2] = G
nacre.segmented[,,3] = B

# View the result
grid.raster(nacre.segmented)

Someone have a track or any idea ? Thanks for any help..


Solution

  • Well I've find a other way to answer my question:

    • I upload my image with load.imagefrom imager package.
    • I extract the RGB channels with this code:

      # Assign RGB channels to data frame
      nacreRGB <- data.frame(
      x = rep(1:nacreDm[2], each = nacreDm[1]),
      y = rep(nacreDm[1]:1, nacreDm[2]),
      R = as.vector(nacre[,,1]),
      G = as.vector(nacre[,,2]),
      B = as.vector(nacre[,,3])
      )
      # head(nacreRGB)
      
      # Assign RGB channels to data frame without pixel coordinates
      nacreRGB2 <- data.frame(
      R = as.vector(nacre[,,1]),
      G = as.vector(nacre[,,2]),
      B = as.vector(nacre[,,3])
      
    • After I convert this into HEX code with rgbSVG2rgbCSS fonction.

    • I put this into a matrix which I call RGB0 to create histogramms and show the different colors with the pixels frequencies.
    • After I perform a PCA to show the distribution of these colors:

      require("ggplot2")
      RGB0 <- as.data.frame(RGB0)
      
      # perform PCA on the nacre data and add the uv coordinates to the 
      dataframe
      PCA = prcomp(RGB0[,c("R","G","B")], center=TRUE, scale=TRUE)
      RGB0$u = PCA$x[,1]
      RGB0$v = PCA$x[,2]
      
    • I show this PCA with ggplot2.
    • After this I translate the RGB code into HSV code with rgb2hsv and I can have a value for the hue, for saturation (hue to white) and value (hue to dark), so I can obtain qualities and quantities datas about colors.

    Edit : All codes are now publishing into CRAN in ImaginR package : https://cran.r-project.org/web/packages/ImaginR/ImaginR.pdf

    Or on GitHub : https://github.com/PLStenger/ImaginR

    This version not really quantifying the color, but it will appears soon in the next version.