[c++]opencv实现RGB和HSI的相互转换

公式

HSI彩色模型就是色调(hub)、饱和度(saturation)、亮度(intensity)

  • 色调:描述纯色(纯黄色、纯蓝色之类)的颜色属性
  • 饱和度:描述一种纯色被白光稀释的程度
  • 亮度:即强度(类似灰度级的感觉)

以下公式来源论文《Color image enhancement with exact HSI color model

RGB转HSI

I = R + G + B 3 I=\frac{R+G+B}{3} I=3R+G+B
H = { θ ,  if  B ≤ G 36 0 ∘ − θ ,  if  B > G 其 中 θ = cos ⁡ − 1 { 1 2 [ ( R − G ) + ( R − B ) ] [ ( R − G ) 2 + ( R − B ) ( G − B ) ] 1 / 2 } H=\left\{\begin{array}{ll} \theta, & \text { if } B \leq G \\ 360^{\circ}-\theta, & \text { if } B>G \end{array}\right. \\其中 \theta=\cos ^{-1}\left\{\frac{\frac{1}{2}[(R-G)+(R-B)]}{\left[(R-G)^{2}+(R-B)(G-B)\right]^{1 / 2}}\right\} H={θ,360θ, if BG if B>Gθ=cos1{[(RG)2+(RB)(GB)]1/221[(RG)+(RB)]}
S = 1 − 3 min ⁡ ( R , G , B ) R + G + B S=1-\frac{3\min (R, G, B)}{R+G+B} S=1R+G+B3min(R,G,B)

HSI转RGB

  • 0 ∘ ≤ H < 12 0 ∘ 0^{\circ} \leq H<120^{\circ} 0H<120
    B = I ( 1 − S ) R = I [ 1 + S cos ⁡ H cos ⁡ ( 6 0 ∘ − H ) ] G = 3 I − ( R + B ) \begin{aligned} B &=I(1-S) \\ R &=I\left[1+\frac{S \cos H}{\cos \left(60^{\circ}-H\right)}\right] \\ G &=3 I-(R+B) \end{aligned} BRG=I(1S)=I[1+cos(60H)ScosH]=3I(R+B)
  • 12 0 ∘ ≤ H < 24 0 ∘ 120^{\circ} \leq H<240^{\circ} 120H<240
    H = H − 24 0 ∘ R = I ( 1 − S ) G = I [ 1 + S cos ⁡ H cos ⁡ ( 6 0 ∘ − H ) ] B = 3 I − ( R + G ) \begin{aligned} H&=H-240^{\circ}\\ R &=I(1-S) \\ G &=I\left[1+\frac{S \cos H}{\cos \left(60^{\circ}-H\right)}\right] \\ B &=3 I-(R+G) \end{aligned} HRGB=H240=I(1S)=I[1+cos(60H)ScosH]=3I(R+G)
  • 24 0 ∘ ≤ H < 36 0 ∘ 240^{\circ} \leq H<360^{\circ} 240H<360
    H = H − 24 0 ∘ G = I ( 1 − S ) B = I [ 1 + S cos ⁡ H cos ⁡ ( 6 0 ∘ − H ) ] R = 3 I − ( G + B ) \begin{aligned} H &=H-240^{\circ}\\ G & =I(1-S) \\ B &=I\left[1+\frac{S \cos H}{\cos \left(60^{\circ}-H\right)}\right] \\ R &=3 I-(G+B) \end{aligned} HGBR=H240=I(1S)=I[1+cos(60H)ScosH]=3I(G+B)

RGB转HSI代码

Mat RGB2HSI(const Mat & rgb){
    Mat hsi(rgb.rows, rgb.cols, rgb.type());
    float  H=0, S=0, I=0;
    for(int i=0; i < rgb.rows; i++)
        for(int j=0; j < rgb.cols; j++){
            float B = rgb.at<Vec3b>(i, j)[0] / 255.f,
                  G = rgb.at<Vec3b>(i, j)[1] / 255.f,
                  R = rgb.at<Vec3b>(i, j)[2] / 255.f;

            float num = (R - G + R - B) / 2,
                  den = sqrt((R - G) * (R - G) + (R - B) * (G - B)),
                  theta = acos(num/den);
            if(den == 0) H = 0; // 分母不能为0
            else H = B <= G ? theta / (2 * MY_PI) : 1 - theta / (2 * MY_PI);

            float sum = B + G + R;
            if(sum == 0) S = 0;
            else S = 1 - 3 * min(min(B, G), R) / sum;

            I = sum/3.0;

            hsi.at<Vec3b>(i, j)[0] = H*255;
            hsi.at<Vec3b>(i, j)[1] = S*255;
            hsi.at<Vec3b>(i, j)[2] = I*255;
        }
    return hsi;
}

HSI转RGB代码

Mat HSI2RGB(const Mat & hsi){
    Mat rgb(hsi.rows, hsi.cols, hsi.type());
    float  R=0,G=0,B=0;
    for(int i=0; i < hsi.rows; i++)
        for(int j=0; j < hsi.cols; j++){
            float H = hsi.at<Vec3b>(i, j)[0] / 255.f * 2 * MY_PI,
                    S = hsi.at<Vec3b>(i, j)[1] / 255.f,
                    I = hsi.at<Vec3b>(i, j)[2] / 255.f;

            if(H < 120.f * MY_PI / 180.f){
                B=I*(1-S);
                R=I*(1+ S*cos(H)/cos(60.f* MY_PI / 180.f-H));
                G=3*I-R-B;
            }
            else if(H >= 120.f * MY_PI / 180.f && H < 240 * MY_PI / 180.f){
                H-=(120.f * MY_PI / 180.f);
                R=I*(1-S);
                G=I*(1+ S*cos(H)/cos(60.f* MY_PI / 180.f-H));
                B=3*I-R-G;
            }
            else if(H >= 240.f * MY_PI / 180.f){
                H-=(240.f * MY_PI / 180.f);
                G=I*(1-S);
                B=I*(1+ S*cos(H)/cos(60.f* MY_PI / 180.f-H));
                R=3*I-B-G;
            }
            
            rgb.at<Vec3b>(i, j)[0] = B*255;
            rgb.at<Vec3b>(i, j)[1] = G*255;
            rgb.at<Vec3b>(i, j)[2] = R*255;
        }
    return rgb;
}

示例

#include<iostream>
#include <opencv2/opencv.hpp>
#define MY_PI 3.1415
using namespace std;
using namespace cv;
Mat RGB2HSI(const Mat & rgb);
Mat HSI2RGB(const Mat & hsi);
int main(int argc, char * argv[]){
    Mat img = imread("../image/RGB.jpg");
    imshow("origin", img);
    waitKey();
    
    Mat hsi = RGB2HSI(img);
    imshow("hsi", hsi);
    waitKey();

    Mat rgb=HSI2RGB(hsi);
    imshow("rgb", rgb);
    waitKey();
    return 0;
}

在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

OTZ_2333

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值