c++如何读取和显示OpenCV中的Mat图像原始数据【技巧】

风杰酱_1106

风杰酱_1106

2026-04-11

785人浏览

原创

opencv中访问mat像素的三种常用方法是:1. at()方法(安全但慢,适合调试和单点访问);2. ptr()指针法(速度快,推荐整行或全图遍历);3. data指针直接操作(最底层、高效,需注意连续性、通道数和步长)。

c++如何读取和显示opencv中的mat图像原始数据【技巧】

Mat.data 指针直接访问原始像素最常用

OpenCV 的 cv::Mat 图像数据本质就是一块连续内存,data 成员是指向首字节的 uchar*(即 unsigned char*)。只要图像连续(mat.isContinuous() == true),就能用指针算术一次性读取全部原始数据。

常见错误是忽略通道数和步长(step):即使图像连续,mat.step[0] 也可能大于 mat.cols * mat.elemSize()(比如内存对齐 padding),但此时 mat.isContinuous() 仍为 true,所以安全做法是优先用 mat.data + mat.total() * mat.elemSize() 计算总字节数,而非硬算 rows * cols * channels。

  • 灰度图:mat.data[i] 就是第 i 个像素值(0–255)
  • BGR 三通道图:mat.data[i*3], mat.data[i*3+1], mat.data[i*3+2] 分别对应 B、G、R
  • 务必先检查 !mat.empty(),否则 data 为空指针,解引用会崩溃

用 ptr() 安全获取某行首地址

当需要按行处理(比如逐行滤波或避免越界),mat.ptr<uchar>(row)</uchar> 比手动算偏移更可靠。它返回第 row 行首像素的指针,类型由模板参数 T 决定,自动适配通道布局。

例如 cv::Mat mat(100, 200, CV_8UC3),mat.ptr<uchar>(5)</uchar> 返回的是第 5 行第一个像素的 B 值地址,后面连续 3 字节分别是 B/G/R;而 mat.ptr<vec3b>(5)</vec3b> 则返回 Vec3b*,可直接写 ptr[0][0](B)、ptr[0][1](G)等。

  • 越界行为未定义:传入 row >= mat.rows 时,OpenCV 不做检查,结果不可预测
  • ptr<t>()</t> 返回的是该行首地址,不是整张图首地址,别和 mat.data 混用
  • 若图像不连续(!mat.isContinuous()),每行必须单独调用 ptr,不能跨行连续访问

显示原始数据别只看前几个字节

用 printf 或 std::cout 打印 mat.data 前 10 字节,大概率看到全是 0 或杂乱值——因为图像顶部常有黑边、padding 或 YUV 转换残留。真正有意义的原始数据往往在中间区域或需结合 mat.type() 解读。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

mat.type() 返回的是 OpenCV 类型常量,如 CV_8UC1(单通道 uchar)、CV_8UC3(三通道 uchar)、CV_32FC1(单通道 float)。打印前必须按实际类型 reinterpret_cast,否则 uchar 指针强转 float 会读错字节顺序。

  • 错误示范:float* fptr = (float*)mat.data; —— 若 mat 是 CV_8UC3,这会把每 4 字节解释成一个 float,完全错乱
  • 正确做法:先 switch(mat.type()),再用 mat.ptr<float>(i)</float> 或 mat.at<float>(i,j)</float>
  • 调试时建议用 cv::imshow("raw", mat) 对照查看,比纯数字更直观

at() 适合稀疏访问,别用来遍历整图

mat.at<uchar>(i,j)</uchar> 或 mat.at<vec3b>(i,j)</vec3b> 提供带边界检查的随机访问,语法清晰,但每次调用都做行/列范围判断和地址计算,性能开销显著。实测遍历 1080p 图像,用 at 比用 ptr 慢 3–5 倍。

它真正的价值在调试和少量坐标访问,比如检查某个疑似异常点:auto p = mat.at<vec3b>(100, 200); cout </vec3b>

  • at 不支持 CV_8UC1 直接写 mat.at<uchar>(i,j)</uchar>?错,支持,但注意 uchar 是 typedef,确保头文件包含完整
  • 多通道时,at<vec3b>(i,j)[0]</vec3b> 是 B,不是 R;OpenCV 默认 BGR 顺序,别按 RGB 习惯读
  • release 模式下 at 的边界检查可能被优化掉,调试时务必开 debug 模式验证逻辑

原始数据本身没“格式”可言,关键是你怎么解释它:字节序、通道顺序、数据类型、内存是否连续,缺一不可。漏掉任意一项,看到的就只是乱码。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

2024.04.28

6667

8

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

2025.10.23

764

4

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6104

49

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

2023.09.21

1071

6

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

2024.03.13

1417

13

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

2023.06.20

808

5

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.28

1029

10

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

359

31

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

2025.11.16

179

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习