一.知识点 1.RGB模式 RGB模式是基于自然界中3种基色光的混合原理,将红(Red)、绿(Green)和蓝(Blue)3中基色按照从0(黑)到255(白色)的亮度值在每个色阶中分配,从而指定其色彩。 3个字节 每个字节8位 表示0-255 黑色(0,0,0);白色(255,255,255);第一个字节B蓝色通道,蓝色为(255,0,0),第二个字节G绿色通道,绿色为(0,255,0);第三个字节R红色通道,红色为(0,0,255); 当3种基色的亮度值相等时,产生灰色 0:黑色 255:白色
2.HSV模式 H:色调,范围0~360,每隔60度表示一种基本颜色(其他度数在是相邻的基本度数之间的颜色):红(RGB(255,0,0))->黄(RGB(255,255,0))->绿(RGB(0,255,0))->青(RGB(0,255,255))->蓝(RGB(0,0,255))->紫(RGB(255,0,255))->红 S:饱和度,范围0~1,是白色(RGB(255,255,255))~根据H计算得到颜色 之间的比例 V:亮度,范围0~1,是黑色(RGB(0,0,0))~根据HS计算得到颜色 之间的比例
3.YUV模式 将亮度与色度分离 1)Y:亮度信息 即灰度值 是通过RGB输入信号来创建的,方法是将RGB信号的特定部分叠加到一起 2)UV:色彩信息 定义了颜色的两个方面-色调与饱和度,分别用Cr和CB来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而CB反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。。通过运算,YUV三分量可以还原出R(红),G(绿),B(蓝)。 3)YUV不像RGB那样要求三个独立的视频信号同时传输,所以YUV方式传送占用极少的频宽。 4)存储格式:YUV4:4:4,YUV4:2:2,YUV4:2:0 eg: (1) YUV 4:4:4采样,每一个Y对应一组UV分量。 (2) YUV 4:2:2采样,每两个Y共用一组UV分量。 (3) YUV 4:2:0采样,每四个Y共用一组UV分量。 二.代码 R G B H S V Y U V 九个通道分别显示代码
#include <opencv2/opencv.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace std; using namespace cv; int main() { Mat img_h, img_s, img_v, imghsv; Mat Image; Image = imread("D://Libs//opencv310//opencv//sources//samples//data//aero1.jpg"); //原图 vector<cv::Mat> hsv_vec; cvtColor(Image, imghsv, CV_BGR2HSV); // 分割hsv通道 split(imghsv, hsv_vec); img_h = hsv_vec[0]; img_s = hsv_vec[1]; img_v = hsv_vec[2]; img_h.convertTo(img_h, CV_32F); img_s.convertTo(img_s, CV_32F); img_v.convertTo(img_v, CV_32F); double max_s, max_h, max_v; minMaxIdx(img_h, 0, &max_h); minMaxIdx(img_s, 0, &max_s); minMaxIdx(img_v, 0, &max_v); //输入RGB图像,转换成YUV并分离 Mat imageY(Image.rows, Image.cols, 1); Mat imageU(Image.rows, Image.cols, 1); Mat imageV(Image.rows, Image.cols, 1); Mat imageYUV; cvtColor(Image, imageYUV, CV_BGR2YUV); vector<Mat> mv; split(Image, (vector<Mat>&)mv); imageY = mv[0].clone(); imageU = mv[1].clone(); imageV = mv[2].clone(); //bgr for (int i = 0; i < 3; i++) { Mat bgr(Image.rows, Image.cols, CV_8UC3, Scalar(0, 0, 0)); Mat temp(Image.rows, Image.cols, CV_8UC1); Mat out[] = { bgr }; int from_to[] = { i, i }; mixChannels(&Image, 1, out, 1, from_to, 1); //分别显示bgr imshow("bgr", bgr); waitKey(); } //显示 imshow("Y", imageY); waitKey(); imshow("U", imageU); waitKey(); imshow("Y_V", imageV); waitKey(); imshow("h", img_h); waitKey(); imshow("s", img_s); waitKey(); imshow("h_v", img_v); waitKey(); return 0; }三.函数分析 1**.split函数用法** 1)功能:通道分离,把一个彩色图像分割成3个通道 2)函数原型: void split(const Mat& src,Mat *mvBegin) 第一个参数为要进行分离的图像矩阵 第二个参数可以是Mat数组的首地址,或者一个vector对象 3)eg:
vector<Mat> Image; Mat aImage[3]; split(src, aImage); //利用数组分离 split(src, Image); //利用vector对象分离 imshow("B",Image[0]); imshow("G",Image[1]); imshow("R",Image[2]);注意: 不是所有格式的Mat型数据都能被使用保存为图片,目前OpenCV主要只支持单通道和3通道的图像,并且要求深度为8bit和16bit无符号(即CV_16U),所以其他一些数据类型是不支持的,比如说float型等。 如果Mat类型数据的深度和通道数不满足这些的要求,则需要使用convertTo()函数和cvtColor()函数来进行转换。 convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到imwrite()函数能够接受的类型。 而cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。 另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中
2.cvtColor()函数 1)功能:色彩图像转化为灰度图像,即转换不同通道的Mat。 2)原型
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 )3)参数: src:原图 dst:转化后的图像 code:是一个掩码,表示由src到dst之间是怎么转的,比如是彩色转为灰 度,还是彩色转为HSI模式 code的模式包括: CV_RGB2GRAY:<彩色图像—>灰度图像> CV_BGR2YCrCb, CV_RGB2YCrCb, CV_YCrCb2BGR, CV_YCrCb2RGB BGR空间—>YChCb空间 CV_BGR2HSV, CV_RGB2HSV, CV_HSV2BGR, CV_HSV2RGB RGB空间—>HSV空间 dst:图像的波段数,这个值默认是0,它可以从参数code中推断
3.Mat.convertTo()的用法 1)原型:oclMat::convertTo(oclMat& m, int rtype, double alpha=1, double beta=0) m:转为目标数据类型的矩阵 rtype: 指定目标数据类型,或者是depth(通道数),如果rtype:是负 值,那么目标矩阵的数据类型和源矩形的数据类型是一致的 alpha:基于尺度的变化值 beta:在尺度上的加和 转换数据类型不同的Mat,可以将类似float型的Mat转换到imwrite()可以读取的类型。