OpenCV C++ 中,访问图像像素三种常用方法

✅ OpenCV C++ 访问像素的三种方法

🔹 方法 1:cv::Mat::at<>() 方法(推荐用于调试和小规模访问)

📌 特点:

复制代码
安全(带边界检查)
易用,语法直观
速度较慢(函数调用开销大)
适合调试、单点访问

🧩 语法:mat.at<数据类型>(行, 列)

cpp 复制代码
cv::Mat img = cv::imread("image.jpg");

// 访问灰度图像素(单通道)
if (img.channels() == 1) {
    uchar pixel = img.at<uchar>(100, 150);  // 第100行,第150列
    img.at<uchar>(100, 150) = 255;          // 修改像素
}

// 访问彩色图像素(三通道 BGR)
if (img.channels() == 3) {
    cv::Vec3b pixel = img.at<cv::Vec3b>(100, 150);
    uchar blue  = pixel[0];
    uchar green = pixel[1];
    uchar red   = pixel[2];

    // 修改像素为红色
    img.at<cv::Vec3b>(100, 150) = cv::Vec3b(0, 0, 255);
}

⚠️ 注意:

复制代码
类型必须匹配,否则会崩溃
cv::Vec3b 表示 3 个 unsigned char 的向量(BGR)

🔹 方法 2:指针访问 cv::Mat::ptr<>()(推荐用于遍历整行或全图)

📌 特点:

复制代码
速度快(直接指针操作)
常用于遍历图像每一行
无边界检查,需手动确保索引合法
最适合性能敏感的场景

🧩 语法:

cpp 复制代码
uchar* row_ptr = mat.ptr<uchar>(行);
row_ptr[列 * 通道数 + 通道索引]
cpp 复制代码
cv::Mat img = cv::imread("image.jpg");

for (int i = 0; i < img.rows; ++i) {
    uchar* row_ptr = img.ptr<uchar>(i);  // 指向第 i 行首地址
    for (int j = 0; j < img.cols; ++j) {
        // 三通道图像:BGR
        uchar blue  = row_ptr[j * 3 + 0];
        uchar green = row_ptr[j * 3 + 1];
        uchar red   = row_ptr[j * 3 + 2];

        // 修改为灰色
        uchar gray = (blue + green + red) / 3;
        row_ptr[j * 3 + 0] = gray;
        row_ptr[j * 3 + 1] = gray;
        row_ptr[j * 3 + 2] = gray;
    }
}

✅ 优势:

复制代码
内层循环中 row_ptr 是连续内存访问,CPU 缓存友好
比 at<>() 快 5~10 倍

🔹 方法 3:迭代器访问(安全且适合 STL 风格编程)

📌 特点:

复制代码
安全(带边界检查)
风格现代,类似 STL
速度中等
适合需要安全遍历的场景

🧩 语法:

cpp 复制代码
cv::MatIterator_<数据类型> it, end;
for (it = mat.begin<数据类型>(), end = mat.end<数据类型>(); it != end; ++it)
cpp 复制代码
cv::Mat img = cv::imread("image.jpg");
cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);  // 转为灰度图便于演示

// 使用迭代器遍历所有像素
cv::MatIterator_<uchar> it, end;
for (it = img.begin<uchar>(), end = img.end<uchar>(); it != end; ++it) {
    *it = 255 - *it;  // 反色操作
}
cpp 复制代码
cv::Mat color_img = cv::imread("image.jpg");
cv::MatIterator_<cv::Vec3b> it, end;
for (it = color_img.begin<cv::Vec3b>(), end = color_img.end<cv::Vec3b>(); it != end; ++it) {
    (*it)[0] = 0;  // B = 0
    (*it)[1] = 0;  // G = 0
    // 保持 R 不变 → 变红图
}
相关推荐
学习星球1 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
小灰灰搞电子2 小时前
C++ 引用折叠详解
c++
布莱克6053 小时前
数组详解:定义、作用、应用场景及与链表的区别(C/C++ 代码讲解)
c语言·开发语言·c++·数组
牛油果子哥q4 小时前
C++内存池与对象池精讲:内存碎片、自定义分配器、对象池实现、STL allocator原理、工程落地与性能对比
java·开发语言·c++
万法若空4 小时前
C/C++ 类型别名定义方式对比
java·c语言·c++
小小晓.5 小时前
C++ 值类别与完美转发深度剖析:从左值右值到 std::forward 源码解密
开发语言·c++·算法
AndrewHZ6 小时前
图像处理入门020 | 图像二值化:阈值分割基础 —— cv2.threshold 五种类型与自适应阈值铺垫
图像处理·opencv·文档扫描·阈值分割·图像二值化·trackbar·自适应阈值
hetao17338376 小时前
2026-08-27~29 hetao1733837 的刷题记录
c++·算法
格林威6 小时前
C# 相机Burst模式图像采集:使用相机内存配合OpenCvSharp和Halcon实现短时间的高速采集的方法
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
chen<>6 小时前
C++ 六种 memory_order:从原子性到线程间可见性.md
java·linux·开发语言·c++