由RGB到HSV顏色空間的理解


1. RGB模型

2. HSV模型

3. 如何理解RGB與HSV的聯系

4. HSV在圖像處理中的應用

5. opencv中RGB-->HSV實現

 

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

而HSV模型,是針對用戶觀感的一種顏色模型,側重於色彩表示,什么顏色、深淺如何、明暗如何。第一次接觸HSV,書本里首先拋出的是一個圓錐模型,由於很少使用HSV,所以印象不深刻,但看一些資料時,HSV的概念時不時出來騷擾一些人的神經,所以,弄清楚HSV與RGB的關系,建立直觀的印象是很有必要的。

 

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變量,划定閾值,即可進行簡單的分割。

 

HSV的去陰影算法:

Improving shadow suppression in moving object detection with HSV color information

 

5. RGB --> HSV中的opencv實現

 

 

struct RGB2HSV_f
{
    typedef float channel_type;
    
    RGB2HSV_f(int _srccn, int _blueIdx, float _hrange)
    : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
    
    void operator()(const float* src, float* dst, int n) const
    {
        int i, bidx = blueIdx, scn = srccn;
        float hscale = hrange*(1.f/360.f);
        n *= 3;
    
        for( i = 0; i < n; i += 3, src += scn )
        {
            float b = src[bidx], g = src[1], r = src[bidx^2];
            float h, s, v;
            
            float vmin, diff;
            
            v = vmin = r;
            if( v < g ) v = g;
            if( v < b ) v = b;       // v = max(b, g, r)
            if( vmin > g ) vmin = g;
            if( vmin > b ) vmin = b;
            
            diff = v - vmin;
            s = diff/(float)(fabs(v) + FLT_EPSILON);  // s = 1 - min/max
            diff = (float)(60./(diff + FLT_EPSILON));
            if( v == r )
                h = (g - b)*diff;
            else if( v == g )
                h = (b - r)*diff + 120.f;
            else
                h = (r - g)*diff + 240.f;
            
            if( h < 0 ) h += 360.f;  // h 求值
            
            dst[i] = h*hscale;
            dst[i+1] = s;
            dst[i+2] = v;
        }
    }
    
    int srccn, blueIdx;
    float hrange;
};



 

RGB --> GRAY的實現 算法:

 

template<typename _Tp> struct RGB2Gray
{
    typedef _Tp channel_type;
    
    RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
    {
        static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };  // 三分量系數不同,人眼對綠色最敏感,所以G分量系數較大
        memcpy( coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]) );
        if(blueIdx == 0)
            std::swap(coeffs[0], coeffs[2]);
    }
    
    void operator()(const _Tp* src, _Tp* dst, int n) const  // 運算
    {
        int scn = srccn;
        float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
        for(int i = 0; i < n; i++, src += scn)
            dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);  // 結果
    }
    int srccn;
    float coeffs[3];
};



轉自:http://blog.csdn.net/viewcode/article/details/8203728


免責聲明!

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



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