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

以指针方式遍历图像

for (size_t y = 0; y < image.rows; y++) 
	{
		//用cv::Mat::ptr获得行指针,unsigned表示无符号数
		unsigned char* row_ptr = image.ptr(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(i, j)[c];
			}
		}
	}
	chrono::steady_clock::time_point t4 = chrono::steady_clock::now();

迭代器方法遍历图像:

for (; it != image.end(); 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];
		}
	}

时间运行结果展示:

Open图像遍历方法总结与时间对比_第1张图片

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

总体代码展示:

#include
#include
#include
//计时器
#include
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(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::durationtime_used = chrono::duration_cast>(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(i, j)[c];
			}
		}
	}
	chrono::steady_clock::time_point t4 = chrono::steady_clock::now();
	//duration代表时间段,duration_cast数据强制转换,类似static_cast,类型转换
	chrono::durationtime_used_1 = chrono::duration_cast>(t4 - t3);
	cout << "at方法遍历图像用时" << time_used_1.count() << "秒" << endl;


	chrono::steady_clock::time_point t5 = chrono::steady_clock::now();
	cv::Mat_::iterator it = image.begin();
	for (; it != image.end(); it++) 
	{
		for (int c = 0; c != image.channels(); c++) {
			(*it)[c];
		}
	}
	chrono::steady_clock::time_point t6 = chrono::steady_clock::now();
	chrono::durationtime_used_2 = chrono::duration_cast>(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::durationtime_used_3 = chrono::duration_cast>(t8 - t7);
	cout << "行指针方法遍历图像用时" << time_used_3.count() << "秒" << endl;
}

 


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

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

你可能感兴趣的:(c++,开发语言)