问题
I'm currently trying to determine the color difference between our output image and a painting of Monet with Python using OpenCV.
With my research I've seen that Delta E is the best for determining color difference. I've tried using extracting the BGR Channels of the two images and then taking the mean "Blue" "Green" and "Red" color used to use for computing the difference of each color channel.
output_chans = cv2.split(image)
monet_chans = cv2.split(best_painting)
colors = ("Blue", "Green", "Red")
for (output_chan, monet_chan, color) in zip(output_chans, monet_chans, colors):
output_mean = np.mean(output_chan)
monet_mean = np.mean(monet_chan)
color1_rgb = None
color2_rgb = None
if color == "Blue":
color1_rgb = sRGBColor(0.0, 0.0, output_mean)
color2_rgb = sRGBColor(0.0, 0.0, monet_mean)
elif color == "Green":
color1_rgb = sRGBColor(0.0, output_mean, 0.0);
color2_rgb = sRGBColor(0.0, monet_mean, 0.0);
elif color == "Red":
color1_rgb = sRGBColor(output_mean, 0.0, 0.0);
color2_rgb = sRGBColor(monet_mean, 0.0, 0.0);
# Convert from RGB to Lab Color Space
color1_lab = convert_color(color1_rgb, LabColor);
# Convert from RGB to Lab Color Space
color2_lab = convert_color(color2_rgb, LabColor);
# Find the color difference
delta_e = delta_e_cie2000(color1_lab, color2_lab);
print("Delta E of the Mean of %s Channel: %f" % (color, delta_e))
I receive an output of for the color difference for each color channel, however my professor suggests that I may be doing Delta E wrong as I'm supposed to only get one value for the color difference of the entire image instead of one value for each three color channels. In this case is there an alternative method or a correct method of of calculating the Delta E of our two images?
This is a link to a sample of our test image: https://imgur.com/a/KToggFS
And a link to a sample of the paintings: https://imgur.com/a/vi1SFax
回答1:
you seem to be using the colormath
library which does the math nicely, but is very slow. the colour-science package uses numpy to vectorise operations and get an answer in much less time
the cv2
library you're using has simple versions of some of the transformations you need, e.g. you can get most of the way doing:
import cv2
image1_rgb = cv2.imread('image1.jpeg')
image2_rgb = cv2.imread('image2.jpeg')
image1_lab = cv2.cvtColor(image1_rgb, cv2.COLOR_RGB2Lab)
image2_lab = cv2.cvtColor(image2_rgb, cv2.COLOR_RGB2Lab)
but note that you'll probably get better results if you convert to floats first:
image_lab = cv2.cvtColor(image_rgb.astype(np.float32) / 255, cv2.COLOR_RGB2Lab)
and then just use color-science
for the final call to delta_E() for each pixel (but note these are all vectorised, so you just give it the array of everything and it does it all efficiently at once):
import colour
delta_E = colour.delta_E(image1_lab, image2_lab)
and then you'll probably want the mean of this over the whole image:
np.mean(delta_E)
but median, quantiles, or a plotting the distribution would give you more information
note that if you care about color spaces and need more control over the transform from RGB to Lab you get a lot more control with colour-science
, with the rough template looking like:
image_lab = colour.XYZ_to_Lab(colour.sRGB_to_XYZ(image_srgb))
and there are lots of options about how to do this transform along the way, see docs for colour.XYZ_to_Lab and colour.XYZ_to_Lab.
来源:https://stackoverflow.com/questions/57224007/how-to-compute-the-delta-e-between-two-images