OpenCV学习笔记(八)--颜色空间及转换

颜色空间

要用三种或更多的特征来指定一种颜色,有许多的方法被称为颜色空间或者颜色模型。
如何选取其中一种方法来表示一副图像要依赖于执行的运算。
不同的颜色空间的转换,Opencv提供方法

void cvtColor(InputArray src, Output dst, int code, int dstCn=0)

code : 这是颜色空间的转换代码。例如COLOR_BGR2GRAY
dstCn:这是目标图形的通道数,如果为0或省略,则通道数有src和code自动产生。

常用的颜色空间:

RGB颜色空间

在RGB中,一幅图像有三个独立的图像平面或通道组成:红,绿,蓝(以及第四个通道透明度)。
如下代码展示了,加载RGB图像,并在灰度空间和颜色空间中拆分并显示每个特定的通道。

void split(InputArray m, OutputArrayOfArrays mv)
1. 将图像的每个通道保存在mv中
2. mv声明为vector mv
void merge(InputArrayOfArrays mv, OutputArray dst)
1. 将mv和并称一个图像dst

#include "opencv2/opencv.hpp"
#include "opencv2/opencv_modules.hpp"
#include "opencv2/highgui/highgui.hpp"
#include<iostream>
using namespace cv;
using namespace std;
vector<Mat> showSeqratedChannels(vector<Mat> channels);
int  main() {
    Mat image = imread("test.jpg");
    vector<Mat> channels;
    split(image, channels);         //分割图像
    //用灰度级显示通道
    namedWindow("Origin", WINDOW_NORMAL);
    imshow("Origin", image);
    namedWindow("Blue channel",WINDOW_NORMAL);
    imshow("Blue channel", channels[0]);
    namedWindow("Green channel", WINDOW_NORMAL);
    imshow("Green channel", channels[1]);
    namedWindow("Red channel", WINDOW_NORMAL);
    imshow("Red channel", channels[2]);
    cout << channels.size() << endl;

    //显示BGR中的通道
    vector<Mat> separated = showSeqratedChannels(channels);
    namedWindow("Blue channel", WINDOW_AUTOSIZE);
    imshow("Blue channel", separated[0]);
    namedWindow("Green channel", WINDOW_AUTOSIZE);
    imshow("Green channel", separated[1]);
    namedWindow("Red channel", WINDOW_AUTOSIZE);
    imshow("Red channel", separated[2]);
    cout << separated[0].size() << endl;
    cout << separated[0].rows << endl;
    cout << separated[0].cols << endl;
    waitKey();
}
//这个函数,将channels中的每个波段分别加上两个波段,形参三个RGB通道
//其余两个通道介入的都是0像素。
vector<Mat> showSeqratedChannels(vector<Mat> channels) {
    vector<Mat> seqaratedChannels;
    for (int i = 0; i < 3; i++) {
        Mat zero = Mat::zeros(channels[0].rows, channels[0].cols, channels[0].type());
        vector<Mat>aux;
        for (int j = 0; j < 3; j++) {
            if (j == i) aux.push_back(channels[i]);
            else
                aux.push_back(zero);
        }
        Mat chann;
        merge(aux, chann);             //chann为输出的容器
        seqaratedChannels.push_back(chann);
    }
    return seqaratedChannels;
}

原始的图像如下所示:

这里写图片描述

用灰度级显示通道:

这里写图片描述

显示BGR中的通道:

这里写图片描述

灰度图像与RGB图像的转变。
RGB[A]转换为灰度:Y=0.299*R+0.587*G+0.114*B;
cvtColor方法的缺陷就是是的原始图像的对比度丢失,从上面的式子中可以看到。

//利用opencv函数将彩色变为灰度图像
cvtColor(image,imageGray,COLOR_BGR2GRAY);

CIE XYZ颜色空间

CIE XYZ系统用一个亮度分类Y来描述颜色,他与人类视觉的亮度灵敏度和两个附加通道X,Z相关。
RGB和CIE XYZ之间的转换颜色空间代码是:

COLOR_BGR2XYZ
COLOR_RGB2XYZ
COLOR_XYZ2BGR
COLOR_XYZ2RGB

它与RGB的转换公式如下图所示:

这里写图片描述
下面代码是将RGB图像转换成XYZ空间,以及在灰度空间和颜色空间中拆分并显示特定通道。

