关于OpenCV的配置和基础用法,请参阅本专栏的其他文章:垚武田的OpenCV合集
这里采用的图片熔合的算法来自Richard Szeliski的书《Computer Vision: Algorithms and Applications》(《计算机视觉:算法和应用》)。
该算法使用了一个两参的线性熔合算子来操作图片的像素:
g ( x ) = ( 1 − α ) f 0 ( x ) + α f 1 ( x ) g(x) = (1-\alpha)f_0(x)+\alpha f_1(x) g(x)=(1−α)f0(x)+αf1(x)
α \alpha α的值从0-1不等。利用这个 α \alpha α值,该算法可以对两个图片或者视频执行一个临时的交叉溶解(criss-dissolve),就像在幻灯片或胶片中那样(很酷是不是?)
在OpenCV中使用addWeighted()
函数来实现上述的线性熔合的方法。
首先导入要熔合的两张图片。这两张图片是OpenCV库中自带的,可以在安装目录的子路径...\opencv\sources\samples\data
中找到它们:LinuxLogo.jpg
和WindowsLogo.jpg
。将它们复制进项目文件夹,导入语句如下:
Mat src1 { imread("LinuxLogo.jpg") }; Mat src2 { imread("WindowsLogo.jpg") };
注意:被熔合的两张图片必须大小(长和宽)一致,类型也必须一致
接着确定 α \alpha α值,并使用线性熔合算法:
double alpha{ 0.5 }; double beta{ 1.0 - alpha }; Mat dst; addWeighted( src1, alpha, src2, beta, 0.0, dst);
这里将 α \alpha α设为0.5; β \beta β其实是算法中的 1 − α 1- \alpha 1−α。这里再回到算法公式:
g ( x ) = ( 1 − α ) f 0 ( x ) + α f 1 ( x ) g(x) = (1-\alpha)f_0(x)+\alpha f_1(x) g(x)=(1−α)f0(x)+αf1(x)
然后我们来看一下在addWeighted()
函数中,是怎样用各个参数来确定线性熔合算法的——addWeighted( src1, alpha, src2, beta, 0.0, dst);
:
src1
和src2
分别是要熔合的两张图片的Mat
对象alpha
是公式中的 α \alpha α,即src1
所代表的图片的权重beta
是公式中的 1 − α 1- \alpha 1−α,即src2
所代表的图片的权重0.0
是公式中没有的一个常数 γ \gamma γ,用来对熔合后的像素值进行偏移dst
为储存熔合结果的Mat
对象addWeighted()
函数的实际算法可以用以下公式表示:创建窗口,展示图片熔合的结果
imshow("线性熔合", dst); waitKey(0);
输出结果如下:
注意:
#include #include #include import ; using namespace cv; //因为C++中有std::beta,为了避免名称冲突,这里没有使用整个std命名空间 using std::cin; using std::cout; using std::endl; int main() { double alpha{ 0.5 }; double beta, input; Mat src1, src2, dst; cout << "简单线性混合" << endl; cout << "-----------" << endl; cout << "* 输入α值 [0.0-1.0]"; cin >> input; if (input >= 0 && input <= 1) alpha = input; src1 = imread("LinuxLogo.jpg"); src2 = imread("WindowsLogo.jpg"); if (src1.empty()) { cout << "图片1导入错误" << endl; return EXIT_FAILURE; } if (src2.empty()) { cout << "图片2导入错误" << endl; return EXIT_FAILURE; } beta = 1.0 - alpha; addWeighted(src1, alpha, src2, beta, 0.0, dst); imshow("线性混合", dst); waitKey(0); return 0; }