I have several pictures of plants (tif files). Each picture contains a set of Munsell color chips. The "true" RGB values of the Munsell color chips are known. My goal is to correct the colors of the pictures, by comparing the "observed" and the "true" colors of the Munsell color chips. I tried to use a simple linear regression for each channel. Here is an example for the Red channel: (EDITED:)

x1 = mean_value_of_red_channel_of_observed_color_chip_1
x2 = mean_value_of_red_channel_of_observed_color_chip_2
y1 = red_value_of_true_color_chip_1
y2 = red_value_of_true_color_chip_2
x_mean = (x1+x2)/2
y_mean = (y1+y2)/2
slope = ((x1-x_mean)*(y1-y_mean)+(x2-x_mean)*(y2-y_mean))/((y1-y_mean)^2+(y2-y_mean)^2)
y_intercept = y_mean-(slope*x_mean)
corrected_red_channel_of_image = (slope*red_channel_of_image)+y_intercept

The result does not look right:

Original Image Original Image Corrected Image Corrected Image

For the conversion I used Python 3.6 with Open CV.
Any ideas what I did wrong?

  • 1
    \$\begingroup\$ What you did wrong starts with the assumption that color correction is linear, but may include other issues as well... \$\endgroup\$
    – twalberg
    Mar 6, 2019 at 16:33
  • \$\begingroup\$ @twalberg the sensor is linear in the way it captures light, so it's a reasonable assumption. Problem is that a curve is applied in the raw conversion for gamma and other adjustments. \$\endgroup\$ Mar 6, 2019 at 16:38
  • 1
    \$\begingroup\$ Real world objects do not have "true" RGB values (even with scare quotes). It's probably better to use a word like "target" or "expected". \$\endgroup\$
    – mattdm
    Mar 6, 2019 at 18:19
  • 1
    \$\begingroup\$ I just realized that maybe you're assuming the image is in RGB order when it's actually BGR. I don't know that for a fact but it would explain your result, it's worth checking. \$\endgroup\$ Mar 6, 2019 at 21:01
  • 1
    \$\begingroup\$ no but you can do it with dcraw. \$\endgroup\$
    – ths
    Mar 7, 2019 at 13:24

1 Answer 1


With your formula, black (0,0,0) becomes a visible color (y_intercept_R,y_intercept_G,y_intercept_B). Your math are based on wrong assumptions. If the picture is correctly exposed, you have the constraint that 0. gives 0. and 1. (or 100% or 255) gives 1. (or 100% or 255). So your adjustment cannot be linear, it is more like a gamma correction on each channel.

  • \$\begingroup\$ I'm not sure you need to keep the constraint that 1.=1., but 0=0 is probably a must. \$\endgroup\$ Mar 7, 2019 at 4:29
  • \$\begingroup\$ In my script I added a correction, that sets all negative values to zero and all values higher than 255 to 255. This should not cause the color shifting.. \$\endgroup\$ Mar 7, 2019 at 13:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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