图像颜色空间

颜色模型

RGB颜色模型是最常见的颜色模型之一,常用于表示和显示图像

图像的其他模型还有YUV、HSV等,分别表示图像的亮度、色度、饱和度等

RBG颜色模型

在OpenCV中于RBG相反,第一个通道是蓝色(B),第二个通道是绿色(G),第三个通道是红色(R)

如果3种颜色分量为0,则表示为黑色,如果3种颜色分量都为最大,则表示为白色

在这个模型上增加第4个通道即为RGBA通道,第4个通道表示颜色的透明度,当没有透明度需求时RGBA模型退化为RGB模型

YUV颜色模型

这3个变量分别表示像素的亮度(Y)、红色分量于亮度的信号差值(U)、蓝色于亮度的差值(V)

这种颜色模型主要用于视频和图像的传输

HSV颜色模型

HSV是色度(Hue)、饱和度(Saturation)和亮度(Value)的简写

色度是色彩的基本属性,就是平常说的颜色

饱和度是指颜色的纯度,饱和度越高色彩越纯和艳丽,饱和度越低,色彩则逐渐地变灰和变暗,取值0~100%

亮度是颜色的明亮程度

相比于RGB模型,HSV模型更加符合人类感知颜色的方式:颜色、深浅和亮暗

Lab模型

Lab模型是一种于设备无关和基于生理特征的颜色模型

L表示亮度(Luminosity),a和b是两个颜色通道,取值是-127~128

a通道数值由小到大对应的颜色是从绿色变成红色,b通道数值由小到大对应的颜色是由蓝色变成黄色

GRAY颜色模型

GRAY模型是一个灰度图像的模型,灰度图像只有单通道,通过0~255表示

255表示白色,灰度图像具有容量小、易于采集、便于传输等优点

颜色模型转换函数cvtColor()

OpenCV提供cvtColor()函数用于实现不同颜色模型之间的相互转换

cvtColor()函数原型:

void cvtColor(InputArray src,
              OutputArray dst,
              int code,
              int dstCn = 0
              )
  • src:待转换颜色模型的原始图像
  • dst:转换颜色模型后的目标图像
  • code:颜色空间转换的标志,如由RBG空间到HSV空间
  • dstCn:目标图像中的通道数,如果参数为0,自动从src和代码中导出通道数

cvtColor()函数颜色模型转换常用标志参数

标志参数 简记 作用
COLOR_BGR2BGRA 0 对RGB图像添加alpha通道
COLOR_BGR2RGB 4 彩色图像通道颜色模型顺序的更改
COLOR_BGR2GRAY 10 彩色图像转成灰度图像
COLOR_GRAY2BGR 8 灰度图像转成彩色图像
COLOR_BGR2YUV 82 RGB模型转成YUV模型
COLOR_YUV2BGR 84 YUV模型转成RGB模型
COLOR_BGR2HSV 40 RGB模型转成HSV模型
COLOR_HSV2BGR 54 HSV模型转成RGB模型
COLOR_BGR2Lab 44 RGB模型转成Lab模型
COLOR_Lab1BGR 56 Lab模型转成RGB模型

示例:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    Mat img = imread("E:\\CLion\\opencv_xin\\cmake-build-debug\\lena.png");
    if (img.empty())
    {
        cout << "Error" << endl;
        return -1;
    }
    Mat gray,HSV,YUV,Lab,img32;
    img.convertTo(img32,CV_32F,1.0/255); //将CV_8U类型转成CV_32F类型
    cvtColor(img32,HSV,COLOR_BGR2HSV);
    cvtColor(img32,YUV,COLOR_BGR2YUV);
    cvtColor(img32,Lab,COLOR_BGR2Lab);
    cvtColor(img32,gray,COLOR_BGR2GRAY);

    imshow("原图",img32);
    imshow("HSV",HSV);
    imshow("YUV",YUV);
    imshow("Lab",Lab);
    imshow("gray",gray);
    waitKey(0);
    return 0;
}

注意:OpenCV的convertTo函数如果第三个参数使用默认的话,就会导致数值只是类型的改变

但在浮点数表示的颜色空间中,数值范围是0-1.0,基本上所有像素都转换成大于1的浮点数,截断后也就是一片白色区域

所以转换成浮点类型要写 1.0/255

数据类型转换函数convertTo()

convertTo()函数原型:

void Mat::convertTo(OutputArry m,
                    int rtype,
                    double alpha = 1,
                    double beta = 0
                    )
  • m:转换类型后输出的图像
  • rtype:转换图像的数据类型
  • alpha:转换过程中的缩放因子
  • beta:转换过程中的偏置因子

该函数用来实现将已有图像转换成指定数据类型的图像,第一个参数用于输出转换数据类型的图像

第二个参数用于声明转换后图像的数据类型,第三个参数和第四个参数用于声明两个数据类型间的转换关系

例如: m(x,y)=saturate_cast\(alpha_(_this)(x,y)+beta);

