图像合成本质上是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