在图像中不同的分量存放在不同的通道中,有时为了减少数据占用的内存,提高程序的运行效率,满足特定的需求,需要将颜色通道中的某一个分量分离出来,例如分离RGB中的GREEN通道。在opencv中提供了split()
用来分离通道得到单通道语义信息。
split()源码中的函数原型
CV_EXPORTS void split(const Mat &src, Mat *mvbegin);
split()源码中重点的函数描述
The function cv::split splits a multi-channel array into separate single-channel arrays:
\f[\texttt{mv} [c](I) = \texttt{src} (I)_c\f] .
@param src input multi-channel array.
@param mvbegin output array; the number of arrays must match src.channels(); the arrays themselves are
reallocated, if needed.
上述描述大概意思是该函数对多通道数组分离为单通道数组。并且分离出来的单通道数组mvbegin
个数必须要和输入图片的多通道的通道数src.channerls()
相匹配。
下面我们来看一个示例
#include
#include
#include
using namespace std;
using namespace cv;
//定义单通道图片存储的动态数组
vector<cv::Mat> list_mat_img;
int main() {
Mat img, clone_img;
img = imread("D:/cat.jpg", 3);
clone_img = img.clone();
double scale = 0.5;
//尺度缩小为原来的50%
resize(clone_img, clone_img, Size(int(img.cols * scale), int(img.rows * scale)), 0, 0, INTER_AREA);
//分割通道
split(clone_img, list_mat_img);
//vector.at(index)查找数组下标为index的数据
for (int i = 0; i < list_mat_img.size(); ++i) {
//to_string(object) int强转为string
imshow("single_channel_frame_" + to_string(i), list_mat_img.at(i));
waitKey(0);
}
return 0;
}
有时,当我们分别处理完多个通道后,需要将所有通道合并在一起重新生成RGB或其他颜色空间图像时,就需要opencv中提供的merge()
进行通道融合。
merge()源码中的函数原型
CV_EXPORTS_W void merge(InputArrayOfArrays mv, OutputArray dst);
merge()源码中的函数描述
@param mv input vector of matrices to be merged; all the matrices in mv must have the same
size and the same depth.
@param dst output array of the same size and the same depth as mv[0]; The number of channels will
be the total number of channels in the matrix array.
上述描述大概意思是输入矩阵中的向量用于融合,并且它们都要有相同大小的尺度和深度。而输出数组要与输入向量的尺度和深度相同。它的通道数要和输入矩阵中所有向量通道数的和相同。
下面看一个颜色通道为HSV分离融合的示例
#include
#include
#include
using namespace std;
using namespace cv;
vector<cv::Mat> list_convert_hsv;
int main() {
Mat img, clone_img, merge_img, convert_hsv_img;
img = imread("D:/cat.jpg", 3);
clone_img = img.clone();
cvtColor(clone_img, convert_hsv_img, COLOR_BGR2HSV);
double scale = 0.5;
resize(convert_hsv_img, convert_hsv_img, Size(int(img.cols * scale), int(img.rows * scale)), 0, 0, INTER_AREA);
split(convert_hsv_img, list_convert_hsv);
cv::merge(list_convert_hsv, merge_img);
imshow("merge_img", merge_img);
waitKey(0);
return 0;
}
addWeight()源码中的线性融合公式
dst = src1*alpha + src2*beta + gamma;//dst是融合之后图像
addWeight()源码中的函数原型
CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2,double beta, double gamma, OutputArray dst, int dtype = -1);
addWeight()源码中主要描述
@param src1 first input array.
@param alpha weight of the first array elements.
@param src2 second input array of the same size and channel number as src1.
@param beta weight of the second array elements.
@param gamma scalar added to each sum.
@param dst output array that has the same size and number of channels as the input arrays.
@param dtype optional depth of the output array; when both input arrays have the same depth, dtype
can be set to -1, which will be equivalent to src1.depth().
上述描述大概意思是对各个参数的描述,src1
是待融合的图像1,alpha
是图像1的融合所占权值(小于1时,亮度暗,大于1时候亮度亮),src2
是待融合的图像2,beta
是图像2的融合所占的权值,dst
融合之后的图像,图像尺寸和深度和src1相同,dtype
可选参数,若与src1尺寸和深度相同时,则设置为-1,否则要设置为src1.depth()
下面来看一个示例
#include
#include
using namespace std;
using namespace cv;
void resize_img(Mat &mat, int width, int height, int interpolation);
int main() {
Mat img1, img2;
Mat img1_clone, img2_clone;
img1 = imread("D:/cat.jpg", 3);
img2 = imread("D:/food.jpg", 3);
img1_clone = img1.clone();
img2_clone = img2.clone();
double scale = 0.5;
int weight = int(img1.cols * scale);
int height = int(img1.rows * scale);
int interpolation = INTER_AREA;
Mat merge_img(height, weight, CV_8UC3);
resize(img2_clone, weight, height, interpolation);
resize(img1_clone, weight, height, interpolation);
imshow("img1", img1_clone);
waitKey(0);
imshow("img2", img2_clone);
waitKey(0);
addWeighted(img1_clone, 0.8, img2_clone, 0.2, 0, merge_img, -1);
imshow("merge_img", merge_img);
waitKey(0);
return 0;
}
void resize_img(Mat &mat, int width, int height, int interpolation) {
resize(mat, mat, Size(width, height), 0, 0, interpolation);
}