下一篇:
引言:
我们将学习如何混合两个图像!
目标
在本教程中,您将学习:
- 什么是线性混合以及它为什么有用;
- 如何使用 **addWeighted()**添加两张图片
理论
注意
下面的解释属于 Richard Szeliski 的《计算机视觉:算法和应用》一书
从我们之前的教程中,我们已经了解了一些 Pixel 运算符 。一个有趣的二元(双输入)运算符是线性混合运算符:
通过参数x从0到 1,该运算符可用于在两个图像或视频之间执行时间交叉溶解,如幻灯片和电影制作中所示(很酷,嗯)
源代码
从这里下载源代码。
C++:
cpp
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
// we're NOT "using namespace std;" here, to avoid collisions between the beta variable and std::beta in c++17
using std::cin;
using std::cout;
using std::endl;
int main( void )
{
double alpha = 0.5; double beta; double input;
Mat src1, src2, dst;
cout << " Simple Linear Blender " << endl;
cout << "-----------------------" << endl;
cout << "* Enter alpha [0.0-1.0]: ";
cin >> input;
// We use the alpha provided by the user if it is between 0 and 1
if( input >= 0 && input <= 1 )
{ alpha = input; }
src1 = imread( samples::findFile("LinuxLogo.jpg") );
src2 = imread( samples::findFile("WindowsLogo.jpg") );
if( src1.empty() ) { cout << "Error loading src1" << endl; return EXIT_FAILURE; }
if( src2.empty() ) { cout << "Error loading src2" << endl; return EXIT_FAILURE; }
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
imshow( "Linear Blend", dst );
waitKey(0);
return 0;
}
Java:
java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import java.util.Locale;
import java.util.Scanner;
class AddingImagesRun{
public void run() {
double alpha = 0.5; double beta; double input;
Mat src1, src2, dst = new Mat();
System.out.println(" Simple Linear Blender ");
System.out.println("-----------------------");
System.out.println("* Enter alpha [0.0-1.0]: ");
Scanner scan = new Scanner( System.in ).useLocale(Locale.US);
input = scan.nextDouble();
if( input >= 0.0 && input <= 1.0 )
alpha = input;
src1 = Imgcodecs.imread("../../images/LinuxLogo.jpg");
src2 = Imgcodecs.imread("../../images/WindowsLogo.jpg");
if( src1.empty() == true ){ System.out.println("Error loading src1"); return;}
if( src2.empty() == true ){ System.out.println("Error loading src2"); return;}
beta = ( 1.0 - alpha );
Core.addWeighted( src1, alpha, src2, beta, 0.0, dst);
HighGui.imshow("Linear Blend", dst);
HighGui.waitKey(0);
System.exit(0);
}
}
public class AddingImages {
public static void main(String[] args) {
// Load the native library.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new AddingImagesRun().run();
}
}
Python:
python
from __future__ import print_function
import cv2 as cv
alpha = 0.5
try:
raw_input # Python 2
except NameError:
raw_input = input # Python 3
print(''' Simple Linear Blender
-----------------------
* Enter alpha [0.0-1.0]: ''')
input_alpha = float(raw_input().strip())
if 0 <= alpha <= 1:
alpha = input_alpha
# [load]
src1 = cv.imread(cv.samples.findFile('LinuxLogo.jpg'))
src2 = cv.imread(cv.samples.findFile('WindowsLogo.jpg'))
# [load]
if src1 is None:
print("Error loading src1")
exit(-1)
elif src2 is None:
print("Error loading src2")
exit(-1)
# [blend_images]
beta = (1.0 - alpha)
dst = cv.addWeighted(src1, alpha, src2, beta, 0.0)
# [blend_images]
# [display]
cv.imshow('dst', dst)
cv.waitKey(0)
# [display]
cv.destroyAllWindows()
解释
由于我们要执行:
通过以下代码加载图像:
C++:
cpp
src1 = imread( samples::findFile("LinuxLogo.jpg") );
src2 = imread( samples::findFile("WindowsLogo.jpg") );
Java:
java
src1 = Imgcodecs.imread("../../images/LinuxLogo.jpg");
src2 = Imgcodecs.imread("../../images/WindowsLogo.jpg");
Python:
python
src1 = cv.imread(cv.samples.findFile('LinuxLogo.jpg'))
src2 = cv.imread(cv.samples.findFile('WindowsLogo.jpg'))
我们使用了以下图像:LinuxLogo.jpg和WindowsLogo.jpg
警告
由于我们添加了 src1 和 src2,因此它们必须具有相同的大小(宽度和高度)和类型。
现在我们需要生成图像g(x)
。为此,**函数 addWeighted()**非常方便:
C++:
cpp
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
Java:
java
beta = ( 1.0 - alpha );
Core.addWeighted( src1, alpha, src2, beta, 0.0, dst);
Python:
python
beta = (1.0 - alpha)
dst = cv.addWeighted(src1, alpha, src2, beta, 0.0)
上面行的Python版本(但cv功能快了大约 2 倍):
python
dst = np.uint8(alpha*(img1)+beta*(img2))
因为addWeighted() 产生:
在本例中,是上面代码中argument 0.0的参数
创建窗口,显示图像并等待用户结束程序。
C++:
cpp
imshow( "Linear Blend", dst );
waitKey(0);
Java:
java
HighGui.imshow("Linear Blend", dst);
HighGui.waitKey(0);
Pytthon:
python
cv.imshow('dst', dst)
cv.waitKey(0)
参考文献:
1、《Adding (blending) two images using OpenCV》---Ana Huamán