Search code examples
rimagepngrgb

How to differente between materials from .png image in R?


I have a png image and want to differentiate between the materials e.g., plants, metal, and soil by using the RGB information. I have been searching for exact values or methods in R with no success. I'm new to this field and maybe I'm using the wrong terms.

Note: I'm not looking for an object-based method only a pixel method.

> library(png)
> library(fields)

> # read the image 
> pic091800<-readPNG("091800.png", native = FALSE, info = FALSE)

> dim(pic091800)
[1] 175 248   3

> pic091800[144,100,]
[1] 0.5882353 0.4941176 0.4549020

> pic091800[144,100,]*255
[1] 150 126 116

Edit: Example (cropped)image


Solution

  • I used to work on pixel isolation based on RGB values quite often. Here is one example of how I went about doing it.

    Lets Say I'm working with the image below, and I want to isolate the blue dot only.

    enter image description here

    To do this, you will need the packages library(raster) and library(png)

    load PNG image

    library(raster)
    library(png)
    img <- png::readPNG('~/path to file/blue dot example.png')
    
    

    Convert your image to a raster file using the brick() function

    r <- brick(img)
    

    plot raster

    raster::plotRGB(r, scale = 1)
    

    enter image description here

    Now lets do a plot that isolates our blue dot based on RGB values (r==0,G==0,B==1)

    plot(r[[1]] == 0 & r[[3]] == 1)
    

    enter image description here

    Finally, if you want the true color, and not the color from the raster output (in our case, we want blue), while excluding everything else, just use the mask() function as below

    raster::plotRGB(mask(r, r[[1]] == 0 & r[[3]] == 1, maskvalue = 0), scale = 1)
    

    enter image description here

    The advantage of this method is the brick() function reads all bands in one object, but I never figured out how to isolate multiple colors in one image using this method. If you were interested in doing this, say with your example, you wanted dirt and plants, you could about go about it like this:

    Create rasters for each band (R, G, B)

    ConvertedR <- raster("example blue dot.png", band = 1)
    ConvertedG <- raster("example blue dot.png", band = 2)
    ConvertedB <- raster("example blue dot.png", band = 3)
    
    #isolate color frequency of interest (this is an example assuming I had some reds, greens, and blues I wanted to isolate, but I made up these numbers)
    
    RGB_selection <- ConvertedR >= 0 & ConvertedR < 50 & ConvertedG >= 0 & ConvertedG < 30 & ConvertedB>=60 & ConvertedB <=90
    
    

    I hope this helps , and I had posted a question like yours a few years back on stackexchange GIS, with a link here (https://gis.stackexchange.com/questions/267402/defining-color-band-to-recognize-from-sing-layer-raster-in-r/267409#267409)