圖像處理5 色彩空間轉換——RGB與HSV


介紹

RGB色彩模式是工業界的一種顏色標准,是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標准幾乎包括了人類視力所能感知的所有顏色,是目前運用最廣的顏色系統之一。

HSV(Hue, Saturation, Value)是根據顏色的直觀特性由A. R. Smith在1978年創建的一種顏色空間, 也稱六角錐體模型(Hexcone Model)。這個模型中顏色的參數分別是:色調(H),飽和度(S),明度(V)。
 

以下轉自由RGB到HSV顏色空間的理解

在圖像處理中,最常用的顏色空間是RGB模型,常用於顏色顯示和圖像處理,三維坐標的模型形式,非常容易被理解。

而HSV模型,是針對用戶觀感的一種顏色模型,側重於色彩表示,什么顏色、深淺如何、明暗如何。

1. RGB模型。

三維坐標:

 

原點到白色頂點的中軸線是灰度線,r、g、b三分量相等,強度可以由三分量的向量表示。

用RGB來理解色彩、深淺、明暗變化:

色彩變化: 三個坐標軸RGB最大分量頂點與黃紫青YMC色頂點的連線

深淺變化:RGB頂點和CMY頂點到原點和白色頂點的中軸線的距離

明暗變化:中軸線的點的位置,到原點,就偏暗,到白色頂點就偏亮

PS: 光學的分析

三原色RGB混合能形成其他的顏色,並不是說物理上其他顏色的光是由三原色的光混合形成的,每種單色光都有自己獨特的光譜,如黃光是一種單色光,但紅色與綠色混合能形成黃色,原因是人的感官系統所致,與人的生理系統有關。

只能說“將三原色光以不同的比例復合后,對人的眼睛可以形成與各種頻率的可見光等效的色覺。”

 

2. HSV模型

倒錐形模型:

 

這個模型就是按色彩、深淺、明暗來描述的。

H是色彩

S是深淺, S = 0時,只有灰度

V是明暗,表示色彩的明亮程度,但與光強無直接聯系,(意思是有一點點聯系吧)。

 

3. RGB與HSV的聯系

從上面的直觀的理解,把RGB三維坐標的中軸線立起來,並扁化,就能形成HSV的錐形模型了。

但V與強度無直接關系,因為它只選取了RGB的一個最大分量。而RGB則能反映光照強度(或灰度)的變化。

v = max(r, g, b)

由RGB到HSV的轉換:

 

HSV對用戶來說是一種直觀的顏色模型。我們可以從一種純色彩開始,即指定色彩角H,並讓V=S=1,然后我們可以通過向其中加入黑色和白色來得到我們需要的顏色。增加黑色可以減小V而S不變,同樣增加白色可以減小S而V不變。例如,要得到深藍色,V=0.4 S=1 H=240度。要得到淡藍色,V=1 S=0.4 H=240度。

 

4. HSV在圖像處理應用

HSV在用於指定顏色分割時,有比較大的作用。

H和S分量代表了色彩信息。

分割應用:

      用H和S分量來表示顏色距離,顏色距離指代表兩種顏色之間的數值差異。
     Androutsos等人通過實驗對HSV顏色空間進行了大致划分,亮度大於75%並且飽和度大於20%為亮彩色區域,亮度小於25%為黑色區域,亮度大於75%並且飽和度小於20%為白色區域,其他為彩色區域。

   對於不同的彩色區域,混合H與S變量,划定閾值,即可進行簡單的分割。

 陰影檢測

2001年的論文《Improving Shadow Suppression in Moving Object Detection with HSV Color Information》中提出將HSV色彩空間用於陰影檢測。估通過估計陰影遮擋造成的HSV值的改變,來區分移動投射陰影和移動物體點。
基本算法如下,其中Ik和Bk分別是當前圖像和背景圖像對應像素的HSV分量,α,β,TS和TH分別表示亮度、飽和度、色度分量的閾值,並且0<α<1,0<β≤1,得到的SP k (x, y)結果為正則歸於陰影。

 

 

 

RGB和HSV相互轉換

前面是matplotlib.colors自帶的函數,后面是根據公式的實現。

# coding: utf8
import numpy as np


