Article Directory
-
- 1. Channel separation function split()
- 2. Channel merge function merge()
-
- Function prototype:
-
- (1) Function prototype 1: the input is the image data `Mat mvbegin[3]` in the form of a Mat array
- (2) Function prototype 2: The input is the image data in the form of vector container `vector <Mat>`
- (3) Example 1: First use split() to separate the three channels of the image, use the Mat type array `Mat mvbegin[3]` to store the separated image, and then merge the three-channel images with merge(), corresponding to function prototype 1 ;
- (4) Example 2: first use split() to separate the three channels of the image, use the vector container `vector <Mat>` to store the separated image, and then use merge() to merge the three-channel images, corresponding to function prototype 2;
- 3. Channel mixing mixChannels()
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:
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 byat()
;
(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> mv
There 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 byat()
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:
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 containervector <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:
(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:
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
(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;
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:
(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:
(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;
}