OpenCv图像处理之颜色通道分离与多通道融合、图像线性融合

OpenCv图像处理之颜色通道分离与多通道融合、图像线性融合

颜色通道分离

在图像中不同的分量存放在不同的通道中,有时为了减少数据占用的内存,提高程序的运行效率,满足特定的需求,需要将颜色通道中的某一个分量分离出来,例如分离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 <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

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 <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

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 <iostream>
#include <opencv2/opencv.hpp>

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);
}

效果显示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_35140742/article/details/119946980