【问题标题】:How to compute the Delta E between two images using OpenCV如何使用 OpenCV 计算两个图像之间的 Delta E
【发布时间】:2019-12-05 00:47:24
【问题描述】:

我目前正在尝试使用 OpenCV 确定输出图像与使用 Python 绘制的莫奈画作之间的色差。

根据我的研究,我发现 Delta E 是确定色差的最佳选择。我尝试使用提取两个图像的 BGR 通道,然后取用于计算每个颜色通道差异的平均“蓝色”“绿色”和“红色”颜色。

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))

我收到每个颜色通道的色差输出,但是我的教授建议我可能做错了 Delta E,因为我应该只获得整个图像的色差值而不是一个值每三个颜色通道的值。在这种情况下,是否有另一种方法或正确的方法来计算我们两个图像的 Delta E?

这是我们测试图片示例的链接:https://imgur.com/a/KToggFS

以及绘画样本的链接:https://imgur.com/a/vi1SFax

【问题讨论】:

    标签: python opencv image-processing histogram


    【解决方案1】:

    您似乎正在使用 colormath 库,它可以很好地完成数学运算,但速度很慢。 colour-science package 使用 numpy 向量化操作并在更短的时间内得到答案

    您正在使用的 cv2 库包含您需要的一些转换的简单版本,例如您可以完成大部分工作:

    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)
    

    但请注意,如果先转换为浮点数,您可能会得到更好的结果:

    image_lab = cv2.cvtColor(image_rgb.astype(np.float32) / 255, cv2.COLOR_RGB2Lab)
    

    然后只需使用color-science 对每个像素进行最终调用delta_E()(但请注意,这些都是矢量化的,因此您只需将所有内容的数组提供给它,它就会一次有效地完成所有操作):

    import colour
    
    delta_E = colour.delta_E(image1_lab, image2_lab)
    

    然后你可能会想要整个图像的平均值:

    np.mean(delta_E)
    

    但中位数、分位数或绘制分布图会为您提供更多信息

    请注意,如果您关心色彩空间并且需要更多地控制从 RGB 到 Lab 的转换,您可以使用 colour-science 获得更多控制权,粗略的模板如下所示:

    image_lab = colour.XYZ_to_Lab(colour.sRGB_to_XYZ(image_srgb))
    

    还有很多关于如何进行此转换的选项,请参阅colour.XYZ_to_Labcolour.XYZ_to_Lab 的文档。

    【讨论】:

    • 正是我想要的。谢谢!
    • 你会如何在纯opencv中做到这一点? :\
    • @jtlz2 可以指出 OpenCV 中的“Delta E”计算吗?如果是这样,那么我会尝试更新我的答案,但 AFAICT 目前不包含该功能
    【解决方案2】:

    以上答案是正确的。但是,如果您正在寻找更简化的计算 Delta E 的方法,即通过避免额外的依赖关系。您可以简单地计算两幅图像之间的欧几里得距离并取平均值。

    def deltaE(img1, img2, colorspace = cv2.COLOR_BGR2LAB):
       # check the two images are of the same size, else resize the two images
       (h1, w1) = img1.shape[:2]
       (h2, w2) = img1.shape[:2]
        h, w = None, None
        # check the height
        if h1 > h2:
            h = h1
        else:
            h = h2
        #check the width
        if w1 > w2:
            w = w1
        else:
            w = w2
        
        img1 = cv2.resize(img1, (h,w))
        img2 = cv2.resize(img2, (h,w))
        # Convert BGR images to specified colorspace
        img1 = cv2.cvtColor(img1, colorspace)
        img2 = cv2.cvtColor(img2, colorspace)
        # compute the Euclidean distance with pixels of two images 
        return np.sqrt(np.sum((img1 - img2) ** 2, axis=-1))/255.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 2020-08-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      相关资源
      最近更新 更多