python颜色压缩的结果颜色比保存颜色深

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python颜色压缩的结果颜色比保存颜色深相关的知识,希望对你有一定的参考价值。

今天帮师姐解决一个bug,测试了Python图像resize前后颜色不一致问题。

代码片段执行的功能:图像指定倍数超分辨率,输入为[0-1] float型数据,输出为格式不限的图像

bug:输入图像与输出图像颜色不一致

一、把产生bug的功能片段做分离测试:

1 import h5py

2 import numpy as np

3 import matplotlib.pyplot as plt

4 from PIL import Image

5 from scipy import misc

6

7

8 def get_result_array():

9 file_name = "./butterfly_GT.bmp"

10 img_no_expand = misc.imread(file_name, flatten=False, mode='YCbCr')

11 img_no_expand = img_no_expand / 255.0

12 # img_no_expand = np.uint8(img_no_expand*255)

13 h, w = img_no_expand.shape[:2]

14 print(img_no_expand.shape)

15 h *= 2

16 w *= 2

17 data = list()

18

19 data.append(misc.imresize(img_no_expand[:, :, 0], [h, w], 'bicubic')[:,:,None])

20 data.append(misc.imresize(img_no_expand[:, :, 1], [h, w], 'bicubic')[:,:,None])

21 data.append(misc.imresize(img_no_expand[:, :, 2], [h, w], 'bicubic')[:,:,None])

22 data_out = np.concatenate(data, axis=2)

23 img = misc.toimage(arr=data_out, mode="YCbCr")

24 img.save("out_3.jpg")

25

26

27 if __name__=='__main__':

28 get_result_array()

运行代码:

左图为输入图像,右图为输出图像。为了便于对比,把输出图像缩放至与输入图像一致,由图可见,输出图像色彩严重失真。

二、在pycharm中,Ctrl+B 查看源码:

三、发现可以选择模式,猜想可能是模式有误:

四、在函数的实现的第一行,初始化Image类,猜想初始化参数设置错误。

五、在类的初始化过程中,默认图像的最大值为255,而实际输入是0-1的float型数据。找到了错误之处。

六、仔细查看文档,mode可以修改。0-1float型数据对应mode=“F”:

七、于是,在代码中加入参数:

八、插值后处理

插值之后部分像素点数值可能大于1,这时有两种做法,一种是归一化,一种是截断。经过实验发现,归一化操作往往会使图像整体亮度变暗,对图像整体视觉效果有较大影响,因此这里选择截断。

九、最终代码如下:

1 import h5py

2 import numpy as np

3 import matplotlib.pyplot as plt

4 from PIL import Image

5 from scipy import misc

6

7

8 def get_result_array():

9 file_name = "./butterfly_GT.bmp"

10 img_no_expand = misc.imread(file_name, flatten=False, mode='YCbCr')

11 img_no_expand = img_no_expand / 255.0

12 # img_no_expand = np.uint8(img_no_expand*255)

13 h, w = img_no_expand.shape[:2]

14 print(img_no_expand.shape)

15 h *= 2

16 w *= 2

17 data = list()

18 data.append(misc.imresize(img_no_expand[:, :, 0], [h, w], 'bicubic', mode="F")[:,:,None])

19 data.append(misc.imresize(img_no_expand[:, :, 1], [h, w], 'bicubic', mode="F")[:,:,None])

20 data.append(misc.imresize(img_no_expand[:, :, 2], [h, w], 'bicubic', mode="F")[:,:,None])

21 data_out = np.concatenate(data, axis=2)

22 data_out[data_out > 1] = 1.0

23 data_out = np.uint8(data_out * 255)

24 img = misc.toimage(arr=data_out, mode="YCbCr")

25 img.save("out_4.jpg")

26

27

28 if __name__=='__main__':

29 get_result_array()
参考技术A python颜色压缩的结果颜色比保存颜色深是因为python保存图片变色,与原始图像颜色不一致有时候将图片保存到本地会发现颜色与原来不一致,有的变成相反的颜色了。

检查Android中的颜色是深还是浅

【中文标题】检查Android中的颜色是深还是浅【英文标题】:Check if color is dark or light in Android 【发布时间】:2014-08-07 06:59:18 【问题描述】:

根据标题,我的问题是:Android 是否提供任何方法来分析/确定颜色(显然是动态的)是浅色还是深色?

