目录
[3.代码,copyto 图层叠加](#3.代码,copyto 图层叠加)
[4. 创建ROI - operator()](#4. 创建ROI - operator())
[5. 复制图像 - copyTo()](#5. 复制图像 - copyTo())
[4.addWeighted 方法对图像数据进行图像叠加](#4.addWeighted 方法对图像数据进行图像叠加)
[5.代码,addweighted 图层叠加](#5.代码,addweighted 图层叠加)
1.图像叠加功能简介
图像叠加顾名思义就是在原图像里面,添加一些其他图像数据,最常见的就是在原图像中添加一些水印图像。这些水印图像可以是:时问戳、L0G0图像等等。
2.OPENCV中图像叠加常用的API
在OPENCV中,图像叠加有许多的API,我们就来介绍最常用的几个API。
2.1.copyTo方法进行图像叠加
copyTo是非常常用的图像叠加方法,这个方法关键是要先选取一个Rect的兴趣区域,然后再调用copyTo的方法把感兴趣区域添加到原图像,copyTo的AP定义如下,它的工作流程如上图,一般而言logo的图像大小要小于原图像:
void copyTof(OutputArray m ) const
传递参数:OutputArray是可感兴趣的图像二进制数据,具体实现的代码如下



3.代码,copyto 图层叠加
cs
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv; //Must Need Write cv
using namespace std;
int main()
{
Mat mat = Mat(400,600,CV_8UC3,Scalar(218,211,146));
imwrite("src.jpg",mat);
Mat mat1 = Mat(100,200,CV_8UC3,Scalar(255,0,0));
std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY,40};
imwrite("logo.jpg",mat1,params);
Mat src_img = imread("src.jpg");
Mat logo_img = imread("logo.jpg");
Mat logo_img_roi = src_img(Rect(0,0,logo_img.cols,logo_img.rows));
logo_img.copyTo(logo_img_roi);
imwrite("src_copyto.jpg",src_img);
return 0;
}
注:
1.创建矩形rect()
cs
Rect(int x, int y, int width, int height)
// 或
Rect(Point pt, Size sz) // 点+尺寸的方式
- x - 左上角的x坐标
- 含义 :矩形左上角在图像中的列位置(水平方向)
- 范围:0 ≤ x < 图像宽度
- 作用:确定矩形开始的位置
- y - 左上角的y坐标
- 含义:矩形左上角在图像中的行位置(垂直方向)
- 范围:0 ≤ y < 图像高度
- 作用:确定矩形开始的行
- width - 矩形的宽度
- 含义:矩形的水平尺寸(列数)
- 范围:> 0,且 x + width ≤ 图像宽度
- 作用:确定矩形在水平方向包含多少像素
- height - 矩形的高度
- 含义:矩形的垂直尺寸(行数)
- 范围:> 0,且 y + height ≤ 图像高度
- 作用:确定矩形在垂直方向包含多少像素
4. 创建ROI - operator()
(Region of Interest)
cs
Mat logo_image_roi = src_image_pic(rect(...));
- 操作符 :
Mat::operator()(const Rect& roi) - 作用:从原图中提取一个感兴趣区域
- 参数 :
Rect对象(定义要提取的区域) - 返回值 :新的Mat对象,但共享原图的数据 (不是副本)
- 特点 :修改roi会修改原图
5. 复制图像 - copyTo()
cs
logo_image_pic.copyTo(m: logo_image_roi);
- 函数 :
Mat::copyTo() - 作用 :将图像复制到目标矩阵中
- 参数 :
m- 目标矩阵 - 特点:如果目标矩阵已有数据,会先释放原数据
4.addWeighted 方法对图像数据进行图像叠加
addWeighted也是一种常用的图像叠加方法,它的原理是执行两个图像的加权和操作。这个函数可以创建一副新的图像,这其中包括两幅输入图像的加权数据,这个函数通常用在图像的融合还有混合,它和 copyTo 的不同在于,adaWeighted 可以修改图片的清晰度和渐变度,而 cpyTo 不行。下面我们来看看这个函数的API定义:
CV_EXPORTS_W void addWeighted(inputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);
- 第一个参数:src1,第一个输入的图像
- 第二个参数:alpha,第一个输入图像的权重值,是一个双精度浮点数
- 第三个参数:src2,第二个输入图像
- 第四个参数:beta,第二个输入图像的权重,是一个双精度浮点数
- 第五个参数:gamma加权和的可选标量,通常是一个双精度浮点数,默认为0
- 第六个参数:dst输出图像,这里是存储加权图像的结果
- 第七个参数:输出图像的类型,默认是-1,表示的是输入图像和输出图像类型一致
关于 addWeighted 加权,一般也会用数学公式进行表示,这个数学公式如下:
dst = src1 *alpha + src2 * beta + gamma
下面是 addWeighted 的DEMO代码,在使用 addWeighted 分为两种情况,一种是两个融合图像的尺寸相同,另外一种是两个图像不一致的情况
5.代码,addweighted 图层叠加
cs
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv; //Must Need Write cv
using namespace std;
int main()
{
Mat mat = Mat(400,600,CV_8UC3,Scalar(218,211,146));
imwrite("src.jpg",mat);
Mat mat1 = Mat(100,200,CV_8UC3,Scalar(255,0,0));
std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY,40};
imwrite("logo.jpg",mat1,params);
Mat src_img = imread("src.jpg");
Mat logo_img = imread("logo.jpg");
Mat logo_img_roi = src_img(Rect(0,0,logo_img.cols,logo_img.rows));
logo_img.copyTo(logo_img_roi);
imwrite("src_copyto.jpg",src_img);
if(logo_img.size != src_img.size)
{
Mat img_roi = src_img(Rect(0,100,logo_img.cols,logo_img.rows));
double alpha = 0.4;
double beta = 1 - alpha;
int gamma = 0;
addWeighted(img_roi,alpha,logo_img,beta,gamma,img_roi);
imwrite("addweighter_notsize.jpg",src_img);
}
else
{
double alpha = 0.4;
double beta = 1 - alpha;
int gamma = 0;
Mat src_addweighted;
addWeighted(src_img,alpha,logo_img,beta,gamma,src_addweighted);
imwrite("addweighter_samesize.jpg",src_addweighted);
}
return 0;
}
效果:

注:
1.参数
实现标准的透明度叠加 时,才需要保持 alpha+beta=1 。其他应用场景可以根据需要自由调整!
- 如果总和>1,可能导致图像过亮(像素值接近饱和)
- 如果总和<1,可能导致图像变暗
- OpenCV会自动将结果裁剪到有效范围(如0-255)
2.gamma亮度调节参数
- 数据类型匹配:gamma的值应该与图像的数据类型匹配
- 溢出处理:OpenCV会自动处理溢出(裁剪到有效范围)
- 浮点图像:对浮点图像要特别小心,gamma值通常很小
不同数据类型的影响
对于8位图像(0-255)
// gamma可以是正数或负数
cv::addWeighted(img1, 0.5, img2, 0.5, 30, result); // 变亮
cv::addWeighted(img1, 0.5, img2, 0.5, -20, result); // 变暗
// OpenCV会自动将结果裁剪到0-255范围内
对于浮点图像(0.0-1.0)
cv::Mat img1_f, img2_f, result_f;
// 转换为浮点型
img1.convertTo(img1_f, CV_32FC3, 1.0/255.0);
img2.convertTo(img2_f, CV_32FC3, 1.0/255.0);
cv::addWeighted(img1_f, 0.5, img2_f, 0.5, 0.1, result_f);
// gamma=0.1 会使图像显著变亮(因为范围是0-1)