zoukankan      html  css  js  c++  java
  • OpenCV实现RGB颜色空间和HSI颜色空间的相互转换

    关于HSI颜色空间参照维基百科:http://zh.wikipedia.org/wiki/HSI%E8%89%B2%E5%BD%A9%E5%B1%AC%E6%80%A7%E6%A8%A1%E5%BC%8F

    核心的转换公式:

    RGB-->HSI

    截图来自中科院刘定生老师的《数字图像处理与分析》课件。

    HSI-->RGB

    具体的数学公式参照冈萨雷斯版《数字图像处理(第三版)》432-434页,中译版的260-261页。

    下面贴代码:

      1 #include "opencv_libs.h"
      2 #include <highgui.h>
      3 #include <cv.h>
      4 #include <math.h>
      5 
      6 /*
      7  * 描述:实现RGB颜色模型到HSI颜色模型之间的相互转换
      8  * 作者:qdsclove(qdsclove@gmail.com)
      9  * 时间:16:01 4/17 星期三 2013
     10  */
     11 
     12 // 将HSI颜色空间的三个分量组合起来,便于显示
     13 IplImage* catHSImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
     14 {
     15     IplImage* HSI_Image = cvCreateImage( cvGetSize( HSI_H ), IPL_DEPTH_8U, 3 );
     16 
     17     for(int i = 0; i < HSI_Image->height; i++)
     18     {
     19         for(int j = 0; j < HSI_Image->width; j++)
     20         {
     21             double d = cvmGet( HSI_H, i, j );
     22             int b = (int)(d * 255/360);
     23             d = cvmGet( HSI_S, i, j );
     24             int g = (int)( d * 255 );
     25             d = cvmGet( HSI_I, i, j );
     26             int r = (int)( d * 255 );
     27 
     28             cvSet2D( HSI_Image, i, j, cvScalar( b, g, r ) );
     29         }
     30     }
     31 
     32     return HSI_Image;
     33 }
     34 
     35 // 将HSI颜色模型的数据转换为RGB颜色模型的图像
     36 IplImage* HSI2RGBImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
     37 {
     38     IplImage * RGB_Image = cvCreateImage(cvGetSize(HSI_H), IPL_DEPTH_8U, 3 );
     39 
     40     int iB, iG, iR;
     41     for(int i = 0; i < RGB_Image->height; i++)
     42     {
     43         for(int j = 0; j < RGB_Image->width; j++)
     44         {
     45             // 该点的色度H
     46             double dH = cvmGet( HSI_H, i, j );
     47             // 该点的色饱和度S
     48             double dS = cvmGet( HSI_S, i, j );
     49             // 该点的亮度
     50             double dI = cvmGet( HSI_I, i, j );
     51 
     52             double dTempB, dTempG, dTempR;
     53             // RG扇区
     54             if(dH < 120 && dH >= 0)
     55             {
     56                 // 将H转为弧度表示
     57                 dH = dH * 3.1415926 / 180;
     58                 dTempB = dI * (1 - dS);
     59                 dTempR = dI * ( 1 + (dS * cos(dH))/cos(3.1415926/3 - dH) );
     60                 dTempG = (3 * dI - (dTempR + dTempB)); 
     61             }
     62             // GB扇区
     63             else if(dH < 240 && dH >= 120)
     64             {
     65                 dH -= 120;
     66                                 
     67                 // 将H转为弧度表示
     68                 dH = dH * 3.1415926 / 180;
     69 
     70                 dTempR = dI * (1 - dS);
     71                 dTempG = dI * (1 + dS * cos(dH)/cos(3.1415926/3 - dH));
     72                 dTempB = (3 * dI - (dTempR + dTempG));
     73             }
     74             // BR扇区
     75             else 
     76             {
     77                 dH -= 240;
     78 
     79                 // 将H转为弧度表示
     80                 dH = dH * 3.1415926 / 180;
     81 
     82                 dTempG = dI * (1 - dS);
     83                 dTempB = dI * (1 + (dS * cos(dH))/cos(3.1415926/3 - dH));
     84                 dTempR = (3* dI - (dTempG + dTempB));
     85             }
     86 
     87             iB = dTempB * 255;
     88             iG = dTempG * 255;
     89             iR = dTempR * 255;
     90 
     91             cvSet2D( RGB_Image, i, j, cvScalar( iB, iG, iR ) );
     92         }
     93     }
     94 
     95     return RGB_Image;
     96 }
     97 
     98 
     99 int main()
    100 {
    101     IplImage* img = cvLoadImage("lena.bmp");
    102 
    103     // 三个HSI空间数据矩阵
    104     CvMat* HSI_H = cvCreateMat( img->height, img->width, CV_32FC1 );
    105     CvMat* HSI_S = cvCreateMat( img->height, img->width, CV_32FC1 );
    106     CvMat* HSI_I = cvCreateMat( img->height, img->width, CV_32FC1 );
    107 
    108     // 原始图像数据指针, HSI矩阵数据指针
    109     uchar* data;
    110 
    111     // rgb分量
    112     byte img_r, img_g, img_b;
    113     byte min_rgb;  // rgb分量中的最小值
    114     // HSI分量
    115     float fHue, fSaturation, fIntensity; 
    116 
    117     for(int i = 0; i < img->height; i++)
    118     {
    119         for(int j = 0; j < img->width; j++)
    120         {
    121              data = cvPtr2D(img, i, j, 0);  
    122              img_b = *data;
    123              data++;
    124              img_g = *data;
    125              data++;
    126              img_r = *data;
    127 
    128              // Intensity分量[0, 1]
    129              fIntensity = (float)((img_b + img_g + img_r)/3)/255;
    130 
    131              // 得到RGB分量中的最小值
    132              float fTemp = img_r < img_g ? img_r : img_g;
    133              min_rgb = fTemp < img_b ? fTemp : img_b;
    134              // Saturation分量[0, 1]
    135              fSaturation = 1 - (float)(3 * min_rgb)/(img_r + img_g + img_b);
    136 
    137              // 计算theta角
    138              float numerator = (img_r - img_g + img_r - img_b ) / 2;
    139              float denominator = sqrt( 
    140                  pow( (img_r - img_g), 2 ) + (img_r - img_b)*(img_g - img_b) );
    141 
    142              // 计算Hue分量
    143              if(denominator != 0)
    144              {
    145                  float theta = acos( numerator/denominator) * 180/3.14;
    146                  
    147                  if(img_b <= img_g)
    148                  {
    149                      fHue = theta ;
    150                  }
    151                  else
    152                  {
    153                      fHue = 360 - theta;
    154                  }
    155              }
    156              else
    157              {
    158                  fHue = 0;
    159              }
    160 
    161              // 赋值
    162              cvmSet( HSI_H, i, j, fHue );
    163              cvmSet( HSI_S, i, j, fSaturation);
    164              cvmSet( HSI_I, i, j, fIntensity );
    165         }
    166     }
    167 
    168     IplImage* HSI_Image = catHSImage( HSI_H, HSI_S, HSI_I );
    169     IplImage* RGB_Image = HSI2RGBImage( HSI_H, HSI_S, HSI_I );
    170 
    171     cvShowImage("img", img);
    172     cvShowImage("HSI Color Model", HSI_Image);
    173     cvShowImage("RGB Color Model", RGB_Image);
    174 
    175     cvWaitKey(0);
    176 
    177     cvReleaseImage( &img );
    178     cvReleaseImage( &HSI_Image );
    179     cvReleaseImage( &RGB_Image );
    180     cvReleaseMat( &HSI_H);
    181     cvReleaseMat( &HSI_S);
    182     cvReleaseMat( &HSI_I);
    183 
    184     cvDestroyAllWindows();
    185 
    186     return 0;
    187 }

    写的比较仓促,代码结构稍微有点混乱。

    测试图像为彩色Lena图,运行结果如下:

    左图为显示出来的HSI颜色模型图,右图为RGB颜色模型图。

    HSI颜色模型为了显示,做了点处理,具体见代码。

  • 相关阅读:
    qmake理解(还可以加入Lex Yacc文件)
    如何在Qt 4程序中优化布局结构(表格讲解,很清楚)
    QList内存释放(看它内部存储的是否是Object,另外还有qDeleteAll)
    Qt工具知多少(一目了然)
    分享个人如何DIY网站的经验
    推荐10款免费而优秀的图表插件
    异步上传文件
    JSON.stringify 方法
    Value Object(值对象)如何使用 EF 进行正确映射
    领域驱动设计(DDD)
  • 原文地址:https://www.cnblogs.com/qdsclove/p/3026488.html
Copyright © 2011-2022 走看看