HSV

hsv.png

基本

Hue Saturation Value of Brightness

Hue 色相 0(赤)~180(水色)~360(赤)
Saturation 彩度 255の時最も鮮やか,0の時色なし
Value of Brightness 輝度 255の時明るい、0の時暗い=黒に近づく

マンセル表色系だと

Hue
色相
Value
明度
Chroma
彩度

という風に呼ばれている。
色相は0~360度の範囲
OpenCVだと0~180の範囲
hsv.png
HSV-RGB.png

java

HSVToColor(float[)]h…は0~360の間の値で渡す。

HSV⇔RGB間の変換

OpenCVcvCvtColorというものでもできるらしい。

C++

#include<math.h>
    struct HSV{
    unsigned int m_Hue;
    unsigned char m_Saturation;
    unsigned char m_Brightness;
    HSV(unsigned int _hue,unsigned char _sat,unsigned char _bri)
    :m_Hue(_hue),m_Saturation(_sat),m_Brightness(_bri){
    }
    void setFromHSV(const struct HSV& _hsv)
    {//H=0-360 S,V=0.0-1.0で渡す hueは360までなければならない
        if(_hsv.m_Hue>360){assert(!"Hueは0-360の値を渡してください。");}
        if(_hsv.m_Saturation>256|| _hsv.m_Brightness>256
         || _hsv.m_Saturation<0 || _hsv.m_Brightness<0){assert(!"S,Vは0-255の値を渡してください");}
 
        double dSaturation=(double)_hsv.m_Saturation/255.0;//S=0の時無彩色(白~黒)R=G=Bになる
        double dBrightness=(double)_hsv.m_Brightness/255.0;
        int in;
        double dVariant;//変化する値(r or g or b)
        double dAlwaysLow, dChanging;
        //60で割る理由:RGBが60度周期で上がったり下がったりするから。
        in = (int)floor((double)(_hsv.m_Hue/ 60) );//6通りにわかれる
        dVariant =((double)_hsv.m_Hue / 60.0 ) - (double)in;//区間スタートからどのぐらい離れているのか
        if( !(in & 1)){ dVariant = 1.0 - dVariant;} //inが偶数ならだんだん上がる
 
        dAlwaysLow = dBrightness * ( 1.0 - dSaturation );//常に下に這ってる要素
        dChanging = dBrightness * ( 1.0 - dSaturation * dVariant );//だんだん上がるor 下がる要素
        dBrightness*=255.0;//常にmaxな要素
        dAlwaysLow*=255.0;
        dChanging*=255.0;
        switch( in ){
           //赤=常に255,緑=だんだん上に上がる状態
           case 0: r =(T) dBrightness    ; g =(T) dChanging    ; b =(T) dAlwaysLow    ; break;
           case 1: r =(T) dChanging    ; g =(T) dBrightness    ; b =(T) dAlwaysLow    ; break;
           case 2: r =(T) dAlwaysLow    ; g =(T) dBrightness    ; b =(T) dChanging    ; break;
           case 3: r =(T) dAlwaysLow    ; g =(T) dChanging    ; b =(T) dBrightness    ; break;
           case 4: r =(T) dChanging    ; g =(T) dAlwaysLow    ; b =(T) dBrightness    ; break;
           case 5: r =(T) dBrightness    ; g =(T) dAlwaysLow    ; b =(T) dChanging    ; break;
           default:assert(!"something wrong!");break;
        }
    }

参考にしたサイト[1]

RGBからHSVへ

template<> void color<unsigned char>::toHSV(struct HSV* _hsv){
        unsigned char maxval=*max_element(&(r),&(a));
        unsigned char minval=*min_element(&(r),&(a));
 
        float range=(float)maxval-(float)minval;
        _hsv->m_Brightness=maxval;
        if(_hsv->m_Brightness==0){//黒
            _hsv->m_Hue=0;
            _hsv->m_Saturation=0;
        }else{
            _hsv->m_Saturation=(unsigned char)(255.0f*range/(float)maxval);
            float hue;
            if(maxval==r){
                if(b>g){
                    hue=360.0f-60.0f*(float(b-g))/range;
                }else if(b<g){
                    hue=60.0f*float(g-b)/range;
                }else{
                    hue=0.0;//真っ赤
                }
            }else if(maxval==g){
                if(r>b){
                    hue=120.0f-60.0f*(float(r-b)/range);
                }else if(r<b){
                    hue=120.0f+60.0f*(float(b-r)/range);
                }else{
                    hue=120.0;//真緑
                }
            }else{
                if(g>r){
                    hue=240.0f-60.0f*(float(g-r)/range);
                }else if(g<r){
                    hue=240.0f+60.0f*(float(r-g)/range);
                }else{
                    hue=240.0f;//真っ青
                }
            }
            _hsv->m_Hue=(unsigned int)hue;
        }
 
    }

サポートサイト Wikidot.com