#include "opencv2/opencv.hpp"
#include "opencv2/opencv_modules.hpp"
#include "opencv2/highgui/highgui.hpp"
#include<iostream>
using namespace cv;
using namespace std;
vector<Mat> showSeqratedChannels(vector<Mat> channels);
int  main() {
    Mat image = imread("cute.jpg");
    namedWindow("Origin", WINDOW_AUTOSIZE);
    imshow("Origin", image);
    cvtColor(image, image, CV_BGR2XYZ);
    namedWindow("Origin_XYZ", WINDOW_AUTOSIZE);
    imshow("Origin_XYZ", image);
    vector<Mat> channels;

    split(image, channels);         //分割图像
    //用灰度级显示通道

    namedWindow("Blue channel_GRAY",WINDOW_AUTOSIZE);
    imshow("Blue channel_GRAY", channels[0]);
    namedWindow("Green channel_GRAY", WINDOW_AUTOSIZE);
    imshow("Green channel_GRAY", channels[1]);
    namedWindow("Red channel_GRAY", WINDOW_AUTOSIZE);
    imshow("Red channel_GRAY", channels[2]);
    cout << channels.size() << endl;

    显示BGR中的通道
    vector<Mat> separated = showSeqratedChannels(channels);
    for (int i = 0; i < 3; i++) {
        cvtColor(separated[i], separated[i], COLOR_XYZ2BGR);     //在将其转成BGR中显示通道
    }
    namedWindow("Blue channel", WINDOW_AUTOSIZE);
    imshow("Blue channel", separated[0]);
    namedWindow("Green channel", WINDOW_AUTOSIZE);
    imshow("Green channel", separated[1]);
    namedWindow("Red channel", WINDOW_AUTOSIZE);
    imshow("Red channel", separated[2]);
    cout << separated[0].size() << endl;
    cout << separated[0].rows << endl;
    cout << separated[0].cols << endl;
    waitKey();
}
vector<Mat> showSeqratedChannels(vector<Mat> channels) {
    vector<Mat> seqaratedChannels;
    for (int i = 0; i < 3; i++) {
        Mat zero = Mat::zeros(channels[0].rows, channels[0].cols, channels[0].type());
        vector<Mat>aux;
        for (int j = 0; j < 3; j++) {
            if (j == i) aux.push_back(channels[i]);
            else
                aux.push_back(zero);
        }
        Mat chann;
        merge(aux, chann);             //chann为输出的容器
        seqaratedChannels.push_back(chann);
    }
    return seqaratedChannels;
}

这里写图片描述
这里写图片描述
这里写图片描述

YCrCb颜色空间

该颜色空间广泛的用于视频压缩和图像压缩方案,不能算是纯粹的颜色空间,因为它是RGB颜色空间的一种解码方式。
该颜色空间广泛的应用于MPEG和JPEG等视频和图像压缩方案。

Y表示亮度
Cr : RGB空间R通道和Y差值
Cb: RGB空间B通道和Y差值

RGB和YCrCb之间的转换颜色空间代码是:

COLOR_BGR2YCrCb
COLOR_RGB2YCrCb
COLOR_YCrCb2BGR
COLOR_YCrCb2RGB

计算的过程如下图所示:

这里写图片描述

同理,将一副RGB图像转换成YCrCb空间,以及在灰度空间和颜色空间中拆分并显示特定通道代码同上述非常类似,因此不再重复。

效果如下图所示:

这里写图片描述
这里写图片描述
这里写图片描述

HSV颜色空间

HSV颜色空间属于面向色度的颜色坐标系的一种,这种颜色模型接近于人类颜色感知的仿真模型,而在其他颜色模型中,例如RGB,一副图像被视为3中基色的叠加。

H(hue): 色调,取值[0,1],对应颜色的种类,颜色从红,通过黄,绿,蓝,紫和黑到红。
S(saturation):饱和度,取值[0,1],对应预色调种类从不饱和(灰度梯度)到完全饱和(无白色)。
V(value):取值[0,1],对应色彩有暗变亮。

OpenCV中使用在RGB,HSV之间变换的颜色空间转换代码:

COLOR_BGR2HSV
COLOR_RGB2HSV
COLOR_HSV2BGR
COLOR_HSV2RGB

如果src图像格式是8位或16位,则首先转成一个浮点格式,将其值变化成0到1之间,在计算:

这里写图片描述

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值