addWeighted函数利用公式 dst = src1 * alpha + src2 * beta + gamma; 来计算两个数组(图像)的加权和,换句话说就是两个图像按照一定比例融合,然后生成新的图像。
06_opencv_mat.h
#pragma once
#ifndef _06_OPENCV_MAT_H
#define _06_OPENCV_MAT_H
#include <opencv2/opencv.hpp>
using namespace cv;
struct contrast_parm {
double alpha;
double beta;
double gamma;
};
class QuickDemo {
public:
//滚动条
void tracking_bar_demo(Mat& image);
};
#endif
06_opencv_mat.cpp
#include <iostream>
#include "06_opencv_mat.h"
using namespace std;
static void on_track(int pos, void* userdata)
{
struct contrast_parm cp;
cp.alpha = pos / 50.0; // 0 -- 2
cp.beta = 0.0;
cp.gamma = 0.0;
Mat src = *((Mat*)userdata);
Mat dst = Mat::zeros(src.size(), src.type());
Mat temp = Mat::zeros(src.size(), src.type());
temp = Scalar(pos, pos, pos);
/*
void addWeighted(InputArray src1, double alpha, InputArray src2,
double beta, double gamma, OutputArray dst, int dtype = -1);
addWeighted函数利用公式 dst = src1*alpha + src2*beta + gamma; 来计算两个数组(图像)的加权和,
对于多通道图像,每个通道都是独立处理的。。
(两个图像按照一定比例融合)
Parameters:
src1 – First source array.
第一张源图像
alpha– Weight for the first array elements.
第一张源图像的权重。
src2 – Second source array of the same size and channel number as src1 .
与第一张源图像相同大小和通道数的第二张图像
beta – Weight for the second array elements.
第二张源图像的权重。
dst – Destination array that has the same size and number of channels as the input arrays.
与输入数组具有相同大小和通道数量的目标数组。
gamma – Scalar added to each sum.
加到每个和上的标量。
dtype – Optional depth of the destination array. When both input arrays have the same depth,
dtype can be set to -1, which will be equivalent to src1.depth().(可选参数)
目标阵列的可选深度。当两个输入数组具有相同的深度时,可以将dtype设置为-1,这相当于src1.depth()。
*/
/* 当 alpha 和 beta的值均为1.0时,而 gamma 不为0就变成了上一节的亮度调整 */
addWeighted(src, cp.alpha,temp, cp.beta, cp.gamma,dst);
imshow("对比度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat &image)
{
namedWindow("对比度调整", WINDOW_AUTOSIZE);
//我希望滚动条的调整范围在 0 - 100 之间
//不用设置最小值,默认就是0 - 100
int contrast_value = 0; //初始值设置为0
int max_value = 100;
//参数1 - 给这个滚动条设置一个名字
//参数2 - 滚动条显示在哪个窗体
//参数3 - 通过哪个值来控制,需要传地址过去
//参数4 - 调整的范围是多少,即最大值是多少,最小值为0
//参数5 - 是一个回调函数, TrackbarCallback onChange = 0,默认为NULL(0),
// typedef void (*TrackbarCallback)(int pos, void* userdata);
// 当我们滑动滚动条时,就会产生一个事件(Trackbar Change),系统会捕捉这个事件,
// 然后调用我们写的回调函数TrackbarCallback
//参数6 - void* userdata = 0,是否需要它携带一个外带的数据,这个数据可以是你自己定义的,由void*修饰
createTrackbar("Value Bar:", "对比度调整", &contrast_value, max_value, on_track,(void*)(&image));
on_track(contrast_value,&image);
}
main.c
#include <iostream>
#include "06_opencv_mat.h"
using namespace std;
int main(int argc,char** argv)
{
//使用Mat(matrix -- 矩阵)这种类型来读取通过指定路径的图像信息并存放到变量picture中。
//图像从本质上来说都是二维的数组(矩阵)
Mat picture = imread("雪地.jpeg", IMREAD_COLOR);
if (picture.empty())
{
cout << "could not Load image." << endl;
system("pause");
return -1;
}
// namedWindow("输入窗口",WINDOW_FREERATIO);
imshow("输入窗口", picture);
QuickDemo qd;
qd.tracking_bar_demo(picture);
waitKey(0);
destroyAllWindows();
system("pause");
return 0;
}
运行程序:
注意:这里我只控制一个参数alpha,其他两个参数我都让它为0了。
初始时,
滑动到中间
100%
从上面的示例中,也许还没有体会到图像融合函数 addWeighted 的妙用。下面,再来看这样的一个示例。
需要注意,addWeighted 函数的参数中的第一张图像和第二张图像必须是相同尺寸大小和相同通道数的两张图片。
本示例中,因为选用的两张图片的大小并不一致,所以需要使用 resize() 函数将其中一张图像变成与另一张图像大小一致,为了保证图像的清晰度,我们把大图像(作为背景)给变小。
resize() 函数注意事项:
1、dsize和fx/fy不能同时为0,要么你就指定好dsize的值,让fx和fy空置直接使用默认值,如:
resize(img, imgDst, Size(30,30));
或者设dsize为0,指定好fx和fy的值,比如fx=fy=0.5,那么就相当于把原图两个方向缩小一倍!
2、关于插值方法的选择,正常情况下使用默认的双线性插值就够用了。
几种常用方法的效率是:
最邻近插值 > 双线性插值 > 双立方插值 > Lanczos插值;
但是效率和效果成反比,所以根据自己的情况酌情使用。
3、正常情况下,在使用之前 dst 图像的大小和类型都是不知道的,类型从 src 图像继承而来,大小也是从原图像根据参数计算出来。但是如果你事先已经指定好dst图像的大小,那么你可以通过下面这种方式来调用函数:
resize(src, dst, dst.size(), 0, 0, interpolation);
—————————————————————————————
以上部分内容参考原文链接: https://blog.csdn.net/zfjBIT/article/details/86233509.
#include <iostream>
#include "14_opencv_mat.h"
using namespace std;
void QuickDemo::addWeighted_demo()
{
Mat src1, src2, src1_out,dst;//创建Mat数组,等待存储图片
src1 = imread("晚霞.jpeg", IMREAD_COLOR);//大图
src2 = imread("老虎.jpeg", IMREAD_COLOR);//小图
/*
* 函数功能:图像缩放
* 函数原型:
void resize(InputArray src, OutputArray dst,Size dsize, double fx = 0, double fy = 0,
int interpolation = INTER_LINEAR);
函数参数:
InputArray src - 原图像
OutputArray dst - 输出图像
Size dsize - 目标图像的大小
double fx=0 - 在x轴上的缩放比例
double fy=0 - 在y轴上的缩放比例
int interpolation - 插值方式,有以下四种方式
1、INTER_NN - 最近邻插值
2、INTER_LINEAR - 双线性插值 (缺省使用)
3、INTER_AREA - 使用象素关系重采样,当图像缩小时候,该方法可以避免波纹出现。
当图像放大时,类似于 INTER_NN 方法。
4、INTER_CUBIC - 立方插值。
说明:dsize与(fx和fy)不能同时为零
*/
int cols = src2.cols;
int rows = src2.rows;
resize(src1, src1_out, Size(cols, rows),0, 0, INTER_CUBIC);
//将图1与图2线性混合
//addWeighted 函数的参数中的第一张图像和第二张图像必须是相同尺寸大小和相同通道数的两张图片
addWeighted(src1_out,1,src2, 1, -50, dst);
imshow("src1.jpg", src1);
imshow("src2.jpeg", src2);
imshow("src1_out.jpeg", src1_out);
imshow("dst.jpeg", dst);
}
输入图像 1 (特别大的图,下图没显示全,如果要显示全需要在程序中添加下面这句代码)
namedWindow("输入窗口",WINDOW_FREERATIO);
重新调整大小后的输入图像 1
输入图像 2
按照一定比例进行融合后图像如下:
可见,如果两张图像选择恰当,并且融合比例也选择很好的话,可以做背景特效方面的应用。