【OpenCV】OpenCV中遍历图像像素的几种方式对比

本文详细介绍了OpenCV中遍历图像像素的五种方法,包括数组遍历、at(i,j)、指针遍历、迭代器遍历,并通过实例和耗时测试比较了它们的效率和安全性。指针法在效率上占优,而迭代器法则确保了安全。" 3092867,444168,使用JavaScript实现回车键模拟Tab键切换,"['javascript', 'HTML', '表单交互']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

Mat 类是OpenCV中的一个基本数据类型,它是一个n维密集数组类
Mat 类表示一个 n 维密集数值单通道或多通道数组。它可用于存储实数或复值向量和矩阵、灰度或彩色图像、体素体积、向量场、点云、张量、直方图。本文将总结几种遍历像素的不同方法,在需要处理大量图片的场景,不同的遍历方法,速度上会有显著差异。

一、Mat数据类型

Mat包含两个数据部分的类:矩阵头(包含诸如矩阵大小,用于存储的方法,存储的矩阵地址等信息)和指向包含像素值矩阵(根据选择的存储方法而有不同的维度)的指针.矩阵头大小是个常量,不同大小的图像的矩阵大小各不相同,通常矩阵大小要比图像大小大几个数量级。
Mat的数据类型及取值范围
在这里插入图片描述当Mat为单通道灰度图时,其在内存中的排布如下:
在这里插入图片描述

当Mat为多通道图像时,以3通道为例,其在内存中的排布方式如下:
在这里插入图片描述
通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。OpenCV中提供了 isContinuous()函数来判断图像数组是否为连续的。

二、Mat数据的遍历方法

1.数组遍历法

代码如下:

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
   
   
	Mat src = imread("./2.png",0);
	int width = src.cols;
	int height = src.rows;
	//单通道
	for (int i = 0; i < height; i++)
	{
   
   
		for (int j = 0; j < width; j++)
		{
   
   
			src.data[i * width + j]+=50;
		}
	}
	
	//三通道
	/*for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			int index = i * width + j;
			src.data[3 * index + 0]+=50;
			src.data[3 * index + 1]+= 50;;
			src.data[3 * index + 2]+=50;
			
		}
	}
*/
	imwrite("test.png", src);
	return 0;
}

原图
在这里插入图片描述
结果图
在这里插入图片描述

2. at(i,j)

Mat类提供了一个at的方法用于取得图像上的点,它是一个模板函数,可以取到任何类型的图像上的点。此typename的定义如下:
在这里插入图片描述

测试代码如下:

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
   
   
	Mat src = imread("./2.png", -1);

	//灰度图
	if (1 == src.channels())
	{
   
   
		for (int y = 0; y < src.rows; y++)
		{
   
   
			for (int x = 0; x < src.cols; x++)
			{
   
   
				src.at<uchar>(y, x) = 255 - src.at<uchar>(y, x);
			}
		}
	}
	else if(3 == src.channels())
	{
   
   
		//彩色图
		for (int y = 0; y < src.rows; y++)
		{
   
   
			for (int x = 0; x < src.cols; x++)
			{
   
   
				cv::Vec3b bgr = src.at<cv::Vec3b>(y, x);
				bgr[0] = 255 - bgr[0];
				bgr[1] = 255 - bgr[1];
				bgr[2] = 255 - bgr[2];
				src.at<cv::Vec3b>(y, x) = bgr;
			}
		}
	}

	imwrite("test.png",src);
}

原图
在这里插入图片描述
结果图
在这里插入图片描述

3、指针遍历法

利用.ptr和数组下标进行图像像素遍历,这种图像遍历方法相比“数组遍历法”更高效。
示例代码:

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shanhedian2013

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值