一、图像叠加功能简介图像叠加顾名思义就是在原图像里面添加一些其他图像数据最常见的就是在原图像中添加一些水印图像。这些水印图像可以是时间戳、LOGO图像等等。如上图原图像是山的背景在这个图像的左上角叠加绿色的LOGO标志然后两个图像就可以融合在一起。上面这个例子就是最经典的图像叠加案例。二、图像叠加最常用的两个核心 APIOpenCV 中图像叠加场景最核心、最常用的两个 API 是cv::copyTo掩码拷贝和cv::addWeighted加权融合分别对应「硬覆盖 / 带透明贴图」和「半透明融合」两类主流需求下面结合你的 logo 贴图场景详细说明。2.1copyTo区域拷贝支持掩码透明叠加1. 功能定位将一张源图完整复制到目标图像的指定区域是最基础的贴图、水印实现方式配合掩码图可以实现 PNG 透明背景叠加透明区域不会覆盖原图。2. 函数原型// 基础版直接全像素覆盖拷贝 void copyTo(OutputArray dst) const; // 带掩码版只在掩码非零的区域拷贝像素 void copyTo(OutputArray dst, InputArray mask) const;3. 参数说明dst目标图像通常是原图的 ROI 感兴趣区域mask掩码图单通道 8 位只有掩码中像素值非 0 的位置才会拷贝源图像素掩码为 0 的位置保留目标图原有像素以此实现透明效果。4. 典型用法1基础硬覆盖你之前代码的写法直接将 logo 完整覆盖到原图左上角PNG 透明区域会变成黑色Mat src imread(frame1.jpg); Mat logo imread(OIP-C.png); // 截取原图左上角和logo等大的ROI区域 Mat roi src(Rect(0, 0, logo.cols, logo.rows)); // logo像素直接覆盖ROI区域 logo.copyTo(roi);2带透明 PNG 叠加进阶常用写法读取带 alpha 通道的 PNG提取透明通道作为掩码实现背景透明的贴图效果// 原样读取PNG保留alpha通道4通道BGRA Mat logo imread(OIP-C.png, IMREAD_UNCHANGED); Mat src imread(frame1.jpg); // 拆分logo的通道提取第4个alpha通道作为掩码 vectorMat channels; split(logo, channels); Mat mask channels[3]; // alpha通道透明处为0不透明处为255 // 提取logo的BGR三通道部分只拷贝颜色掩码控制透明 Mat logo_bgr; cvtColor(logo, logo_bgr, COLOR_BGRA2BGR); // 截取原图ROI带掩码拷贝 Mat roi src(Rect(0, 0, logo.cols, logo.rows)); logo_bgr.copyTo(roi, mask);5. 核心注意事项目标图与源图必须尺寸一致、通道数一致掩码必须是单通道通常配合 ROI 使用保证目标区域和源图尺寸相同。不带掩码的版本是内存块级拷贝性能极高是所有叠加方式里最快的适合嵌入式场景。掩码图是二值逻辑像素为 0 的区域完全不拷贝非 0 区域完整拷贝没有半透明过渡。2.2addWeighted加权线性融合1. 功能定位对两张尺寸、类型完全相同的图像按权重比例做逐像素线性叠加实现半透明融合效果是半透明水印、图像叠底、双曝光效果的标准实现。2. 函数原型 计算公式void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst);运算公式dst(x,y) src1(x,y) * alpha src2(x,y) * beta gamma3. 参数说明参数作用src1第一张输入图像alpha第一张图的权重系数透明度0~10 完全透明1 完全不透明src2第二张输入图像尺寸、通道数必须和 src1 完全一致beta第二张图的权重系数通常alpha beta 1.0保证整体亮度不变gamma整体亮度偏移量叠加后整体加 / 减亮度一般填 0dst输出的融合结果图4. 典型用法半透明水印将 logo 以半透明的方式叠加在原图左上角实现淡水印效果Mat src imread(frame1.jpg); Mat logo imread(OIP-C.png); // 截取原图对应区域 Mat roi src(Rect(0, 0, logo.cols, logo.rows)); Mat dst_roi; // 加权融合原图权重0.8logo权重0.2logo呈现20%透明度 addWeighted(roi, 0.8, logo, 0.2, 0, dst_roi); // 将融合结果写回原图 dst_roi.copyTo(roi);5. 核心注意事项自动饱和截断OpenCV 内置像素值溢出保护计算结果超过 255 自动截断为 255低于 0 自动截断为 0不会出现手动写循环时的无符号溢出 bug。两张输入图必须尺寸、通道数、像素类型完全一致否则直接报错。属于逐像素算术运算性能比不带掩码的copyTo略低但远快于手动双层循环。2.3 两个 API 核心对比对比项copyTo带掩码addWeighted核心效果要么完全覆盖、要么完全透明无半过渡按权重半透明融合过渡平滑适用场景带透明背景的图标、logo 贴图半透明水印、图像融合、曝光叠加性能更高掩码判断 块拷贝略低逐像素加权计算透明度粒度0/1 二值透明0~1 连续可调透明度是否修改原图直接修改目标图生成新的结果图不修改原图2.4 RV1126 嵌入式场景建议优先用copyTo实现贴图需求性能最优CPU 占用更低需要半透明效果再用addWeighted。避免手动写双层循环做像素叠加OpenCV 内置 API 做了指令集优化速度和稳定性都远优于手动实现。叠加前务必检查图像是否为空、尺寸是否匹配防止越界导致程序闪退。三、代码copyTo#include opencv2/opencv.hpp #include opencv2/dnn.hpp #include opencv2/imgcodecs.hpp #include opencv2/imgproc.hpp #include iostream using namespace cv; using namespace std; int main(int argc, char * argv[]) { Mat src1 imread(argv[1]); Mat src2 imread(argv[2]); if(src1.size ! src2.size) { Mat image_roi src1(Rect(20, 20, src2.cols, src2.rows)); double alpha 0.4; double beta 1 - alpha; int gama 0; addWeighted(image_roi, alpha, src2, beta, gama, image_roi); imwrite(addweighted_norsamesize.jpg,src1); } else { double alpha 0.4; double beta 1 - alpha; int gama 0; Mat dst; addWeighted(src1, alpha, src2, beta, gama, dst); imwrite(addweighted_samesize.jpg,dst); } return 0; }