OpenCV 颜色空间RGB 到HSI CMYK的转换 C++

从RGB 到 HSI 的空间转换


   给定一幅RGB彩色格式的图像,每个RGB像素的H分量可用下式得到:

OpenCV 颜色空间RGB 到HSI CMYK的转换 C++_第1张图片

其中\Theta 等于

OpenCV 颜色空间RGB 到HSI CMYK的转换 C++_第2张图片

饱和度分量由下式给出:

强度分量下式得出:

上式已假定RGB归一化到【0-1】,且角度是根据HSI空间的红轴来度量。色调可以用6.2-2的结果除以360度归一化到[0-1];

如果RGB已经归一化到[0-1],那其他两个分量已经归一化到0-1了。

 

从 RGB 到 CMYK 转换

蓝绿色,深红色,黄色是光的二次色,换句话说,是颜料的颜色;

转换公式如下:

OpenCV 颜色空间RGB 到HSI CMYK的转换 C++_第3张图片

这里假定RGB都归一化到[0-1]了。

K是指黑色,这里

 

草莓转换 CMYK结果:

HSI结果:

OpenCV 颜色空间RGB 到HSI CMYK的转换 C++_第4张图片

RGB单独通道结果:

OpenCV 颜色空间RGB 到HSI CMYK的转换 C++_第5张图片

 

代码实现:

#include
#include
#include
#include

#define PI 3.1416
#define min(a,b) (a

using namespace std;
using namespace cv;

int rgb2hsi(Mat &image,Mat &hsi)
{
    if(!image.data){
        cout<<"Miss Data"<         return -1;
    }
    int nl = image.rows;
    int nc = image.cols;
    if(image.isContinuous()){
        nc = nc*nl;
        nl = 1;
    }
    for(int i = 0;i < nl;i++){
        uchar *src = image.ptr(i);
        uchar *dst = hsi.ptr(i);
        for(int j = 0;j < nc;j++){
            float b = src[j*3]/255.0;
            float g = src[j*3+1]/255.0;
            float r = src[j*3+2]/255.0;
            float num = (float)(0.5*((r-g)+(r-b)));
            float den = (float)sqrt((r-g)*(r-g)+(r-b)*(g-b));
            float H,S,I;
            if(den == 0){    //分母不能为0
                H = 0;
            }
            else{
                double theta = acos(num/den);
                if(b <= g)
                    H = theta/(PI*2);
                else
                    H = (2*PI - theta)/(2*PI);
            }
            double minRGB = min(min(r,g),b);
            den = r+g+b;
            if(den == 0)    //分母不能为0
                S = 0;
            else
                S = 1 - 3*minRGB/den;
            I = den/3.0;
            //将S分量和H分量都扩充到[0,255]区间以便于显示;
            //一般H分量在[0,2pi]之间,S在[0,1]之间
            dst[3*j] = H*255;
            dst[3*j+1] = S*255;
            dst[3*j+2] = I*255;
        }
    }
    return 0;
}

uchar minimum(uchar a, uchar b)
{
    return a <= b ? a : b;
}

cv::Mat bgr2cmyk(cv::Mat& rgb)
{
    cv::Mat cmyk = cv::Mat::zeros(rgb.rows, rgb.cols, CV_8UC4);

    int pixel_num = rgb.rows * rgb.cols;

    for (int i = 0; i < pixel_num; i++)
    {
        uchar c = 255 - rgb.data[3 * i + 2];
        uchar m = 255 - rgb.data[3 * i + 1];
        uchar y = 255 - rgb.data[3 * i + 0];
        uchar K = minimum(minimum(c, m), y);


        cmyk.data[4 * i + 0] = c;
        cmyk.data[4 * i + 1] = m;
        cmyk.data[4 * i + 2] = y;
        cmyk.data[4 * i + 3] = K;
    }
    return cmyk;
}


int rgb2cmyk( Mat &image,Mat &cmyk)
{
    if(!image.data){
        cout<<"Miss Data"<         return -1;
    }
    int nl = image.rows;    //行数
    int nc = image.cols;    //列数
    if(image.isContinuous()){    //没有额外的填补像素
        nc = nc*nl;
        nl = 1;                    //It is now a 1D array
    }
    //对于连续图像,本循环只执行1次
    for(int i=0;i         uchar *data = image.ptr(i);
        uchar *dataCMYK = cmyk.ptr(i);
        for(int j = 0;j < nc;j++){
            uchar c = 255 - data[3*j+2];
            uchar m = 255 - data[3*j+1];
            uchar y = 255 - data[3*j];
            uchar k = min(min(c,m),y);

            dataCMYK[4*j] = c ;
            dataCMYK[4*j+1] = m ;
            dataCMYK[4*j+2] = y  ;
            dataCMYK[4*j+3] = k;
        }
    }
    return 0;
}
int main(){
    Mat img = imread("630.tif");
    if(!img.data){
        cout<<"Miss Data"<         return -1;
    }
    resize(img,img,Size(), 0.5, 0.5);
    Mat img_cmyk,img_hsi;
    Mat img_hsv;
    vector vecRgb,vecHsi,vecHls,vecHsv,vecCmyk;
    img_hsv.create(img.rows,img.cols,CV_8UC3);
    Mat img_hls;
    img_hls.create(img.rows,img.cols,CV_8UC3);
    //生成与输入图像尺寸一样的4通道cmyk图像
    split(img, vecRgb);
    imshow( " src_b", vecRgb[0]);
    imshow( " src_g", vecRgb[1]);
    imshow( " src_r", vecRgb[2]);

    img_cmyk.create(img.rows,img.cols,CV_8UC4);
    img_hsi.create(img.rows,img.cols,CV_8UC3);
    rgb2cmyk(img,img_cmyk);
    rgb2hsi(img,img_hsi);
    cvtColor(img,img_hsv,CV_BGR2HSV);
    cvtColor(img,img_hls,CV_BGR2HLS);
    split(img_cmyk,vecCmyk);
    split(img_hsi,vecHsi);
    cout<<"pixel(0,0) in RGB"<     for(int i=0;i<3;i++){
        cout<<(int)img.at(0,0)[i]<<" ";
    }
    cout<     for(int i=0;i<4;i++){
        cout<<(int)img_cmyk.at(0,0)[i]<<" ";
    }
    int a = min(min(24,32),16);
    cout<     namedWindow("RGB_Image");
    namedWindow("CMYK_Image");
    //namedWindow("HSV_Image");
    //namedWindow("HLS_Image");
    namedWindow("HSI_Image");
    namedWindow("CMYK_C");
    namedWindow("CMYK_M");
    namedWindow("CMYK_Y");
    namedWindow("CMYK_K");
    imshow("CMYK_C",vecCmyk[0]);
    imshow("CMYK_M",vecCmyk[1]);
    imshow("CMYK_Y",vecCmyk[2]);
    imshow("CMYK_K",vecCmyk[3]);
    imshow("HSI_H",vecHsi[0]);
    imshow("HSI_S",vecHsi[1]);
    imshow("HSI_I",vecHsi[2]);
    imshow("RGB_Image",img);
    imshow("CMYK_Image",img_cmyk);
    //imshow("HSV_Image",img_hsv);
    //imshow("HLS_Image",img_hls);
    imshow("HSI_Image",img_hsi);
    waitKey();
    return 0;
}

 

你可能感兴趣的:(OpenCV,C++,数字图像处理,OpenCV,C++数字图像处理,冈萨雷斯第三版)