OpenCV图像数据处理:convertTo,normalize和scaleAdd

在 OpenCV 图像处理的世界里,有几个函数进行一些基本数据变换:

  • cv::convertTo():类型转换与线性缩放;

  • cv::normalize():归一化处理;

  • cv::scaleAdd():加权叠加运算。

  • cv::addWeighted(): 与scaleAdd相似,进行加权叠加运算;

一、cv::convertTo():线性变换 + 数据类型转换

cpp 复制代码
void cv::Mat::convertTo(OutputArray dst, int rtype, double alpha = 1, double beta = 0) const;

其操作逻辑为:

cpp 复制代码
dst(x, y) = saturate_cast<rtype>( src(x, y) * alpha + beta )

主要功能包括:

  • 类型转换,如CV_8U->CV_32F
  • 缩放变换,如alpha=1/255时实现归一化
  • 图像增强,如alpha > 1, beta ≠ 0 调整对比度与亮度

二、cv::normalize():归一化到特定范围或分布

cpp 复制代码
cv::normalize(InputArray src, OutputArray dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());

src:输入数组(cv::Mat)

  • 要被归一化的数据,可以是图像,也可以是向量或矩阵。

  • 可以是任意深度(CV_8U、CV_32F、CV_64F等),任意通道数(灰度、彩色等)。

dst:输出数组(cv::Mat)

  • 存储归一化后的结果,类型由 dtype 决定(默认与 src 一致)。

alpha:归一化下限或范数值(具体含义取决于 norm_type)

  • 如果 norm_type 是 NORM_MINMAX,alpha 表示 归一化后的最小值。

  • 如果是其他范数(如 NORM_L1, NORM_L2),alpha 是规范化后的 目标范数。

beta:归一化上限(仅在 NORM_MINMAX 有意义)

  • 只有当 norm_type = NORM_MINMAX 时,beta 表示 归一化后的最大值。

  • 对于其他归一化类型,beta 会被忽略。

norm_type:归一化类型(cv::NormTypes 枚举)

  • cv::NORM_MINMAX,将数组线性映射到 [alpha, beta] 区间,常用于图像对比度增强。
  • cv::NORM_L1,将向量归一化为 L1 范数(绝对值和)为 alpha。
  • cv::NORM_L2(默认),将向量归一化为 L2 范数(欧几里得范数)为 alpha。
  • cv::NORM_INF,将向量归一化为最大绝对值为 alpha。

dtype:输出数据类型(默认 -1 表示与 src 一致)

  • 可以指定输出图像的数据类型,如 CV_8U, CV_32F 等。

  • 如果 dtype = -1,表示 dst 类型与 src 保持一致。

mask:掩膜(可选)

  • 用于选择对哪些像素进行归一化,非零位置参与归一化计算。

  • 对于不需要掩膜的常见情况,使用默认值 cv::noArray()。

函数应用场景:

  • 使用NORM_MINMAX,将图像所有像素值映射到0,1区间
  • 使用NORM_L2,将图像看作向量,使得所有元素构成向量的模长为alpha

三、cv::scaleAdd():线性叠加的高效实现

cpp 复制代码
void cv::scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst);

其操作逻辑为:

cpp 复制代码
dst = src1 * alpha + src2;

用法场景:

  • 梯度融合;

  • 图像加权融合(曝光合成);

  • 向量叠加(例如 PCA 主成分叠加)。

四、完整实战示例:图像增强 + 归一化 + 加权融合

我们将演示如下流程:

  1. 读取一张图像并转换为浮点格式;

  2. 使用 convertTo 将其归一化到 0,1;

  3. 使用 scaleAdd 将原图与边缘图像加权融合,输出增强图像。

cpp 复制代码
int main() {
	cv::Mat img = cv::imread("lena.png", cv::IMREAD_GRAYSCALE);
	if (img.empty()) {
		std::cerr << "Cannot read image!" << std::endl;
		return -1;
	}

	// 1. 使用 convertTo 将图像转换为 float 并归一化
	cv::Mat img_f;
	img.convertTo(img_f, CV_32F, 1.0 / 255.0);

	// 2. 使用 Sobel 提取边缘
	cv::Mat grad_x, grad_y, grad;
	cv::Sobel(img_f, grad_x, CV_32F, 1, 0, 3);
	cv::Sobel(img_f, grad_y, CV_32F, 0, 1, 3);
	cv::magnitude(grad_x, grad_y, grad);

	// 3. 对梯度图 normalize 到 [0,1]
	cv::Mat grad_norm;
	cv::normalize(grad, grad_norm, 0.0, 1.0, cv::NORM_MINMAX);

	// 4. 使用 scaleAdd 融合边缘与原图
	cv::Mat enhanced;
	cv::scaleAdd(grad_norm, 0.5, img_f, enhanced); // enhanced = grad_norm * 0.5 + img_f

	// 5. 将增强图转换回 uchar 显示
	cv::Mat enhanced_8u;
	enhanced.convertTo(enhanced_8u, CV_8U, 255.0);

	// 显示结果
	cv::imshow("Original", img);
	cv::imshow("Enhanced", enhanced_8u);
	cv::waitKey(0);

	return 0;
}
相关推荐
晨间晓1 小时前
图片里的高频和低频是什么?用华为云码道开发 OpenCV 傅里叶频谱分析工具
opencv·计算机视觉·华为云
晨间晓2 小时前
图片里的阴影能不能减弱?用华为云码道开发 OpenCV 光照校正工具
人工智能·opencv·华为云
晨间晓16 小时前
图片里的细小噪点怎么平滑?用华为云码道开发 OpenCV 图像滤波对比工具
人工智能·opencv·华为云
偷吃米饭20 小时前
图片特征怎么描述?用华为云码道开发 OpenCV ORB 特征提取工具
人工智能·opencv·华为云
晨间晓21 小时前
图片里的关键点怎么找?用华为云码道开发 OpenCV FAST 特征点检测工具
人工智能·opencv·华为云
晨间晓21 小时前
二值图里的噪点怎么去掉?用华为云码道开发 OpenCV 形态学操作工具
人工智能·opencv·华为云
晨间晓1 天前
图片里的角点在哪里?用华为云码道开发 OpenCV Harris 角点检测工具
人工智能·opencv·华为云
晨间晓1 天前
图片细节丰富不丰富?用华为云码道开发 OpenCV 纹理复杂度分析工具
人工智能·opencv·华为云
richard_yuu2 天前
OpenCV 实战第 15 篇:G-API 图计算,工业流水线的 CPU/GPU 混合执行
人工智能·opencv·计算机视觉
老唐7772 天前
OpenCV5实测:纯CPU跑YOLO26目标检测
图像处理·人工智能·opencv·yolo·目标检测·计算机视觉