OpenCV4 channel separation split(), channel merge merge(), channel mixing mixChannels()

Article Directory

The default imread function in opencv loads image files, and the loaded image is a three-channel color image, the color space is RGB color space, and the order of channels is BGR (blue, green, red). For three-channel images, OpenCV provides three APIs The function is used to realize channel separation split(), merge(), and mixChannels();

RGB image, in opencv's Mat, pixel data, storage structure and channel separation, the operation relationship diagram is as follows:

insert image description here

1. Channel separation function split()

Function prototype:

The usage of the two function prototypes is the same, and it is used to separate multi-channel images into several single-channel images. The difference between the two function prototypes is that the separated Mat-type single-channel images are stored in Mat-type arrays; Mat mvbegin[3]or Stored in a vector container, vector <Mat> mv;

The split() function in OpenCV 4 has 2 overloaded prototypes:

(1) Function prototype 1: use Mat type array Mat mvbegin[3]to store the separated image;

void split( const Mat &src, Mat *mvbegin )

Input parameters:
  • src: image to be separated, Mat type multi-channel matrix;
  • mvbegin: Separated Mat-type single-channel image, stored in a Mat-type array, , Mat mvbegin[3]when defining the array size, you need to know the number of channels of the original image, array size = number of channels of the original image;
  • The separated images are stored in a Mat-type array Mat mvbegin[3]. The three elements in the array are all Mat-type matrices with the size of image.rows X image.cols, which store the data of the B, G, and R components of the original image in turn, and take the array The elements inside can only be []valued by , not by at();

(2) Function prototype 2: use vector container vector <Mat>to store separated images;

void split( InputArray m, OutputArrayOfArrays mv )

Input parameters:
  • m: image to be separated, Mat type multi-channel matrix;
  • mv: Separated Mat-type single-channel image, stored in a vector container, vector <Mat> mv, does not need to know the number of channels of the original image;
  • The separated image is stored in the vector container. vector <Mat> mvThere are 3 elements in the mv container, and the size of each element is a Mat-type matrix of image.rows X image.cols, which stores the B, G, and R components of the original image in turn. Data, each element can be obtained by []value, or by at()value;

(3) Example:

#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

using namespace cv;
using namespace std;

int main() {
    
    
	// 读取图像,BGR存储在Mat矩阵里
	Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
	if (src.empty()) {
    
    
		printf("could not load image..../n");
		return -1;
	}
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);

	// 用Mat型数组,存储分离后的图像,只能用 [] 访问
	// Mat mvbegin[3];
	// split(src, mvbegin);
	// imshow("B", mvbegin[0]);
	// imshow("G", mvbegin[1]);
	// imshow("R", mvbegin[2]); 

	// 用vector容器,存储分离后的图像,用 [] 访问
	// vector<Mat> mv;
	// split(src, mv);
	// imshow("B", mv[0]);
	// imshow("G", mv[1]);
	// imshow("R", mv[2]);

	// 用vector容器,存储分离后的图像,用 at() 访问
	vector<Mat> mv;
	split(src, mv);
	imshow("B", mv.at(0));
	imshow("G", mv.at(1));
	imshow("R", mv.at(2));

	waitKey();
	destroyAllWindows();
	return 0;
}
operation result:

insert image description here

2. Channel merge function merge()

  • The usage of the two function prototypes is the same, which is used to combine multiple images (single-channel or multi-channel images) into a multi-channel image. The difference between the two function prototypes is that the input is the image data in the form of a Mat array, Mat mvbegin[3]or An image data in the form of a vector container vector <Mat>, which corresponds to the prototype of the split() function;
  • The output of the merging function is a multi-channel image, and its number of channels is the sum of the number of channels of all input images. The images used for merging are not all single-channel, but can also be multi-channel images. The number of channels of the input image can be different. Same, but requires all images to be of the same size and data type;

Function prototype:

(1) Function prototype 1: the input is image data in the form of Mat arrayMat mvbegin[3]

void merge( const Mat *mvbegin, size_tcount, OutputArray dst )

Input parameters:
  • mvbegin: Single-channel or multi-channel images that need to be merged, the input is one image data in the form of a Mat array mvbegin[3];
  • size_tcount: the length of the input image array, its value must be greater than 0;
  • dst: merged image;

(2) Function prototype 2: The input is image data in the form of a vector containervector <Mat>

void merge( InputArrayOfArrays mv, OutputArray dst )