def rgb_to_hsv(arr):
    """
    convert float rgb values (in the range [0, 1]), in a numpy array to hsv
    values.

    Parameters
    ----------
    arr : (..., 3) array-like
       All values must be in the range [0, 1]

    Returns
    -------
    hsv : (..., 3) ndarray
       Colors converted to hsv values in range [0, 1]
    """
    # make sure it is an ndarray
    arr = np.asarray(arr)

    # check length of the last dimension, should be _some_ sort of rgb
    if arr.shape[-1] != 3:
        raise ValueError("Last dimension of input array must be 3; "
                         "shape {shp} was found.".format(shp=arr.shape))

    in_ndim = arr.ndim
    if arr.ndim == 1:
        arr = np.array(arr, ndmin=2)

    # make sure we don't have an int image
    if arr.dtype.kind in ('iu'):
        arr = arr.astype(np.float32)

    out = np.zeros_like(arr)
    arr_max = arr.max(-1)
    ipos = arr_max > 0
    delta = arr.ptp(-1)
    s = np.zeros_like(delta)
    s[ipos] = delta[ipos] / arr_max[ipos]
    ipos = delta > 0
    # red is max
    idx = (arr[..., 0] == arr_max) & ipos
    out[idx, 0] = (arr[idx, 1] - arr[idx, 2]) / delta[idx]
    # green is max
    idx = (arr[..., 1] == arr_max) & ipos
    out[idx, 0] = 2. + (arr[idx, 2] - arr[idx, 0]) / delta[idx]
    # blue is max
    idx = (arr[..., 2] == arr_max) & ipos
    out[idx, 0] = 4. + (arr[idx, 0] - arr[idx, 1]) / delta[idx]

    out[..., 0] = (out[..., 0] / 6.0) % 1.0
    out[..., 1] = s
    out[..., 2] = arr_max

    if in_ndim == 1:
        out.shape = (3,)

    return out

def hsv_to_rgb(hsv):
    """
    convert hsv values in a numpy array to rgb values
    all values assumed to be in range [0, 1]

    Parameters
    ----------
    hsv : (..., 3) array-like
       All values assumed to be in range [0, 1]

    Returns
    -------
    rgb : (..., 3) ndarray
       Colors converted to RGB values in range [0, 1]
    """
    hsv = np.asarray(hsv)

    # check length of the last dimension, should be _some_ sort of rgb
    if hsv.shape[-1] != 3:
        raise ValueError("Last dimension of input array must be 3; "
                         "shape {shp} was found.".format(shp=hsv.shape))

    # if we got pased a 1D array, try to treat as
    # a single color and reshape as needed
    in_ndim = hsv.ndim
    if in_ndim == 1:
        hsv = np.array(hsv, ndmin=2)

    # make sure we don't have an int image
    if hsv.dtype.kind in ('iu'):
        hsv = hsv.astype(np.float32)

    h = hsv[..., 0]
    s = hsv[..., 1]
    v = hsv[..., 2]

    r = np.empty_like(h)
    g = np.empty_like(h)
    b = np.empty_like(h)

    i = (h * 6.0).astype(np.int)
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))

    idx = i % 6 == 0
    r[idx] = v[idx]
    g[idx] = t[idx]
    b[idx] = p[idx]

    idx = i == 1
    r[idx] = q[idx]
    g[idx] = v[idx]
    b[idx] = p[idx]

    idx = i == 2
    r[idx] = p[idx]
    g[idx] = v[idx]
    b[idx] = t[idx]

    idx = i == 3
    r[idx] = p[idx]
    g[idx] = q[idx]
    b[idx] = v[idx]

    idx = i == 4
    r[idx] = t[idx]
    g[idx] = p[idx]
    b[idx] = v[idx]

    idx = i == 5
    r[idx] = v[idx]
    g[idx] = p[idx]
    b[idx] = q[idx]

    idx = s == 0
    r[idx] = v[idx]
    g[idx] = v[idx]
    b[idx] = v[idx]

    rgb = np.empty_like(hsv)
    rgb[..., 0] = r
    rgb[..., 1] = g
    rgb[..., 2] = b

    if in_ndim == 1:
        rgb.shape = (3, )

    return rgb


def hsv2rgb(h, s, v):
    h60 = int(h * 6.0)
    hi = h60 % 6
    f = h *6.0 - h60
    p = v * (1.0 - s)
    q = v * (1.0 - f * s)
    t = v * (1.0 - (1.0 - f) * s)
    if hi == 0:
        return v, t, p
    elif hi == 1:
        return q, v, p
    elif hi == 2:
        return p, v, t
    elif hi == 3:
        return p, q, v
    elif hi == 4:
        return t, p, v
    else:  #  hi == 5:
        return v, p, q

def rgb2hsv(r, g, b):
    mx = np.max([r, g, b])
    mn = np.min([r, g, b])
    df = mx-mn
    if mx == mn:
        h = 0.0
    elif mx == r:
        h = (((g-b)/df))
    elif mx == g:
        h = (((b-r)/df) + 2.0)
    else:  # mx == b
        h = (((r-g)/df) + 4.0)
    if mx == 0:
        s = 0.0
    else:
        s = df/mx
    h = h/6.0%1.0
    v = mx
    return h, s, v


if __name__ == "__main__":
    for r,g,b in np.random.rand(10,3):
        h,s,v= rgb_to_hsv((r,g,b))
        h1,s1,v1=rgb2hsv(r, g, b)
        r,g,b = hsv_to_rgb((h,s,v))
        r1,g1,b1= hsv2rgb(h,s,v)
        print [h,s,v,r,g,b]==[h1,s1,v1,r1,g1,b1]
    """
    True
    True
    True
    True
    True
    True
    True
    True
    True
    True
    """

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM