当前位置: 首页 > news >正文

图像归一化:OpenCV 高效映射 [0,255] → [-1,1] 性能实测

 一、背景

在深度学习推理任务中,图像输入需要与模型训练时的数值范围保持一致。
而使用 OpenCV 读取图像时,像素默认是 uint8 类型,取值范围 [0, 255]
然而,模型往往要求输入为:

  • [0, 1](归一化)或  [-1, 1](标准化后输入)

若预处理方式不合理,就会带来额外的内存读写、临时矩阵创建甚至性能瓶颈。
在一次算法优化的任务中,我需要将整个推理项目的速度尽可能优化到极致(前处理,推理,后处理),将自己对于其中图像归一化的迭代优化思考的过程记录下来,温故而知新。


 二、图像归一化改进:从两步法到一次到位

下面展示三种实现方式的演变,从最常见的旧写法,到错误的“优化”,再到最终高效版本。


        第一代:传统两步法(正确但低效)

cv::Mat f32;
rgb.convertTo(f32, CV_32F, 1.f / 255.f);
f32 = f32 * 2.f - 1.f;

逻辑:

  1. 先把像素范围 通过除法[0,255] → [0,1],再通过乘法减法共三次计算线性变换为 [-1,1]

数学表达:

问题:

  • 两次完整图像遍历;

  • 每次遍历触发一次内存读写;

  • 对大图或多分块(图像分块推理)场景,性能损耗显著。


        第二代:自认为“优化”的错误写法

cv::Mat f32;
rgb.convertTo(f32, CV_32F);
f32 = (f32 - 127.5f) / 127.5f;

初衷:
想把利用减法除法两次计算压缩成一行,结果反而更慢。

原因:

  • (f32 - 127.5f) 创建一个新的临时矩阵;

  • / 127.5f 再创建第二个临时矩阵;

  • 共两次全图遍历,且无法使用 OpenCV 内部 SIMD 加速。

⚠️ 注意:
在 Python (NumPy) 中这是广播操作,一次遍历;
在 C++/OpenCV 中,每个算术运算都会生成新矩阵


        第三代:最终版 —— 一次到位的高效归一化

cv::Mat f32;
rgb.convertTo(f32, CV_32F, 1.0 / 127.5, -1.0); // f32 = rgb * (1/127.5) + (-1)

原理:
convertTo() 内部支持同时执行线性变换:

代入参数:

即:

优势:

  • 一次遍历完成;

  • 内部启用 SIMD + 多线程优化;

  • 无临时矩阵,无额外内存拷贝;


三、性能测试验证

测试程序如下:

#include <opencv2/opencv.hpp>
#include <chrono>
#include <iostream>
using namespace std;int main() {cv::Mat rgb = cv::imread("test.jpg");int N = 50;auto run = [&](auto func, const string& name) {auto t0 = chrono::high_resolution_clock::now();for (int i = 0; i < N; ++i) func();auto t1 = chrono::high_resolution_clock::now();double ms = chrono::duration<double, milli>(t1 - t0).count();cout << name << ": " << ms / N << " ms" << endl;};run([&] {cv::Mat f32;rgb.convertTo(f32, CV_32F, 1.f / 255.f);f32 = f32 * 2.f - 1.f;}, "第一代:两步法");run([&] {cv::Mat f32;rgb.convertTo(f32, CV_32F);f32 = (f32 - 127.5f) / 127.5f;}, "第二代:错误优化");run([&] {cv::Mat f32;rgb.convertTo(f32, CV_32F, 1.0 / 127.5, -1.0);}, "第三代:一次到位");return 0;
}

测试环境:

  • Intel i7-12700H

  • OpenCV 4.8

  • 输入图像:3840×2160 (4K)


测试结果

 

重复运行过很多次,确实是第三种优化方式更快。


四、总结

写法遍历次数SIMD 优化是否创建临时矩阵性能
/255 + *2-12中等
(x - 127.5)/127.52中等
convertTo(..., 1/127.5, -1)1最优 🔥

结论:

建议使用
rgb.convertTo(f32, CV_32F, 1.0 / 127.5, -1.0);
一步完成归一化。
大图、超分辨率切片推理等场景,能显著节省 CPU 资源。

http://www.dtcms.com/a/536116.html

相关文章:

  • allWebPlugin.IE扩展使用介绍
  • C语言输入输出函数完整指南:从基础到高级应用
  • 20.10 多模态PPT生成准确率突破93%!ChatPPT v3.0动态权重技术深度解析
  • 中国移动通信联合会人工智能与元宇宙产业委联席秘书长叶毓睿受聘为“北京设计学会无障碍设计专业委员会指导专家”
  • 励志网站织梦源码建个人网上银行登录入口
  • Nginx清除浏览器缓存的三个缓存响应头的关系详解
  • 14天极限复习软考-day5 软件工程 、UML
  • 基于M4-R1开发板的OpenHarmony开发实战丨创建第一个应用工程
  • 【计算机视觉】Python 验证码图片分割:基于 OpenCV 的字符区域提取实现
  • 时序论文速递:覆盖时间序列预测、分类、异常检测及交叉应用!(10.20-10.24)
  • wordpress 建视频网站福步外贸论坛怎样注册
  • 没有网站可以做的广告联盟家居企业网站建设精英
  • navicat11不支持mysql8.0的加密方式
  • 程序综合实践第五次DP1
  • 架构论文《论系统超融合架构的设计与应用》
  • PCB行业数字化转型样本:兴森科技携手盘古信息MOM系统,实现生产效率跃升
  • ESP32-C3赋能物联网设备,开启产品智能化,乐鑫代理商飞睿科技
  • 奥比中光相机pythonAPI color.py运行报错 (-5:Bad argument) in function ‘cvtColor‘
  • 南和网站建设公司建筑设计网课
  • 网站建设与管理 自考网络营销的四大基础理论
  • 毫秒级自动对焦,超高景深液态镜头在机器视觉检测中的应用
  • 了解一下攻击树(从攻击者的视角审视自身系统)
  • 【MySQL体系】第7篇:MySQL锁机制深度解析与实战
  • 【代码随想录算法训练营——Day50(Day49周日休息)】图论——98.所有可达路径
  • 基于Django的医疗电子仪器系统
  • Django 用户认证流程详解:从原理到实现
  • 新版 vscode 去除快捷键 Ctrl+I 显示 Copilot 的 AI 对话框
  • 工业智能车载台应用在什么场景?有什么功能?
  • ES7243E ADC模拟音频转i2S到 BES I2S1 Master输出播放到SPK精准分析
  • Oracle 19c 归档日志挖掘(Log Mining)完全指南