以指针方式遍历图像
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];
}
}
时间运行结果展示:
综上可知: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));