• Color Models (RGB, CMY, HSI)


    Gonzalez R. C. and Woods R. E. Digital Image Processing (Forth Edition)

    除了我们熟悉的RGB模式来表示图片, 还有其他很多种图片表示方式. 其实我现在很想要知道的一点是, 神经网络会对不同的表示会有不同的反应吗?

    定义

    RGB

    普通的彩色图片, 每个像素点是一个三维的值((x, y, z) in [0, 1]^3),

    CMY

    RGB是以Red, Green, Blue为坐标轴的坐标系, 而CMY是以Cyan, Magenta, Yellow为坐标轴(这些颜色成为second colors), 以White为原点的坐标系.

    CMYK

    CMY因为不是以black为原点, 所以在实际中难以表示true black? 所以特意引入第四个颜色K表示黑色.

    HSI

    HSI, 即hue, saturation, identisity.

    Hue: 即表示某种颜色, 正如上图所示, 以H, 点与红色(标准)之间的角度(相当于指定某种颜色).

    Saturation: 饱和度, 顾名思义, 表示该颜色是有多少的纯色和白色混合在一起的.

    Identisity: 灰度值, 将一个图像变成一个灰度图就是根据这个指标, 其相当于((x, y, z))在black-white这个轴上的投影.

    注: HSI的值也是归一化为([0, 1])之间.

    相互的转换

    RGB <=> CMY

    [left [ egin{array}{l} C \ M \ Y \ end{array} ight ] = left [ egin{array}{l} 1 \ 1 \ 1 \ end{array} ight ] - left [ egin{array}{l} R \ G \ B end{array} ight ] . ]

    CMY <=> CMYK

    CMY > CMYK

    [K = min (C, M, Y), \ C = (C - K) / (1 - K), \ M = (M - K) / (1 - K), \ Y = (Y - K) / (1 - K). \ ]

    CMYK > CMY

    [C = C * (1 - K) + K, \ M = M * (1 - K) + K, \ Y = Y * (1 - K) + K. \ ]

    RGB <=> HSI

    hsi-to-rgb-conversion.pdf (tau.ac.il)

    RGB > HSI

    注意RGB > HSI并非直接的坐标变换, 具体的推导可以看上面的参考文献.

    [ heta = cos^{-1} { frac{frac{1}{2}[(R-G) + (R-B)]}{[(R-G)^2 + (R-B)(G-B)]^{1/2}} }, \ H = left { egin{array}{ll} heta / 2pi & ext{if} : B le G, \ 1 - heta/2pi & ext{if} : B > G. end{array} ight . \ S = 1 - frac{3}{R + G + B}[min (R, G, B)]. \ I = frac{1}{3}(R + G + B). ]

    注: 原文使用的是角度制, 这里我改成弧度制, 另外我这里直接将(H)归一化了.

    HSI > RGB

    HSI > RGB 需要根据(H)的不同改变策略:

    首先令(H = H cdot 2pi in [0, 2pi)).

    1. (H in [0, frac{2}{3}pi]):

    [B = I(1-S), \ R = I[1 + frac{Scos H}{cos (frac{1}{3}pi - H)}], \ G = 3I - (R + B). ]

    1. (H in [frac{2}{3}pi, frac{4}{3}pi)):

    [H = H - frac{2}{3}pi, \ R = I(1-S), \ G = I[1 + frac{Scos H}{cos (frac{1}{3}pi - H)}], \ B = 3I - (R + G). ]

    1. (H in [frac{4}{3}pi, 2pi)):

    [H = H - frac{4}{3}pi, \ G = I(1-S), \ B = I[1 + frac{Scos H}{cos (frac{1}{3}pi - H)}], \ R = 3I - (G + B). ]

    代码示例

    import cv2
    import matplotlib.pyplot as plt
    import numpy as np
    from PIL import Image
    
    img = np.random.randint(0, 256, (10, 10, 3), dtype=np.uint8)
    
    # rgb -> hsi
    def calcH(v):
        r, g, b = v
        val = (2 * r - g - b) / np.sqrt((r - g) ** 2 + (r - b) * (g - b))
        val /= 2
        theta = np.arccos(val)
        h = theta / (2 * np.pi) if b <= g else (1 - theta / (2 * np.pi))
        return h
    
    def calcS(v):
        return 1 - 3 * v.min() / v.sum()
    
    def calcI(v):
        return v.mean()
    
    def rgb2hsi(img: np.ndarray) -> np.ndarray:
        img = img.astype(np.float) / 255.
        def unit(v):
            h = calcH(v)
            s = calcS(v)
            i = calcI(v)
            return np.array([h, s, i])
        img = np.apply_along_axis(unit, 2, img)
        return img
    
    # hsi -> rgb
    
    def unit(v):
        h, s, i = v
        idx = np.arange(3)
        h = h * np.pi * 2
        if h >= 2 * np.pi / 3:
            if h >= 4 * np.pi / 3:
                h = h - 4 * np.pi / 3
                idx = (idx - 2) % 3
            else:
                h = h - 2 * np.pi / 3
                idx = (idx - 1) % 3
        b = i * (1 - s)
        r = i * (1 + s * np.cos(h) / np.cos(np.pi / 3 - h))
        g = 3 * i - b - r
        v = np.array([r, g, b])
        return v[idx]
    
    
    
    def hsi2rgb(img: np.ndarray):
        img = img.astype(np.float) / 255.
        img = np.apply_along_axis(unit, 2, img) * 255
        return img.astype(np.uint8)
    
    

    在opencv库中, 可以通过如下手段变化:

    rgb2hsi_cv = cv2.cvtColor(img[..., [2, 1, 0]], cv2.COLOR_BGR2HLS)
    hsi2rgb_cv = cv2.cvtColor(rgb2hsi_cv, cv2.COLOR_HLS2BGR)[..., [2, 1, 0]]
    

    opencv采用BGR格式是由于历史原因.

    另外, 其出来的结果和我所实现的结果并不一致, 其I值也并非(frac{1}{3}(R + G + B))​, 所以我怀疑可能用的是另外一套变换公式(虽然网上说, HLS就是HSI).

    在PIL库中, 我没找到RGB2HSI的函数, 不过PIL一般采用如下方式进行变换:

    rgb2what = Image.fromarray(img).convert('RGB').convert('...')
    

    注: '...'部分表示mode, 具体参考: Concepts — Pillow (PIL Fork) 8.3.1 documentation

  • 相关阅读:
    没有可持续集成的日子里
    Apache Avro 与 Thrift 比较
    CruiseControl.NET以及使用
    不靠谱产品经理的特征
    Hadoop 新 MapReduce 框架 Yarn 详解
    Storm On YARN
    iOS开发资源:推送通知相关开源项目--PushSharp、APNS-PHP以及Pyapns等
    Swift REPL入门介绍
    学习Swift,一定不能错过的10大开源项目!
    iOS8 Size Classes的理解与使用
  • 原文地址:https://www.cnblogs.com/MTandHJ/p/15072026.html
Copyright © 2020-2023  润新知