Input parameters:
  • mv: The single-channel or multi-channel images that need to be merged. The input is one image data in the form of a vector container vector <Mat>, where each image must have the same size and data type;
  • dst: The merged image mv[0]has the same size and data type, and the number of channels is equal to the sum of the number of channels of all input images;

(3) Example 1: Use split() to separate the image into three channels, Mat mvbegin[3]store the separated image in a Mat-type array, and then merge the three-channel images with merge(), corresponding to function prototype 1;

#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

using namespace cv;
using namespace std;

int main() {
    
    
	// 读取图像,BGR存储在Mat矩阵里
	Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
	if (src.empty()) {
    
    
		printf("could not load image..../n");
		return -1;
	}
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);


	// 通道分离,用Mat型数组存储分离后的图像
	Mat mvbegin[3];
	split(src, mvbegin);
	Mat BlueChannel = mvbegin[0];
	Mat GreenChannel = mvbegin[1];
	Mat RedChannel = mvbegin[2];

	// 将R通道全部置0
	Mat r = mvbegin[2].clone();
	r.setTo(0);

	// 需要合并的Mat型数组 
	Mat newChannel[3] = {
    
     BlueChannel , GreenChannel , r };

	// 合并通道
	Mat dst;
	merge(newChannel, 3, dst);
	// 显示
	imshow("Merged", dst);

	waitKey();
	destroyAllWindows();
	return 0;
}
operation result:

insert image description here

(4) Example 2: first use split() to separate the three channels of the image, use the vector container to vector <Mat>store the separated image, and then merge the three-channel images with merge(), corresponding to function prototype 2;

#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

using namespace cv;
using namespace std;

int main() {
    
    
	// 读取图像,BGR存储在Mat矩阵里
	Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
	if (src.empty()) {
    
    
		printf("could not load image..../n");
		return -1;
	}
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);


	// 通道分离
	vector<Mat> mv;
	split(src, mv);
	Mat BlueChannel = mv.at(0);
	Mat GreenChannel = mv.at(1);
	Mat RedChannel = mv.at(2);

	// 将B通道全部置0
	Mat b = mv.at(0).clone();
	b.setTo(0);

	vector<Mat> newChannel;
	newChannel.push_back(b);
	newChannel.push_back(GreenChannel);
	newChannel.push_back(RedChannel);

	//通道合并
	Mat mergedImage;
	merge(newChannel, mergedImage);
	// 显示
	imshow("Merged", mergedImage);

	waitKey();
	destroyAllWindows();
	return 0;
}
operation result:

insert image description here

3. Channel mixing mixChannels()

Function prototype:

(1) Function prototype one:

void cv::mixChannels	(
	InputArrayOfArrays		src,
	InputOutputArrayOfArrays 	dst,
	const std::vector< int > 	&fromTo 
)
Input parameters:
  • src: input matrix, all matrices must have the same size and depth;
  • dst: output matrix, the size and depth must be the src[0]same as;
  • fromTo: index pair, indicating which channel of the input matrix, copied to, which channel of the output matrix; for example: {
    0, 2, 1, 1, 2, 0 } means:
    src color channel 0 is copied to dst Color channel 2
    src color channel 1 copied to dst color channel 1
    src color channel 2 copied to dst color channel 0
    insert image description here

(2) Function prototype 2:

In this function prototype:

  • If the input matrix and output matrix are both 1, then it is consistent with the first function prototype;
  • If it is not 1, multiple matrices can be merged, or a matrix can be split into multiple matrices, or other functions;
void cv::mixChannels
(
	const Mat 	*src,
	size_t 		nsrcs,
	Mat		*dst,
	size_t	        ndsts,
	const int       *fromTo,
	size_t 		npairs 
)
Input parameters:
  • src: input matrix, all matrices must have the same size and depth;
  • ndsts: number of matrices;
  • dst: output matrix, the size and depth must be the src[0]same as;
  • fromTo: index pair, indicating which channel of the input matrix, copied to, which channel of the output matrix;
  • ndsts: number of matrices;
  • npairs: the number of index pairs in fromTo;

(3) Example 1: Color channel exchange cyan (255, 255, 0) yellow (0, 255, 255)

The cyan color (255, 255, 0) of the original image is copied to the output image through the specified channel and becomes yellow (0, 255, 255);

Channel correspondence:

The meaning of the index pair from_to[] = { 0, 2, 1, 1, 2, 0, 3, 3 }:

  • Channel 0 of bg, copied to, channel 2 of out[], that is, channel 0 of bgr;
  • Channel 1 of bgra, copied to, channel 1 of out[], that is, channel 1 of bgr;
  • Channel 2 of bgra, copied to, channel 0 of out[], that is, channel 2 of bgr;
  • The 3 channels of bgra, copied to, the 3 channels of out[], that is, the alpha channel of bgr;
    insert image description here
Sample code:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

using namespace cv;
using namespace std;

int main() {
    
    
	// 读取图像,BGR存储在Mat矩阵里
	Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
	if (src.empty()) {
    
    
		printf("could not load image..../n");
		return -1;
	}
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);

	Mat bgra(200, 200, CV_8UC4, Scalar(255, 255, 0, 255));
	Mat bgr(bgra.rows, bgra.cols, CV_8UC3);
	Mat alpha(bgra.rows, bgra.cols, CV_8UC1);

	Mat out[] = {
    
     bgr, alpha };

	int from_to[] = {
    
     0, 2, 1, 1, 2, 0, 3, 3 };
	mixChannels(&bgra, 1, out, 2, from_to, 4);

	imshow("bgra", bgra);
	imshow("bgr", bgr);

	waitKey();
	destroyAllWindows();
	return 0;
}
operation result:

insert image description here

(4) Example 2: Image Segmentation

Split a 4-channel matrix (BGRA image) into a 3-channel matrix (BGR image) and a single-channel matrix (alpha channel image);

Channel correspondence: index pair, int fromTo[] = { 0, 2, 1, 1, 2, 0, 3, 3 }

  • Channel 0 of bgra, copied to, channel 2 of bgr;
  • Channel 1 of bgra, copied to, channel 1 of bgr;
  • Channel 2 of bgra, copied to, channel 0 of bgr;
  • Channel 3 of bgra, copied to, channel 0 of alpha;
Sample code:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

using namespace cv;
using namespace std;

int main() {
    
    

	Mat bgra( 200, 200, CV_8UC4, Scalar(255, 0, 0, 255) );
	Mat bgr( bgra.rows, bgra.cols, CV_8UC3 );
	Mat alpha( bgra.rows, bgra.cols, CV_8UC1 );

	Mat out[] = {
    
     bgr,alpha };
	// 通道对应关系
	int fromTo[] = {
    
     0, 2, 1, 1, 2, 0, 3, 3 };

	mixChannels(&bgra, 1, out, 2, fromTo, 4);
	imshow("bgra", bgra);
	imshow("bgr", bgr);
	imshow("alpha", alpha);

	waitKey();
	destroyAllWindows();
	return 0;
}
operation result:

insert image description here

(5) Example 3: HSV channel acquisition

Use the mixChannels() function to copy the specified channel, and you can see the details of the three channels in the HSV color space;

HSV color space:

  • Hue (hue): represents the color, measured from 0 to 360 degrees (red-yellow-green-cyan-blue-magenta);
  • Saturation (saturation, chroma): refers to the depth of the color. Saturation represents the ratio of gray to hue, and is measured from 0% (gray) to 100% (full saturation). When S=0, there is only gray scale;
  • Value (hue): the brightness of the color, V=1, which includes the three faces of R=1, G=1, and B=1 in the RGB model, and the color represented is brighter;
Sample code:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

using namespace cv;
using namespace std;

int main() {
    
    
	// 读取图像,BGR存储在Mat矩阵里
	Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
	if (src.empty()) {
    
    
		printf("could not load image..../n");
		return -1;
	}
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);

	Mat hsv, dst;
	cvtColor(src, hsv, COLOR_BGR2HSV);
	dst.create( hsv.size(), hsv.depth() );

	//分离Hue,色相通道
	int ch[] = {
    
     0, 0 };
	mixChannels(&hsv, 1, &dst, 1, ch, 1);
	imshow("H channel", dst);

	//分离Saturation,饱和度通道
	int ch1[] = {
    
     1, 0 };
	mixChannels(&hsv, 1, &dst, 1, ch1, 1);
	imshow("S channel", dst);

	//分离Value,色调通道
	int ch2[] = {
    
     2, 0 };
	mixChannels(&hsv, 1, &dst, 1, ch2, 1);
	imshow("V channel", dst);

	waitKey();
	destroyAllWindows();
	return 0;
}
operation result:

insert image description here

Guess you like

Origin blog.csdn.net/qq_33867131/article/details/131602283