opencv图像合成

图像合成本质上是alpha blending,也称为alpha融合,数学表达如下
y = alpha * x1 + (1 - alpha) * x2
opencv中提供了融合函数,可进行单通道或多通道整合(本质上是各个通道分别整合),如下为官方文档描述。

对于c++版本,有7个参数,分别是:

  • src1,输入图像1
  • alpha,src1的权重
  • src2,输入图像2
  • beta,src2的权重
  • gamma,结果偏移
  • dst,输出图像
  • dtype,输出图像的位宽设置,默认为-1,此时输出图像位宽等于src1的位宽
    该方法公式如下:dst = src1alpha + src2beta + gamma;

对于更便捷的python来说,方法为cv2.addWeighted,参数与c++版本基本一样,后面直接看代码。

1.opencv图像融合c++实现

直接show代码:

#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{
    Mat imsrc1 = imread(argv[1]);
    Mat imsrc2 = imread(argv[2]);
    Mat imsrc2_scaler;      //将imsrc2缩放到imsrc1的尺寸
    Mat imdst;              //合成的目标图像
    double alpha = 0.3;
    double gamma = 0;
    if(imsrc1.size() != imsrc2.size()){
        printf("resize start!\n");
        //resize(imsrc2, imsrc2_scaler, Size(imsrc1.cols, imsrc1.rows), 0, 0, INTER_LINEAR);
        resize(imsrc2, imsrc2_scaler, imsrc1.size(), 0, 0, INTER_LINEAR);    //方法2
        addWeighted(imsrc1, alpha, imsrc2_scaler, 1 - alpha, gamma, imdst);
    }
    else{
        addWeighted(imsrc1, alpha, imsrc2, 1 - alpha, gamma, imdst);
    }

    imwrite("imdst.jpg", imdst);
    return 0;
}

保存为image_merge.cpp
编译:g++ pkg-config --cflags --libs opencv image_merge.cpp -o test
运行:./test im1.jpg im2.jpg
原始图片:
在这里插入图片描述
在这里插入图片描述
结果如下:
在这里插入图片描述
在这里插入图片描述

2.python图像合成

python实现如下,简洁、便捷!

import cv2

imsrc1 = cv2.imread("../../c-base/opencv-imageprocess/im1.jpg")
imsrc2 = cv2.imread("../../c-base/opencv-imageprocess/im2.jpg")

alpha = 0.7

imdst = cv2.addWeighted(imsrc1, alpha, imsrc2, 1 - alpha, 0)
#cv2.namedWindow("merge")
#cv2.imshow("merge", imdst)
cv2.imwrite("imDstMerge.jpg", imdst)

3.通道split及区域合图

split可将多通道拆分开,然后各个通道使用Rect做区域融合

#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

//合成图像的中间区域
int main(int argc, char **argv)
{
    Mat imsrc1 = imread(argv[1]);
    Mat imsrc2 = imread(argv[2]);
    Mat imsrc2_scaler;      //将imsrc2缩放到imsrc1的尺寸
    Mat imdst;              //合成的目标图像
    double alpha = 0.3;
    double gamma = 0;

    vector<Mat> channels_src1;
    split(imsrc1, channels_src1);
    Mat imageRedChannels = channels_src1.at(0);
    Mat imageGreenChannels = channels_src1.at(1);
    Mat imageBlueChannels = channels_src1.at(2);

    resize(imsrc2, imsrc2_scaler, Size(imsrc1.cols / 2, imsrc1.rows / 2), 0, 0, INTER_LINEAR);
    vector<Mat> channels_src2;
    split(imsrc2_scaler, channels_src2);
    Mat imageRedChannels_src2 = channels_src2.at(0);
    Mat imageGreenChannels_src2 = channels_src2.at(1);
    Mat imageBlueChannels_src2 = channels_src2.at(2);

    addWeighted(imageRedChannels(Rect(imsrc1.cols / 4, imsrc1.rows / 4, imsrc2_scaler.cols, imsrc2_scaler.rows)), 
        0.3, imageRedChannels_src2, 0.7, 0, imageRedChannels(Rect(imsrc1.cols / 4, imsrc1.rows / 4, imsrc2_scaler.cols, imsrc2_scaler.rows)));
    addWeighted(imageGreenChannels(Rect(imsrc1.cols / 4, imsrc1.rows / 4, imsrc2_scaler.cols, imsrc2_scaler.rows)), 
        0.3, imageGreenChannels_src2, 0.7, 0, imageGreenChannels(Rect(imsrc1.cols / 4, imsrc1.rows / 4, imsrc2_scaler.cols, imsrc2_scaler.rows)));
    addWeighted(imageBlueChannels(Rect(imsrc1.cols / 4, imsrc1.rows / 4, imsrc2_scaler.cols, imsrc2_scaler.rows)), 
        0.3, imageBlueChannels_src2, 0.7, 0, imageBlueChannels(Rect(imsrc1.cols / 4, imsrc1.rows / 4, imsrc2_scaler.cols, imsrc2_scaler.rows)));

    merge(channels_src1, imdst);
    imwrite("imdst.jpg", imdst);
    return 0;
}

结果如下:
在这里插入图片描述

参考:
[1] https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值