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_typeNORM_MINMAXalpha 表示 归一化后的最小值

  • 如果是其他范数(如 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;
}
相关推荐
梦醒过后说珍重13 小时前
医学图像超分辨率:如何构建“教科书级”的模型评测与交互式可视化流水线?
opencv
格林威15 小时前
工业相机参数解析:曝光时间与运动模糊的“生死博弈”
c++·人工智能·数码相机·opencv·算法·计算机视觉·工业相机
AI科技星1 天前
全尺度角速度统一:基于 v ≡ c 的纯推导与验证
c语言·开发语言·人工智能·opencv·算法·机器学习·数据挖掘
格林威2 天前
C++ 工业视觉实战:Bayer 图转 RGB 的 3 种核心算法(邻域平均、双线性、OpenCV 源码级优化)
开发语言·c++·人工智能·opencv·算法·计算机视觉·工业相机
格林威2 天前
工业相机图像高速存储(C++版):RAID 0 NVMe SSD 阵列方法,附堡盟相机实战代码!
开发语言·c++·人工智能·数码相机·opencv·计算机视觉·视觉检测
容沁风2 天前
用opencv和yolov5su定位二维码
opencv·yolo·二维码
追烽少年x2 天前
在Python中学习OpenCV - ROI(region of interest)
python·opencv
液态不合群3 天前
OpenCV多线程编程:从单线程到多线程的视频处理
人工智能·opencv·音视频
万物得其道者成3 天前
uni-app Android 离线打包:多环境(prod/dev)配置
android·opencv·uni-app
kkoral3 天前
OpenCV 与 FFmpeg 的关系
opencv·ffmpeg