【问题讨论】:

【参考方案1】:

Android 不提供,您可以实现一个方法来确定这一点。这是一种方法:

public boolean isColorDark(int color)
    double darkness = 1-(0.299*Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
    if(darkness<0.5)
        return false; // It's a light color
    else
        return true; // It's a dark color
    

【讨论】:

谢谢! goona 尽快尝试并报告! 你从哪里得到这些神奇的数字?? (0.299, 0.587, 0.114) ? 这是数字格式的亮度定义。 en.wikipedia.org/wiki/Luma_%28video%29 貌似android提供了***.com/a/48267387/3940133 你真聪明,谢谢你与我们分享你的智慧【参考方案2】:

如果您使用支持库 v4(或 AndroidX),您可以使用 ColorUtils.calculateLuminance(color),它返回颜色的亮度为 0.01.0 之间的浮点数。

所以你可以这样做:

boolean isDark(int color) 
    return ColorUtils.calculateLuminance(color) < 0.5;

见:

支持库 v4:https://developer.android.com/reference/android/support/v4/graphics/ColorUtils.html#calculateLuminance(int) AndroidX:https://developer.android.com/reference/androidx/core/graphics/ColorUtils#calculateLuminance(int)

注意,由于 Android API 24 还有一个方法:Color.luminance(color)

【讨论】:

不知何故 ColorUtils.calculateLuminance(color) &lt; 0.25 对我来说效果更好。【参考方案3】:
public float getLightness(int color) 
    int red   = Color.red(color);
    int green = Color.green(color);
    int blue  = Color.blue(color);

    float hsl[] = new float[3];
    ColorUtils.RGBToHSL(red, green, blue, hsl);
    return hsl[2];

人们可以很容易地使用 ColorUtils 来检查颜色的亮度。

if (getLightness(color) < 0.5f )
    // This color is too dark!

【讨论】:

【参考方案4】:

如果您想了解背景颜色是浅色还是深色,以确定在其上绘制的文本使用什么颜色(白色或黑色)——在所有情况下,计算亮度不会为您提供正确的值.

假设您有背景颜色:#7f6fad。 如果你检查它的亮度(通过ColorUtils#calculateLuminance)你会得到:0.1889803503770053,它低于0.5,因此按照这个逻辑应该被认为是黑暗的。

但如果您关注WCAG,您会发现一般文本对比度至少应为 4.5:1。

ColorUtils 有方法calculateContrast,它会给出以下结果:

对于白色文本颜色:4.393666669010922 对于黑色文本颜色:4.779607007540106

可以看出,白色文本提供的对比度不够,而黑色则很好。 因此,如果您想检查在一些通用背景颜色之上绘制什么颜色,最好检查对比度:

@ColorInt
fun getContrastColor(@ColorInt color: Int): Int 
    val whiteContrast = ColorUtils.calculateContrast(Color.WHITE, color)
    val blackContrast = ColorUtils.calculateContrast(Color.BLACK, color)

    return if (whiteContrast > blackContrast) Color.WHITE else Color.BLACK

【讨论】:

【参考方案5】:

另一种解决方案:

private static final int BRIGHTNESS_THRESHOLD = 130;

    /**
     * Calculate whether a color is light or dark, based on a commonly known
     * brightness formula.
     *
     * @see @literal http://en.wikipedia.org/wiki/HSV_color_space%23Lightness
     */
    public static boolean isColorDark(int color) 
        return ((30 * Color.red(color) +
                59 * Color.green(color) +
                11 * Color.blue(color)) / 100) <= BRIGHTNESS_THRESHOLD;
    

【讨论】:

【参考方案6】:

稍微简化接受的答案

public boolean isColorDark(int color)
    final double darkness = 1-(0.299*Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
    return !(darkness<0.5);

【讨论】:

以上是关于python颜色压缩的结果颜色比保存颜色深的主要内容,如果未能解决你的问题,请参考以下文章

UIView 背景颜色比 UICollectionView 背景颜色深

页脚视图的颜色总是比 UITableView 分隔符的颜色深

如何切换 ListView 项目颜色并保存?

在列表框/python中保存颜色更改

Onclick背景颜色更改并保存在数据库中

Python - 更改数据框的标题颜色并将其保存到excel文件