有两幅图像src1
和src2
,通过依据权重相加的方式实现ROI区域的混合,通过cv::addWeighted()
函数可以轻松地实现这一功能,对cv::addWeighted()
的参数,作如下说明:
void addWeighted(
cv::inputArray src1, //输入的第一幅图像数组
double alpha, //第一幅图像的权重参数,可以调整第一幅图像的透明度
cv::inputArray src2, //输入的第二幅图像
double beta, //第二幅图像的权重参数
double gamma, //加权总和的偏移量
cv::outputArray dst, //输出的图像
int dytpe =-1 //输入图像的类型
)
利用addWeighted()
函数实习ROI区域混合的完整代码如下:
#include<opencv2/core.hpp>
#include<highgui.hpp>
#include<string>
using namespace cv;
int main(int argc, char* argv[])
{
String src1Path = "G:\\visual_project\\cv_charpt5Exm\\charpt6Exm\\src1.jpg";
String src2Path = "G:\\visual_project\\cv_charpt5Exm\\charpt6Exm\\src2.jpg";
Mat src1 = imread(src1Path,1);
Mat src2 = imread(src2Path, 1);
if ( !src1.empty() && !src2.empty())
{
//src1 图像ROI区域的起始点坐标(x,y)
int x = 0;
int y = 0;
//src1 图像的ROI区域的宽和高
int w = 220;
int h = 220;
// alpha 越大,src1的ROI区域的亮度越高
double alpha = 0.3;
double beta = 0.7;
// 利用Rect 获取src1的ROI区域
Mat roi1(src1,Rect(x, y, w, h));
//利用Rect 获取src2的ROI区域,与src1的ROI区域加权处理
Mat roi2(src2, Rect(0, 0, w, h));
addWeighted(roi1, alpha, roi2, beta, 0.0,roi2);
namedWindow("Alpha Blend", 1);
imshow("Alpha blend", src2);
//imshow("roi", roi1);
waitKey(0);
}
return 0;
}
实现效果如下所示:
注意: 利用Rect处理图像矩阵问题时,最不容忽视的问题是数组越界的问题,所以要注意边界检查,本次实现中,应该使得roi1的坐标
(x,y)
和宽高(w1,h1)
与roi2的宽高(w2,h2)
应该满足((x+w1)<=w2 && (y+h1) <=h2)
,加入边界检查和完整输入输出的代码,参考github代码如下所示:
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void help(const char** argv) {
cout << "\n\n"
<< "This program alpha blends the first image onto the other \n"
<< "alpha is the blending of the first image and beta onto the second\n"
<< "Call:\n"
<< argv[0] << " <path/blend_this_img> <path/onto_this_img> <where_to_blend_x> <where_to_blend_y> <alpha> <beta>\n\n"
<< "Example:\n"
<< " ./example_05-01 ../faceTemplate.jpg ../faces.png 230 155 0.8 0.2\n"
<< endl;
}
int main(int argc, const char** argv)
{
help(argv);
if (argc != 7) {
cout << "ERROR: Wrong # of parameters (7), you had " << argc << "\n" << endl;
return -1;
}
// Using the first two arguments, open up the image to be copied onto
// (src1), and the image that will be copied from (src2).
//
cv::Mat src1 = cv::imread(argv[1], 1);
cv::Mat src2 = cv::imread(argv[2], 1);
int from_w = src1.size().width;
int from_h = src1.size().height;
int to_w = src2.size().width;
int to_h = src2.size().height;
if (argc == 7 && !src1.empty() && !src2.empty()) {
// Four more arguments tell where in src1 to paste the chunk taken from
// src2. Note that the width and height also specify what portion of
// src2 to actually use.
//
int x = atoi(argv[3]);
int y = atoi(argv[4]);
// Make sure we don't exceed bounds:
if ((x < 0) || (y < 0) || (x > to_w - 1) || (y > to_h - 1) || (x + from_w > to_w - 1) || (y + from_h > to_h)) {
cout << "\nError, at (x,y) (" << x << ", " << y << "), your input image [w,h] [" << from_w << ", "
<< from_h << "] doesn't fit within the blend to image [w,h] [" << to_w << ", " << to_h << "]\n" << endl;
return -1;
}
// Two more arguments set the blending coefficients.
//
double alpha = (double)atof(argv[5]);
double beta = (double)atof(argv[6]);
cv::Mat roi1(src1, cv::Rect(0, 0, from_w - 1, from_h - 1)); //Just take the whole thing
cv::Mat roi2(src2, cv::Rect(x, y, from_w - 1, from_h - 1));
// Blend together the image src2 onto the image src1
// at the specified location.
//
cv::addWeighted(roi1, alpha, roi2, beta, 0.0, roi2);
// Create a window to shoow the result and show it.
//
cv::namedWindow("Alpha Blend", 1);
cv::imshow("Alpha Blend", src2);
// Leave the window up and runnnig until the user hits a key
//
cv::waitKey(0);
}
return 0;
}
网友评论