嗚嗚喔學習筆記: OPENCV[RGBtoHSV的應用~~照相機濾鏡效果]

搜尋此網誌

2014年2月10日 星期一

OPENCV[RGBtoHSV的應用~~照相機濾鏡效果]

最近有發現有的相機有濾鏡效果 - 隔離出綠色的物件特別顯示

  
在此我也來試試看用電腦處裡能不能到達相同效果 

後來發現RGB轉成 HSV 格式後  利用H的色調做判別就能達成了

轉換公式 :  


排序色相區域公式
R\geq G\geq B紅色-黃色h_{{Preucil\ circle}}=60^{{\circ }}\cdot {\frac  {G-B}{R-B}}
G>R\geq B黃色-綠色h_{{Preucil\ circle}}=60^{{\circ }}\cdot \left(2-{\frac  {R-B}{G-B}}\right)
G\geq B>R綠色-青色h_{{Preucil\ circle}}=60^{{\circ }}\cdot \left(2+{\frac  {B-R}{G-R}}\right)
\ B>G>R\ 青色-藍色h_{{Preucil\ circle}}=60^{{\circ }}\cdot \left(4-{\frac  {G-R}{B-R}}\right)
B>R\geq G藍色-品紅色h_{{Preucil\ circle}}=60^{{\circ }}\cdot \left(4+{\frac  {R-G}{B-G}}\right)
R\geq B>G品紅色-紅色h_{{Preucil\ circle}}=60^{{\circ }}\cdot \left(6-{\frac  {B-G}{R-G}}\right)
好了來看看結果吧 - 成功把藍色調以外的達到灰階效果了 !!


程式碼:

#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace std ;

void RGBtoHSV( float r, float g, float b, int *h, float *s, float *v )
{
               //轉換成 0 ~ 1 之間
               r = r / 255 ;
               g = g / 255 ;
               b = b / 255 ;
                    
               // RGB HSV 公式
               if (r >= g && g>= b)
                         *h = 60*(g-b)/(r-b);
               if (g > r && r >= b)
                         *h = 60*(2-((r-b)/(g-b)));
               if (g >= b && b > r)
                         *h = 60*(2+ ((b-r)/(g-r)));
               if (b >g && g>r)
                         *h = 60*(4 - (g-r)/(b-r));
               if (b>r && r>=g)
                         *h = 60*(4 + (r-g)/(b-g));
               if (r>=b && b>g)
                         *h = 60*(6-(b-g)/(r-g));


        if( *h < 0 )
                *h += 360;
        else
                *h = *h%360 ;
}



void RGB_HSV(IplImage * temp)
{
    //創造和src一樣的IplImage資料結構
    IplImage * rgb = cvCreateImage( cvGetSize(temp), 8, 3 );
    cvCopy(temp,rgb);
    //創造和src一樣的IplImage資料結構
    IplImage * hsv = cvCreateImage( cvGetSize(rgb), 8, 3 );
    cvCopy(temp,hsv);

    int H=cvGetDimSize(rgb,0);//讀取矩陣高度
    int W=cvGetDimSize(rgb,1);//讀取矩陣寬度
    int sum = 0;
    for(int y = 0 ; y < H ; y++)
         for(int x = 0 ; x < W; x++ )
         {
               int H = 0;
               float S = 0;
               float V = 0;//讀取圖片 hsv
               float R ,G ,B ;
               float GY;
               R = cvGet2D(rgb,y,x).val[2] ;
               G = cvGet2D(rgb,y,x).val[1] ;
               B = cvGet2D(rgb,y,x).val[0] ;
               GY = (R+G+B)/3 ;//RGB
               RGBtoHSV(R,G,B,&H,&S,&V);//轉換
               if( !(H  > 180 && H < 230))//不是藍轉成灰
                  cvSet2D(hsv,y,x,CV_RGB(GY,GY,GY));//寫入
                               
         }        

    cvNamedWindow( "Source-RGB", 0 );
    cvShowImage( "Source-RGB", rgb );
    cvNamedWindow( "Source-HSV", 0 );
    cvShowImage( "Source-HSV", hsv );
}

int main( int argc, char **argv )
{

    IplImage* img = cvLoadImage("people.jpg",1);
    RGB_HSV(img);

    int h = 0;
    float s = 0;
    float v = 0;

    cvWaitKey(0);
    return 0;
}

  

8 則留言:

  1. 可以請問一下 如果是要用H 和S來篩選呢
    我換成
    if(V > 0 )//
    cvSet2D(hsv,y,x,CV_RGB(255,255,255));//
    好像無法篩選 全變成白色

    回覆刪除
    回覆
    1. 不好意思 說錯了 是S和V篩選出黑色部分 其餘變白
      if(V > 50)//

      刪除
    2. 根據 上面的表格 我只有算出H 而已
      如果你要 V 跟S 要另外去找公式喔@@~

      刪除
    3. 請問大概哪部分要加些甚麼

      刪除
    4. void RGBtoHSV ()
      裡面多寫一段 轉換V的公式 *v = .....
      轉換S就寫 *s = .....
      H的部份不用改 這樣HSV 3個值都會算出來了
      看你公式是多少 帶進去*v

      公式:
      http://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4

      刪除
    5. 好的 謝謝你!

      刪除
  2. 你好,可以請問一下公式裡的max和min在code裡面沒有
    那我加入S的公式時max和min要個別在甚麼條件之下帶甚麼值呢

    回覆刪除
    回覆
    1. 假設 R= 100 ; G=20 ; B = 10
      Max = 100 (RGB之中最大值)
      Min = 10 (RGB之中最小值)

      刪除