基础入门
在OpenCV中,图像的数学运算是一种基本而强大的工具,可以用于多种图像处理任务,包括:图像增强、图像融合、特征提取等。这些运算包括加法、减法、乘法和除法等基本的数学操作。
加法运算:可以用来合并两个图像,或者调整图像的亮度。对于两个图像的加法,OpenCV会逐像素地将两个图像对应位置上的像素值相加。对于图像与常数的加法,就是将该常数加到图像的每个像素值上,一般用于跳转图像的亮度。
减法运算:通常用来突出图像间的差异,如比较同一场景的不同图像以发现变化的部分。对于两个图像的减法,OpenCV会逐像素地将两个图像对应位置的像素值相减。减法运算还可用于从前景图像中减去背景图像,以突出前景物体。
乘法运算:通常用于图像融合,或者调整图像的亮度和对比度。OpenCV中的图像乘法是逐像素进行的,并且通常需要将结果归一化到0到255之间。
除法运算:通常用来调整图像的动态范围,或者对比度。由于直接除法可能会导致像素值溢出或者精度丢失,因此通常需要将图像转换为浮点数类型。
注意:在进行加法和减法运算时,OpenCV会自动处理溢出问题。乘法和除法需要特别注意数据类型转换,以避免精度损失。
接口介绍
在OpenCV中,加法运算可以使用cv::add函数,其函数原型如下。
void add(const InputArray& src1, const InputArray& src2, OutputArray& dst,
const InputArray& mask = noArray(), int dtype = -1);
各个参数的含义如下。
src1和src2:输入图像,必须具有相同的尺寸和深度。
dst:输出图像,与输入图像具有相同的尺寸和深度(除非指定了不同的数据类型)。
mask:可选的掩模图像,与输入图像具有相同的尺寸,非零值位置将被应用于加法运算。
dtype:输出图像的数据类型。如果设置为-1,则输出图像的数据类型与输入图像相同。
减法运算可以使用cv::subtract函数,其参数与cv::add函数基本相同,故这里不再赘述。
乘法运算可以使用cv::multiply函数,其函数原型如下。
void cv::multiply(const InputArray& src1, const InputArray& src2,
OutputArray& dst, double scale = 1, int dtype = -1);
各个参数的含义如下。
src1和src2:输入图像,必须具有相同的尺寸和深度。
dst:输出图像,与输入图像具有相同的尺寸和深度(除非指定了不同的数据类型)。
scale:乘法结果的缩放因子,通常用于将结果映射到正确的范围。
dtype:输出图像的数据类型。如果设置为-1,则输出图像的数据类型与输入图像相同。
除法运算可以使用cv::divide函数,其参数与cv::multiply函数基本相同,故这里不再赘述。
实战解析
下面的实战代码首先尝试读取两张图片,并将它们存储在Mat类型的变量img1和img2中。如果图片未能成功加载,程序将输出错误信息并终止。接下来,代码检查两张图片的尺寸是否相同。如果不相同,则输出错误信息并终止程序。这是因为,图像的数学运算要求两张图片必须具有相同的尺寸。
然后,代码执行以下四个数学运算。
1、加法运算。将两张图片相加,并将结果存储在outputAdd中。
2、减法运算。从img1中减去img2,并将结果存储在outputSub中。
3、乘法运算。将两张图片逐像素相乘,并将结果存储在outputMul中。乘法结果需要进行归一化处理,即将结果除以255。
4、除法运算。为了执行除法运算,首先将两张图片转换为浮点数类型CV_32F。执行除法运算后,再将结果转换回8位整数类型CV_8U,并将结果存储在outputDiv中。
最后,我们使用imshow函数分别显示了加法、减法、乘法和除法运算的结果。
#include <opencv2/opencv.hpp>
using namespace cv;
#include <iostream>
using namespace std;
int main()
{
Mat img1 = imread("C++.png");
Mat img2 = imread("Hello.png");
if (img1.empty() || img2.empty())
{
cout << "Can not open or find the image" << endl;
return -1;
}
// 确保两个图像大小相同
if (img1.size() != img2.size())
{
cout << "Images must be same size" << endl;
return -1;
}
// 加法运算
Mat outputAdd;
add(img1, img2, outputAdd);
// 减法运算
Mat outputSub;
subtract(img1, img2, outputSub);
// 乘法运算
Mat outputMul;
multiply(img1, img2, outputMul, 1.0 / 255.0);
// 除法运算
Mat outputDiv;
Mat img1Float, img2Float;
img1.convertTo(img1Float, CV_32F);
img2.convertTo(img2Float, CV_32F);
divide(img1Float, img2Float, outputDiv, 1.0);
outputDiv.convertTo(outputDiv, CV_8U);
// 显示结果
imshow("Add", outputAdd);
imshow("Subtract", outputSub);
imshow("Multiply", outputMul);
imshow("Divide", outputDiv);
waitKey(0);
destroyAllWindows();
return 0;
}
执行上面的示例代码,运行效果可参考下图。