Linux39:OPENCV图像叠加

目录

1.图像叠加功能简介

2.OPENCV中图像叠加常用的API

2.1.copyTo方法进行图像叠加

[3.代码,copyto 图层叠加](#3.代码,copyto 图层叠加)

1.创建矩形rect()

[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)  // 点+尺寸的方式
  1. x - 左上角的x坐标
  • 含义 :矩形左上角在图像中的列位置(水平方向)
  • 范围:0 ≤ x < 图像宽度
  • 作用:确定矩形开始的位置
  1. y - 左上角的y坐标
  • 含义:矩形左上角在图像中的行位置(垂直方向)
  • 范围:0 ≤ y < 图像高度
  • 作用:确定矩形开始的行
  1. width - 矩形的宽度
  • 含义:矩形的水平尺寸(列数)
  • 范围:> 0,且 x + width ≤ 图像宽度
  • 作用:确定矩形在水平方向包含多少像素
  1. 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)

相关推荐
呆呆敲代码的小Y3 小时前
【Unity-AI开发篇】| Unity-MCP最新指南:让AI接管游戏开发
人工智能·游戏·unity·ai·游戏引擎·mcp·unitymcp
格林威3 小时前
工业相机图像高速存储(C++版):内存映射文件(MMF)零拷贝方案,附堡盟 (Baumer) 相机实战代码!
开发语言·c++·人工智能·数码相机·计算机视觉·视觉检测·工业相机
穿过锁扣的风3 小时前
OpenCV 入门实战:图片与视频处理零基础教程
人工智能·opencv·计算机视觉
沪漂阿龙3 小时前
智能体:给大语言模型装上“手脚”,让它学会使用工具
人工智能·语言模型·自然语言处理
无心水3 小时前
【OpenClaw:认知启蒙】3、OpenClaw Agent执行循环(Lobster)深度拆解:从意图识别到工具调用的全流程
java·人工智能·系统架构·自动化
Fuxiao___3 小时前
RoboTwin2.0中训练OpenVLA-oft 全流程(bell + alarmclock)
人工智能·python·深度学习
Daydream.V3 小时前
Opencv——轮廓有关操作
人工智能·opencv·计算机视觉
weiyvyy3 小时前
机器人数学基础补充
人工智能·决策树·机器学习·机器人·嵌入式软件开发·机器人嵌入式开发
一知半解仙3 小时前
AI加持下的IDEA让Java开发更高效
java·人工智能·intellij-idea