该转换公式可知,该转换方式就是将原有函数进行线性转换

该函数不仅可以实现不同类型之间的转换,也可以实现同一数据类型中的线性转换

注:

线性变换中最常见的一类就是所谓的矩阵变换

矩阵变换(matrix transformation)指的是这样一种把向量变成向量的对应法则:先给定一个矩阵m×n阶矩阵A,然后对于一个n维向量x,给它左边乘上A,变成Ax,根据乘法行与列的运算法则,这样得到的就是个m维向量。所以它把一个n维向量变成一个m维向量,这样的变换我们称为由矩阵A诱导出的线性变换,简称为矩阵变换。这种变换一定是线性的

矩阵变换在电脑做图中非常有用,在电脑中对一张图片进行拉伸,旋转,翻转等操作,本质就是矩阵变换。因为一张图片是由很多像素点组成的,每一个像素可以看成是一个2维向量。对图片进行操作,就相当于把每个向量都变换一下。比如我想把一张图片等比例拉伸三倍,就相当于把每一个向量都拉伸三倍,方法就是让每一个向量都乘以一个3倍单位矩阵:

于是就会产生以下的效果:

多通道分离函数split()

split()函数有两种重载类型

split()函数原型:

void split(const Mat & src,
           Mat * mvbegin
           )
void split(InputArry m,
           OutputArrayOfArrays mv
           )
  • src:待转换颜色模型的原始图像
  • mvbegin:分离后的单通道图像,为数组形式,数组大小需要于图像的通道数相同
  • m:待分离的多通道图像
  • mv:分离后的单通道图像,为向量(vector)形式

该函数主要是用于将多通道的图像分离成诺干单通道图像

前者第二个参数输出Mat类型的数组,其数组的长度需要于多通道图像的通道数相等并提前定义

后者第二个参数输出一个vector\容器

\

多通道合并函数merge()

merge()函数有两种重载类型

merge()函数原型:

void merge(const Mat *mv,
           size_t count,
           OutputArray dst
           )
void merge(InputArrayOfArrays mv,
           OutputArray dst
           )
  • mv(第一种重载类型):需要合并的图像数组,其中每个图像必须有相同的尺寸和数据类型
  • count:输入的图像数组的长度,其数值必须大于0
  • mv(第二种重载类型):需要合并的图像向量(vector),其中每个图像必须有相同的尺寸和数据类型
  • dst:合并后输出的图像,于mv[0]具有相同的尺寸和数据类型,通道数等于所有输入图像的通道数总和

该函数主要用于将多个图像合并成一个多通道图像,该函数也具有两种不同的函数原型

与split()函数相对应,分别需要输入数组和向量的图像数据

用于合成的图像并非都是单通道的,也可以是多个不同通道数目的图像合并成一个通道更多的图像

虽然图像的通道数目可以不同,但是需要所有图像具有相同的尺寸和数据类型

示例:imshow最多显示4个通道,因此结果在Image Watch中查看

#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
    Mat img = imread("E:\\CLion\\opencv_xin\\cmake-build-debug\\lena.png");
    if (img.empty())
    {
        cout << "Error" << endl;
        return -1;
    }
    Mat HSV;
    cvtColor(img,HSV,COLOR_RGB2HSV);
    Mat imgs0,imgs1,imgs2; //用于存放数组类型的结果
    Mat imgv0,imgv1,imgv2; //用于存放vector类型的结果
    Mat result0,result1,result2; //多通道合并结果
    //输入数组参数的多通道分量和合并
    Mat imgs[3];
    split(img,imgs);
    imgs0 = imgs[0];
    imgs1 = imgs[1];
    imgs2 = imgs[2];
    imshow("RGB-B通道",imgs0);  //显示分离后B通道的像素值
    imshow("RGB-G通道",imgs1);  //显示分离后G通道的像素值
    imshow("RGB-R通道",imgs2);  //显示分离后R通道的像素值
    Mat zero = Mat::zeros(img.rows,img.cols, CV_8UC1);
    imgs[0] = zero;
    imgs[2] = zero;
    merge(imgs,3,result1); //用于还原G通道的真实情况,合并结果为绿色
    imshow("reslit1",result1);
    // 输入vector参数的多通道分离和合并
    vector<Mat> imgv;
    split(HSV,imgv);
    imgv0 = imgv.at(0);
    imgv1 = imgv.at(1);
    imgv2 = imgv.at(2);
    imshow("HSV-H通道",imgv0);  //显示分离后H通道的像素值
    imshow("HSV-S通道",imgv1);  //显示分离后S通道的像素值
    imshow("HSV-V通道",imgv2);  //显示分离后V通道的像素值
    merge(imgv,result2); //合并图像
    imshow("result2",result2);
    waitKey(0);
}

注:彩色图像一般是三通道图像(24位),一个像素需要3个值来表示分别是0-255,例如(255,178,233)。单通道(8位)只能表示一个值,范围0-255,所以都是灰度图

results matching ""

    No results matching ""