https://blog.csdn.net/ZYTTAE/article/details/42234989
由于算法的需要,需要把彩色图像的R、G、B值分离出来,OpenCV中正好有split() 和 merge() 函数可以实现。
一、对单独彩色图片的RGB通道分离:
#include <iostream> #include "cv.h" #include "highgui.h" using namespace std; using namespace cv; int main(int argc,char* argv[]) { Mat img = imread("lena.jpg"/*,CV_LOAD_IMAGE_COLOR*/); Mat channel[3]; split(img,channel); imshow("original",img); imshow("B",channel[0]); imshow("G",channel[1]); imshow("R",channel[2]); //set blue channel to 0 channel[0] = Mat::zeros(img.rows,img.cols,CV_8UC1); //merge red and green channels merge(channel,3,img); imshow("R_G_merge",img); waitKey(0); return 1; }
二、对摄像头摄入视频帧的RGB彩色通道分离
int main(int argc,char* argv[]) { VideoCapture cap; cap.open(0); if(!cap.isOpened()) { exit(0); } cap.set(CV_CAP_PROP_FRAME_WIDTH,250); cap.set(CV_CAP_PROP_FRAME_HEIGHT,250); cout << "Frame Width: " << cap.get(CV_CAP_PROP_FRAME_WIDTH) << endl; cout << "Frame Height: " << cap.get(CV_CAP_PROP_FRAME_HEIGHT) << endl; Mat frame; vector<Mat> rgb; cap >> frame; //rgb.push_back( Mat(frame.rows, frame.cols, CV_8UC1)); //rgb.push_back( Mat(frame.rows, frame.cols, CV_8UC1)); //rgb.push_back( Mat(frame.rows, frame.cols, CV_8UC1)); //rgb.push_back( Mat(frame.rows, frame.cols, CV_8UC1)); namedWindow("original", 1); namedWindow("red", 1); namedWindow("green", 1); namedWindow("blue", 1); for(;;) { cap >> frame; imshow("original", frame); split(frame, rgb); imshow("red", rgb.at(2)); imshow("green", rgb.at(1)); imshow("blue", rgb.at(0)); if(waitKey(30) >= 0) break; } waitKey(0); return 1; }
1.split()函数
此函数的作用是将一个图像通道进行分离。
首先看一下split()函数定义:
void split(const Mat& m, vector<Mat>& mv );
参数说明:
第一个参数,const Mat&类型的src,填我们需要进行分离的图像;
第二个参数,vector<Mat>类型的mv,填函数的输出数组或者输出的vector容器,即分离后的图像;
2.merge()函数
merge()函数的功能是split()函数的逆向操作,将多个数组合并成一个多通道的数组。
首先看一下merge()函数定义:
void merge(const vector<Mat>& mv, OutputArray dst );
参数说明:
第一个参数,const <Mat>类型的mv,填需要被合并的vector容器的阵列,这个mv参数中所有的矩阵必须有着一样的尺寸和深度;说白了就是前面被split()函数分离后的图像通道。
第二个参数,保存为合并后的图像;
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { //【0】定义相关变量 Mat srcImage, newImage; //源图像、通道合并后的图像 Mat srcImage_B, srcImage_G, srcImage_R; //R、G、B各个通道 Mat image_H, image_S, image_V; //H、S、V各个通道 vector<Mat> channels_BGR; //vector<Mat>: 可以理解为存放Mat类型的容器(数组) vector<Mat> channels_HSV; //【1】读取原始图像并检查图像是否读取成功 srcImage = imread("D:\\OutPutResult\\ImageTest\\adog.jpg"); //请修改为自己的图像路径 if (srcImage.empty()) { cout << "读取图像有误,请重新输入正确路径!\n"; return -1; } imshow("srcImage源图像", srcImage); //在窗口显示源图像 //【2】对加载的原图像进行通道分离,即把一个3通道图像转换成为3个单通道图像 split(srcImage, channels_BGR); //0通道为B分量,1通道为G分量,2通道为R分量。因为:RGB色彩空间在opencv中默认通道顺序为BGR!!! srcImage_B = channels_BGR.at(0); srcImage_G = channels_BGR.at(1); srcImage_R = channels_BGR.at(2); imshow("srcImage_B通道", srcImage_B); //分别显示R,G,B各个通道图像 imshow("srcImage_G通道", srcImage_G); imshow("srcImage_R通道", srcImage_R); //【3】将BGR颜色空间转换为HSV颜色空间 Mat image_hsv; cvtColor(srcImage, image_hsv, CV_BGR2HSV); imshow("HSV颜色空间图像", image_hsv); //【4】对加载的HSV图像进行通道分离 split(image_hsv, channels_HSV); //0通道为H分量,1通道为S分量,2通道为V分量 image_H = channels_HSV.at(0); image_S = channels_HSV.at(1); image_V = channels_HSV.at(2); imshow("image_H通道", image_H);//分别显示H,S,V各个通道图像 imshow("image_S通道", image_S); imshow("image_V通道", image_V); //【5】将3个单通道重新合并成一个三通道图像 merge(channels_HSV, newImage); imshow("将H,S,V通道合并后的图像", newImage); //【6】保持等待状态 waitKey(0); return 0; }
5.程序说明 看到这里,可能有人会问为什么分离出的通道都是黑白灰,而不是红绿蓝? 原因是分离后为单通道,相当于分离通道的同时把其他两个通道填充了相同的数值。比如红色通道,分离出红色通道的同时,绿色和蓝色被填充为和红色相同的数值,这样一来就只有黑白灰了。那么红色体现在哪呢?可以进行观察,会发现原图中颜色越接近红色的地方在红色通道越接近白色。 ====================分割线=============== 此程序共显示9个窗口。 先将RGB图像通道分离,分别显示R、G、B、单个通道; 后将RGB颜色空间转为HSV空间,将HSV图像通道分离,分别显示H、S、V、单个通道; 最后将H、S、V、单个通道重新合并为3通道图像; =========================END======================