使用PIL进行RGB到HSV转换

11

我正在尝试自动增强一些图像,以便将它们传输到数字相框中。我已经编写了代码来调整大小,在图像的最不显著(最少细节)的角落添加日期/时间,并将纵向拍摄的图像成对粘贴在一起,以避免在数字相框的41:20低分辨率屏幕上显示单个纵向图像。

对于那些照明不太好的图片,我使用colorsys.rgb_to_hsv函数计算H、S、V通道并对V通道进行亮度拉伸滤镜,然后将其转换回RGB格式并保存为JPEG格式以供数字相框使用。显然,转换需要很长时间,即使使用itertools技巧;我通过使用psyco成功地提高了效率。

然而,我注意到PIL Image.convert有一个示例,其中RGB可以使用4×4矩阵作为第二个参数转换为XYZ颜色空间,于是我想知道:

如何在convert方法调用中使用自定义矩阵将RGB转换为HSV(然后再将其转回RGB)?(在这种情况下,小的舍入误差并不重要,因此我不介意每个通道都以0…255整数的形式表示)

提前感谢您。


注意:虽然 ImageOps.autocontrast 函数也可以完成我所做的工作,但我希望能够根据需要扩展滤镜(例如,可能稍微增加一些饱和度),这就是为什么我想要一个快速的 RGB↔HSV 方法。 - tzot
2个回答

1

虽然我看到过引用[1]声称HSV颜色空间是从RGB的线性变换,这似乎意味着它可以通过矩阵完成,但我一直没能找到或确定这样一个矩阵看起来像什么。从某种角度来说,这并不让我感到惊讶,因为我也看到了许多[类似]非矩阵过程实现,它们完成的方式并不“看起来”线性。

无论如何,在研究这个问题时,我发现了前SGI研究员Paul Haeberli的在线计算机图形笔记本中的一篇[有些过时的]文章,标题为Matrix Operations for Image Processing,其中介绍了如何使用4x4矩阵进行多种不同的颜色变换,这可能会对您有所帮助。所有给出的示例都是直接在RGB彩色图像上操作的,就像几何矩阵变换一样,它们的任何序列都可以通过级联组合成单个矩阵。

希望这可以帮到您。
[1]: 颜色空间转换 <http://www.poynton.com/PDFs/coloureq.pdf>:

2.7.3 HSL(色相、饱和度和亮度)

这代表了许多类似的颜色空间,替代名称包括HSI(强度)、HSV(值)、HCI(色度/色彩饱和度)、HVC、TSD(色相、饱和度和黑暗度)等。这些颜色空间大多是从RGB进行线性变换,因此与设备相关且非线性。它们的优点在于极其直观的颜色指定方式。很容易选择所需的色调,然后通过调整其饱和度和强度略微修改它。


谢谢,我正在调查。就像你一样,到目前为止我所看到的代码并没有让我对我的问题有一个积极的答案感到乐观... - tzot
接近但不完美的东西:在Paul Bourke的网站上转换RGB和YIQ/YUV。不幸的是,来回转换YIQ/YUV会严重扭曲颜色信息;也许这是由于矩阵中数字的几个小数位造成的。无论如何,它们不能直接使用。 - tzot
这些变换确实是线性的,但它们是分段的,所以我认为不可能用单个矩阵进行变换(而且我也不确定使用“分段矩阵”是否有用或可行)。 - heltonbiker

0

将RGB值转换为HSV值的公式可以在此处找到:http://www.rapidtables.com/convert/color/rgb-to-hsv.htm。我曾经需要反过来做,因此编写了以下函数。

def hsb2rgb(hsb):
    '''
    Transforms a hsb array to the corresponding rgb tuple
    In: hsb = array of three ints (h between 0 and 360, s and v between 0 and 100)
    Out: rgb = array of three ints (between 0 and 255)
    '''
    H = float(hsb[0] / 360.0)
    S = float(hsb[1] / 100.0)
    B = float(hsb[2] / 100.0)

    if (S == 0):
        R = int(round(B * 255))
        G = int(round(B * 255))
        B = int(round(B * 255))
    else:
        var_h = H * 6
        if (var_h == 6):
            var_h = 0  # H must be < 1
        var_i = int(var_h)
        var_1 = B * (1 - S)
        var_2 = B * (1 - S * (var_h - var_i))
        var_3 = B * (1 - S * (1 - (var_h - var_i)))

        if      (var_i == 0):
            var_r = B     ; var_g = var_3 ; var_b = var_1
        elif (var_i == 1):
            var_r = var_2 ; var_g = B     ; var_b = var_1
        elif (var_i == 2):
            var_r = var_1 ; var_g = B     ; var_b = var_3
        elif (var_i == 3):
            var_r = var_1 ; var_g = var_2 ; var_b = B
        elif (var_i == 4):
            var_r = var_3 ; var_g = var_1 ; var_b = B
        else:
            var_r = B     ; var_g = var_1 ; var_b = var_2

        R = int(round(var_r * 255))
        G = int(round(var_g * 255))
        B = int(round(var_b * 255))

    return [R, G, B]

我已经使用了 colorsys 模块。问题是关于一个可以与 convert 函数一起使用的矩阵。 - tzot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接