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

3通道图的数据在opencv的mat是如何存放的

在 OpenCV 中,3 通道图像(如常见的 RGB 或 BGR 图像)的数据存储在 cv::Mat 对象中,其存储方式是基于行优先的连续内存布局。这意味着图像的像素数据是按行顺序存储的,并且每个像素包含 3 个通道的值。以下是详细的解释:

1. 内存布局

对于一个 3 通道图像,cv::Mat 的内存布局如下:

  • 行优先存储:图像的每一行数据是连续存储的。

  • 通道顺序:在 OpenCV 中,默认的通道顺序是 BGR(蓝、绿、红),而不是 RGB。

  • 像素格式:每个像素由 3 个字节组成,分别表示蓝色、绿色和红色通道的值。

假设有一个图像 img,其大小为 rows×cols,类型为 CV_8UC3(表示每个通道是 8 位无符号整数,共有 3 个通道)。那么:

  • 每个像素占用 3 个字节。

  • 每行的字节数为 cols×3。

  • 整个图像的内存大小为 rows×cols×3 字节。

2. 数据访问

在 OpenCV 中,可以通过多种方式访问 3 通道图像的像素数据:

2.1 使用 at<>() 方法

cv::Mat::at<>() 是一种安全的像素访问方法,适用于单个像素的读写操作。对于 3 通道图像,可以使用 cv::Vec3b 类型来访问像素值:

cv::Mat img = cv::imread("image.jpg");
if (img.empty()) {std::cerr << "无法加载图像!" << std::endl;return -1;
}// 访问第 (y, x) 位置的像素
int y = 10, x = 20;
cv::Vec3b pixel = img.at<cv::Vec3b>(y, x);// 获取每个通道的值
uchar blue = pixel[0];   // 蓝色通道
uchar green = pixel[1];  // 绿色通道
uchar red = pixel[2];    // 红色通道// 修改像素值
img.at<cv::Vec3b>(y, x) = cv::Vec3b(255, 0, 0); // 设置为蓝色
2.2 使用指针访问

对于性能敏感的应用,可以直接通过指针访问像素数据。这种方式更高效,但需要手动计算偏移量:

cv::Mat img = cv::imread("image.jpg");
if (img.empty()) {std::cerr << "无法加载图像!" << std::endl;return -1;
}// 获取图像的指针
uchar* data = img.data;// 访问第 (y, x) 位置的像素
int y = 10, x = 20;
int cols = img.cols;
int channels = img.channels();// 计算偏移量
int offset = y * cols * channels + x * channels;// 获取每个通道的值
uchar blue = data[offset];
uchar green = data[offset + 1];
uchar red = data[offset + 2];// 修改像素值
data[offset] = 255;      // 蓝色通道
data[offset + 1] = 0;    // 绿色通道
data[offset + 2] = 0;    // 红色通道
2.3 使用迭代器

OpenCV 提供了迭代器,可以方便地遍历图像的像素:

cv::Mat img = cv::imread("image.jpg");
if (img.empty()) {std::cerr << "无法加载图像!" << std::endl;return -1;
}cv::MatIterator_<cv::Vec3b> it = img.begin<cv::Vec3b>(), it_end = img.end<cv::Vec3b>();
for (; it != it_end; ++it) {cv::Vec3b& pixel = *it;pixel[0] = 255;  // 设置蓝色通道为 255pixel[1] = 0;    // 设置绿色通道为 0pixel[2] = 0;    // 设置红色通道为 0
}

3. 内存对齐

在某些情况下,cv::Mat 的每一行可能会有额外的填充字节,以确保内存对齐。这可以通过 cv::Mat::step 属性来获取每行的实际字节数:

int step = img.step[0]; // 每行的实际字节数

对于连续存储的图像(大多数情况下),step 等于 cols * channels * sizeof(uchar)。如果图像不是连续存储的(例如,通过 cv::Mat::rowcv::Mat::col 提取的子图像),step 可能会大于预期。

4. 示例:遍历图像

以下是一个完整的示例,展示如何遍历 3 通道图像并修改像素值:

#include <opencv2/opencv.hpp>
#include <iostream>int main() {cv::Mat img = cv::imread("image.jpg");if (img.empty()) {std::cerr << "无法加载图像!" << std::endl;return -1;}// 遍历图像的每一行for (int y = 0; y < img.rows; ++y) {// 获取当前行的指针uchar* row = img.ptr<uchar>(y);// 遍历当前行的每一列for (int x = 0; x < img.cols; ++x) {// 计算偏移量int offset = x * 3;// 获取每个通道的值uchar blue = row[offset];uchar green = row[offset + 1];uchar red = row[offset + 2];// 修改像素值row[offset] = 255;      // 蓝色通道row[offset + 1] = 0;    // 绿色通道row[offset + 2] = 0;    // 红色通道}}// 显示结果cv::imshow("Processed Image", img);cv::waitKey(0);return 0;
}

5. 总结

在 OpenCV 中,3 通道图像的数据存储在 cv::Mat 对象中,采用行优先的连续内存布局,每个像素包含 3 个通道的值(默认为 BGR 顺序)。可以通过 at<>() 方法、指针访问或迭代器来操作像素数据。了解这些细节有助于高效地处理图像数据。

http://www.xdnf.cn/news/13375.html

相关文章:

  • flow_controllers
  • plantuml画uml图
  • Python实例题:Python计算离散数学
  • 使用swagger来生成文档
  • C++中优雅的属性封装:Sint类设计分析
  • 网络六边形受到攻击
  • PLC入门【5】基本指令3(PLS PLF ZRST)
  • TestCafe API
  • vue3 + element plus -- table表格使用sortablejs实现表格拖拽换位功能
  • 麒麟Kylin V10 SP3服务器操作系统安装
  • 项目进度管理软件是什么?项目进度管理软件有哪些核心功能?
  • LoRA(Low-Rank Adaptation,低秩适应)
  • leetCode- 两数相加
  • 【AI学习】一、向量表征(Vector Representation)
  • 报告精读:金融算力基础设施发展报告 2024【附全文阅读】
  • 构建欺诈事件的结构化威胁建模框架
  • Coze 和 Dify 对比
  • 销售心得分享
  • 保险风险预测数据集insurance.csv
  • vivado IP核High speed/Low latency设置对系统性能的影响
  • 深入浅出Diffusion模型:从原理到实践的全方位教程
  • 改进系列(13):基于改进U-ResNet的脊椎医学图像分割系统设计与实现
  • 游戏盾的功能是什么
  • 关于前端常用的部分公共方法(二)
  • 2.6 查看动态库或程序的依赖库
  • PH热榜 | 2025-06-06
  • 高保真组件库:上传
  • “深时数字地球”新进展!科学智能助推地球科学研究范式变革
  • if综合演练——石头剪刀布
  • 命令行关闭Windows防火墙