OpenCV cv::Mat之(三)算术操作

在计算机视觉领域,OpenCV的算术运算是图像处理的基础操作。通过简单的加减乘除,我们可以实现亮度调整、对比度增强、图像融合等多种效果。下面将介绍OpenCV 4.x中C++接口的核心运算方法。

1、算术符号计算

1.1和标量Scalar计算

使用 “+ - /” 符号可以对Mat对象直接进行操作。注意不支持乘法操作,需要使用后面的核心算术函数

#include "stdio.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
int main()
{

	//-------------------------------------------------------------------------------------
	Mat image(3, 4, CV_8UC3);
	//直接赋值 
	image = Scalar(120, 120, 120);//B G R
	//除法运算
	image = image/Scalar(2, 3, 5);
	std::cout << "CV_8UC3:" << std::endl;
	std::cout << image << std::endl;
	cv::waitKey(0);
	destroyAllWindows();
	return 0;
}

在这里插入图片描述
注意:计算过程是对BGR3个通道分别除以对应的值“2,3,5”。加法和减法也是一样。

1.2 Mat和Mat计算

Mat image(3, 4, CV_8UC3);
Mat image1(3, 4, CV_8UC3); 
image1= Scalar(120, 120, 120);
image = Scalar(120, 120, 120);
image = image/ image1;

注意:两个Mat进行计算需要保证行列通道数一致。

2、核心算术函数计算

2.1 基础运算函数

// 图像加法(饱和运算)
void add(InputArray src1, InputArray src2, OutputArray dst);
// 图像减法
void subtract(InputArray src1, InputArray src2, OutputArray dst);
// 像素乘法(支持缩放因子)
void multiply(InputArray src1, InputArray src2, OutputArray dst, double scale=1);
// 像素除法
void divide(InputArray src1, InputArray src2, OutputArray dst, double scale=1);

2.2 运算特性对比

运算类型 溢出处理 执行速度 典型应用场景
加法 饱和截断(0-255) 亮度增强
减法 模运算 较快 背景差分
乘法 可能溢出需缩放 中等 对比度调整
除法 向下取整 较慢 颜色空间归一化

2.3 标量运算示例

    cv::Mat srcImage=cv::imread("E:/image/lena.png");
	Mat result1, result2;
	// 亮度增强:每个像素值+80
	add(srcImage, Scalar(80, 80, 80),result1);
	// 对比度降低:每个像素值×0.7
	multiply(srcImage, Scalar(0.7, 0.7, 0.7), result2);
	add(srcImage, srcImage2, result3);

	imshow("原图", srcImage);
	imshow("add", result1);
	imshow("multiply", result2);
	cv::waitKey(0);
	destroyAllWindows();

运行结果看到相加后图像亮度增加
在这里插入图片描述

注意:因uint8类型数值溢出,一些运算需先转换为浮点类型。参考代码

Mat img_float;
img.convertTo(img_float, CV_32F,1.0/255);//限制在0~1之间

2.3 图像运算

Mat和Mat数据进行运算,需要保证大小一致,这里使用了resize函数进行调整。

    cv::Mat srcImage=cv::imread("E:/image/lena.png");
	cv::Mat srcImage2 = imread("E:/image/Opencv-logo.png",COLOR_BGR2GRAY);
	//减法降低亮度
	//subtract(srcImage2, Scalar(100, 100, 100), srcImage2);
	//调整大小
	resize(srcImage2, srcImage2, Size(srcImage.rows, srcImage.cols));
  //加法运算
	Mat result1;
	add(srcImage, srcImage2, result1);
  //乘法运算比例因子抑制过饱和
	Mat result2;
	multiply(srcImage, srcImage2, result2,0.02);
	//减法
	Mat result3;
	subtract(srcImage, srcImage2, result3);
	Mat result4;
	//除法
	divide(srcImage, srcImage2, result4);

	//imshow("srcImage", srcImage);
	//imshow("srcImage2", srcImage2);
	imshow("add", result1);
	imshow("multiply", result2);
	imshow("subtract", result3);
	imshow("divide", result4);
	cv::waitKey(0);
	destroyAllWindows();

在这里插入图片描述
在这里插入图片描述

2.4 运算应用之图像融合

函数addWeighted可以实现权重融合,也可以使用multiply和add进行

// 线性混合:result1= 0.3*srcImage+ 0.7*srcImage2
addWeighted(srcImage, 0.7, srcImage2, 0.3, 0, result1);

//使用multiply 和add 
multiply(srcImage, Scalar(0.7, 0.7, 0.7), result1);
multiply(srcImage2, Scalar(0.3, 0.3, 0.3), result2);
add(result1, result2, result3);

融合效果就好像加了水印

在这里插入图片描述

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