Open图像遍历方法总结与时间对比

该博客详细介绍了使用指针、at函数、迭代器和data行指针四种方式遍历OpenCV图像,并通过计时器比较了它们的运行效率。实验结果显示,使用data行指针遍历图像的速度最快。代码示例展示了如何实现这四种遍历方法,并提供了时间消耗的输出。

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

以指针方式遍历图像

for (size_t y = 0; y < image.rows; y++) 
	{
		//用cv::Mat::ptr获得行指针,unsigned表示无符号数
		unsigned char* row_ptr = image.ptr<uchar>(y);
		for (size_t x = 0; x < image.rows; x++)
		{
			unsigned char* data_ptr = &row_ptr[x * image.channels()];//代表加上第x列的地址,移动到那一列
			//输出通道值
			for (int c = 0; c != image.channels(); c++)
			{
				unsigned char data=data_ptr[c];
			}
		}
			
	}

以at方式进行遍历图像:


	for (int i = 0; i < image.rows; i++) {
		for (int j = 0; j < image.cols; j++) {
			for (int c = 0; c != image.channels(); c++) {
				image.at<cv::Vec3b>(i, j)[c];
			}
		}
	}
	chrono::steady_clock::time_point t4 = chrono::steady_clock::now();

迭代器方法遍历图像:

for (; it != image.end<cv::Vec3b>(); it++) 
	{
		for (int c = 0; c != image.channels(); c++) {
			(*it)[c];
		}
	}

opencv自带data行指针遍历图像:

for (int row = 0; row < image.rows; row++) {
		//step为一行的字节数,相当于换行
		uchar* uc_pixel = image.data + row * image.step;
		for (int col = 0; col < image.cols; col++) {
			for (int c = 0; c != image.channels(); c++)
				uc_pixel[c];
		}
	}

时间运行结果展示:

综上可知:opencv自带行指针data方法遍历图像速度最快。

总体代码展示:

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
//计时器
#include<chrono>
using namespace std;

int main() 
{
	//读取图片
	cv::Mat image;
	image = cv::imread("C:\\Users\\11634\\Desktop\\name.jpg");
	//防卫性,保证读进去图片
	if (image.data == nullptr)
	{
		//错误信息输出流,通常使用cerr输出
		cerr << "文件不存在" << endl;
		return 0;
	}

	//输出基本信息
	cout << "图像宽度为" << image.cols << ",高为" << image.rows << ",通道数为" << image.channels() << endl;
	//cv::imshow("image", image);
	cv::waitKey(0);
	
	//判断图像类型,CV_8UC1单通道灰度图;CV_8UC3三通道彩色图
	if (image.type() != CV_8UC1 && image.type() != CV_8UC3)
	{
		//图像不符合要求
		cout << "请输入正确彩色或灰度图像" << endl;
		return 0;
	}
	chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
	for (size_t y = 0; y < image.rows; y++) 
	{
		//用cv::Mat::ptr获得行指针,unsigned表示无符号数
		unsigned char* row_ptr = image.ptr<uchar>(y);
		for (size_t x = 0; x < image.rows; x++)
		{
			unsigned char* data_ptr = &row_ptr[x * image.channels()];//代表加上第x列的地址,移动到那一列
			//输出通道值
			for (int c = 0; c != image.channels(); c++)
			{
				unsigned char data=data_ptr[c];
			}
		}
			
	}
	chrono::steady_clock::time_point t2 = chrono::steady_clock::now();

	chrono::duration<double>time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
	cout << "指针方法遍历图像用时" << time_used.count() << "秒" << endl;

	chrono::steady_clock::time_point t3 = chrono::steady_clock::now();
	for (int i = 0; i < image.rows; i++) {
		for (int j = 0; j < image.cols; j++) {
			for (int c = 0; c != image.channels(); c++) {
				image.at<cv::Vec3b>(i, j)[c];
			}
		}
	}
	chrono::steady_clock::time_point t4 = chrono::steady_clock::now();
	//duration代表时间段,duration_cast数据强制转换,类似static_cast,类型转换
	chrono::duration<double>time_used_1 = chrono::duration_cast<chrono::duration<double>>(t4 - t3);
	cout << "at方法遍历图像用时" << time_used_1.count() << "秒" << endl;


	chrono::steady_clock::time_point t5 = chrono::steady_clock::now();
	cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
	for (; it != image.end<cv::Vec3b>(); it++) 
	{
		for (int c = 0; c != image.channels(); c++) {
			(*it)[c];
		}
	}
	chrono::steady_clock::time_point t6 = chrono::steady_clock::now();
	chrono::duration<double>time_used_2 = chrono::duration_cast<chrono::duration<double>>(t6 - t5);
	cout << "迭代器方法遍历图像用时" << time_used_2.count() << "秒" << endl;


	chrono::steady_clock::time_point t7 = chrono::steady_clock::now();
	for (int row = 0; row < image.rows; row++) {
		//step为一行的字节数,相当于换行
		uchar* uc_pixel = image.data + row * image.step;
		for (int col = 0; col < image.cols; col++) {
			for (int c = 0; c != image.channels(); c++)
				uc_pixel[c];
		}
	}
	chrono::steady_clock::time_point t8 = chrono::steady_clock::now();
	chrono::duration<double>time_used_3 = chrono::duration_cast<chrono::duration<double>>(t8 - t7);
	cout << "行指针方法遍历图像用时" << time_used_3.count() << "秒" << endl;
}

 


补充:data指针通常不用于遍历图像,通常用于不是以opencv为主体的代码中,就不能直接使用Mat,而要转换为其它形式的数据结构。最简单的解决方案是指针,即将Mat拷贝到自定义的指针中,因为是拷贝数据所以必须要先分配内存。

memcpy(pdst,psrc,src.total()*sizeof(mtype));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值