关于遍历Mat图像的每个像素,最常用的是遍历单通道灰度图和3通道彩色图。首先是单通道灰度图的像素遍历。
单通道灰度图遍历方法
单通道灰度图是一个最简单的二维矩阵,可以通过两层for循环和at<类型>(y,x)进行遍历,还可以使用指针进行遍历,或是用迭代器进行遍历。下面将分别演示这几种情况。
1.for循环加at方法遍历
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat girl = imread("images/girl.jpg", IMREAD_GRAYSCALE);//单通道灰度图(CV_8UC1)
if (girl.empty()) {
return 0;
}
imshow("window1", girl);//显示图像
imwrite("photo1.jpg", girl);//保存图像
for (int i = 0; i < girl.rows; i++)
{
for (int j = 0; j < girl.cols; j++)
{
uchar pixel = girl.at<uchar>(i, j);//读取像素点值
girl.at<uchar>(i, j) = 255 - pixel;//反色后写入像素值
}
}
imshow("window2", girl);//显示图像
imwrite("photo2.jpg", girl);//保存图像
waitKey(0);//等待按键
return 0;
}
在本例中,通过imread将原本是3通道的彩色图以单通道灰度图进行加载,随后显示该灰度图。

灰度图的每个像素点的数据类型为uchar,于是采用两层for循环嵌套,配合at<uchar>(i, j) 遍历每个像素点,计算其反色值后,再写回到每个像素点。最后效果如下图所示。

at<类型>(y, x)
的语法简单,直接通过坐标访问,每次调用会检查边界。特别是在Debug模式下有性能开效,如果需要高性能的连续内存遍历,推荐使用下面的指针遍历。
2.指针遍历
使用指针遍历图像是最快的方式,对于灰度图,通常按如下所示代码进行操作。
//指针遍历
for (int i = 0; i < girl.rows; i++)
{
uchar* row = girl.ptr<uchar>(i);//获取第i行指针
for (int j = 0; j < girl.cols; j++)
{
uchar pixel = row[j];//访问像素
row[j] = 255 - pixel;//修改像素(反色)
}
}
Mat类提供了ptr()函数,专用于获取某行的指针。如果想直接获取整个数据矩阵的指针,可直接访问Mat类的data。如果数据内存又是连续的,那么还有更高效的单循环遍历方式。如下面的代码所示。
//单循环指针遍历
if (girl.isContinuous()) {
uchar* data = girl.data;//获取整个图像的指针
int pixels = girl.rows * girl.cols;
for (int i = 0; i < pixels; i++)
{
data[i] = 255 - data[i];//反色
}
}
3.使用迭代器遍历
遍历访问Mat对象最安全的方式是使用迭代器,完全不需要担心越界的问题。迭代器的访问速度虽然比不上指针,但是比Mat.at<类型>()要快。
//迭代器遍历
MatIterator_<uchar> it = girl.begin<uchar>();
MatIterator_<uchar> end = girl.end<uchar>();
while (it != end) {
*it = 255 - *it;//反色
it++;
}
其中,MatIterator_是一个模板类,用于以迭代器(Iterator)的方式安全高效地遍历Mat矩阵中的像素,它类似于C++ STL(标准模板库)中的迭代器,提供了面向对象的像素访问方式。它的效率也是at<>快,但比指针慢。
4.forEach()函数遍历
这是Mat类提供的一个遍历矩阵元素的函数,结合了C++的Lambda表达式和并行化优化潜力,代码简洁,性能高效。特别适合对每个像素独立操作的场景,如阈值或颜色转换。
函数原型
mat.forEach<PixelType>([](PixelType &pixel, const int* position) {
// pixel: 当前像素的引用(可直接修改)
// position: 可选参数,像素位置 [y, x]
//PixelType:与 Mat 数据类型匹配(如 uchar、float、cv::Vec3b 等)。
});
使用示例
//foreach遍历
girl.forEach<uchar>([](uchar& pixel, const int* pos) {
pixel = 255 - pixel;
});
通过网盘分享的文件:001-遍历单通道灰度图.zip
链接: https://pan.baidu.com/s/1jviZHwpySzlNMvXo0tF8Sg 提取码: 8m96
——重庆教主 2025年5月8日
若文章对您有帮助,可以激励一下我哦,祝您平安幸福!
微信 | 支付宝 |
---|---|
![]() |
![]() |