C++ 高效的遍历opencv Mat像素


前言

在文章https://blog.csdn.net/weixin_44901043/article/details/120047996?spm=1001.2014.3001.5502 中,从内存存储上,分析了行优先遍历和列优先遍历方式效率差别,得出行优先遍历的方式比列优先效率快的结论。在该文中,采用的是Mat对象提供的at()函数通过行列索引方式遍历每个像素值。当然还有更加快速的遍历方式。

一、直接获取Mat对象的data数据的指针

代码如下:

//构造一个7000*7000大小的Mat
   cv::Mat matKernel = cv::Mat::zeros(7000, 7000, CV_32F);
   //循环10次
   int nums = 10;
   while (nums)
   {
       double t = (double)cv::getTickCount();
       for(int i = 0; i < matKernel.rows; i++)
       {
           float *pt = (float*)matKernel.data + i * matKernel.step/4;
           for(int j = 0; j < matKernel.cols; j++)
           {
              *(pt++) = 255;
           }
       }
       t = ((double)cv::getTickCount() - t) / cv::getTickFrequency()*1000; //获得时间,单位是毫秒
       cout << "data指针遍历:" << t<<"ms"<<endl;
       nums--;
   }

耗时如下:

在这里插入图片描述

二、再看看行优先和列优先遍历的耗时

行优先代码如下:

//构造一个7000*7000大小的Mat
   cv::Mat matKernel = cv::Mat::zeros(7000, 7000, CV_32F);
   //循环10次
   int nums = 10;
   while (nums)
   {
       double t = (double)cv::getTickCount();

       for(int i = 0; i < matKernel.rows; i++)
       {
           for(int j = 0; j < matKernel.cols; j++)
           {
               matKernel.at<float>(i,j) = 255;
           }
           //cout<<endl;
       }
       t = ((double)cv::getTickCount() - t) / cv::getTickFrequency()*1000; //获得时间,单位是毫秒
       cout << "行优先:" << t<<"ms"<<endl;
       nums--;
   }

耗时如下:

在这里插入图片描述

列优先代码如下:

//构造一个7000*7000大小的Mat
   cv::Mat matKernel = cv::Mat::zeros(7000, 7000, CV_32F);
   //循环10次
   int nums = 10;
   while (nums)
   {
       double t = (double)cv::getTickCount();
       for (int i = 0; i < matKernel.cols; i++)
       {
           for (int j = 0; j < matKernel.rows; j++)
           {
               matKernel.at<float>(j, i) = 255;
           }
       }
       t = ((double)cv::getTickCount() - t) / cv::getTickFrequency()*1000; //获得时间,单位是毫秒
       cout << "列优先:" << t<<"ms"<<endl;
       nums--;
   }

耗时如下:

在这里插入图片描述

三、总结

由以上对比,可以发现直接使用data指针访问图像像素是最快的方式。