I have a 4-band raster image (RGB), downloaded from a WMS, representing clay content of topsoil ranging from brown (high clay content) to yellow (low clay content). The 4th band is alpha-band, with constant 255 values.

Part of image

Instead of the red, green, blue values (all of them ranging from 0 to 255) the concentration is needed (ranging from 0 to 100). As a help, at certain points, I have the corresponding percentage (see the image above). That means, I have a lookup table like this:

R, G, B , percentage

244, 229, 115, 9

242, 187, 62, 26

220, 148, 37, 33

183, 97, 6, 41

177, 87, 1, 43


The question is, how can I get the value of clay content in percentage for every raster pixel.

For me this looks much like an interpolation task; however, resample, interp, approx work only in fewer dimensions.

Here is a similar problem however with a different color ramp.

  • Any chance of a link to the image or the WMS from where it came? Or a similar image? Or even just a peek at part of the image?
    – Spacedman
    Jan 8 '19 at 14:07
  • And how is this a four-band raster image? R,G,B and something else? Is there an alpha or opacity channel?
    – Spacedman
    Jan 8 '19 at 14:27
  • Outline: A colour palette should be a continuous path in 3d R-G-B space. Get the unique colours in your image and plot them using rgl::plot3d and you should see them form a path - although it might not be straight or even smooth. You then need to construct the path using (probably) nearest neighbours and then you can interpolate...
    – Spacedman
    Jan 8 '19 at 14:51
  • Just for clarity, does the actual image have the spots with the value labels on, or is it a very clean raster with no annotations?
    – Spacedman
    Jan 8 '19 at 15:47
  • 1
    A fairly simplistic approach would be to create a multiple linear regression between the extracted percentage and the R-G-B values. That should give you a formula to go from the 3 values to the 1 value. It is likely not going to be perfect, but it is a place to start. Jan 8 '19 at 15:56

You have a monochromatic palette (shades of yellow/brown) so there's a good chance some linear combination of the individual RGB values to a single value will work.

Your point sample data looks like this:

> train
    R   G   B percentage
1 244 229 115          9
2 242 187  62         26
3 220 148  37         33
4 183  97   6         41
5 177  87   1         43

Plotting some scatter plots of each component against percentage shows the Blue component to be near-linear:

> plot(train$B, train$percentage)

enter image description here

So we can predict percentage from Blue by fitting a linear model:

> m = lm(percentage~B, data=train)

Now we create a template raster and fill it with predicted percentages over the blue pixel values and plot:

> percent = p[[1]]
> percent[] = predict(m, newdata=data.frame(B=p[[3]][]))
> plot(percent)

enter image description here

this is a single band raster with percentage values. The holes are where I had to crop out the point labels from your image with NA values - if you have a clean source image then this shouldn't be a problem.

If this is good enough then stop, otherwise if you want better you could go into more complicated modelling based on all RGB components, or fitting a line through the path in RGB space, or asking the people who produced the data for a key, all depending on the level of precision you need in your application, which we don't know.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.