天天看点

opencv 3.0 Mat遍历:指针和STL

一. opencv 中的高效遍历自然是指针遍历

先上最优的代码

以下实例是参考OPENCV书上的

功能:像素颜色减少

1. 当数据存储内有补齐,是连续的。则使用指针统一遍历

2. 当多通道,内循环顺次处理3通道。减少循环的跳转。

// using .ptr and * ++ and bitwise (continuous+channels)
void colorReduce(cv::Mat &image, int div=64) {

	  int nl= image.rows; // number of lines
	  int nc= image.cols ; // number of columns

	  if (image.isContinuous())  {
		  // then no padded pixels
		  nc= nc*nl; 
		  nl= 1;  // it is now a 1D array
	   }

	  int n= static_cast<int>(log(static_cast<double>(div))/log(2.0));
	  // mask used to round the pixel value
	  uchar mask= 0xFF<<n; // e.g. for div=16, mask= 0xF0
              
      for (int j=0; j<nl; j++) {

		  uchar* data= image.ptr<uchar>(j);

          for (int i=0; i<nc; i++) {
 
            // process each pixel ---------------------
                 
            *data++= *data&mask + div/2;
            *data++= *data&mask + div/2;
            *data++= *data&mask + div/2;
 
            // end of pixel processing ----------------
 
            } // end of line                   
      }
}
           

相比以下的代码,上面的快10%

// using .ptr and * ++ and bitwise (continuous)
void colorReduce(cv::Mat &image, int div=64) {

	  int nl= image.rows; // number of lines
	  int nc= image.cols * image.channels(); // total number of elements per line

	  if (image.isContinuous())  {
		  // then no padded pixels
		  nc= nc*nl; 
		  nl= 1;  // it is now a 1D array
	   }

	  int n= static_cast<int>(log(static_cast<double>(div))/log(2.0));
	  // mask used to round the pixel value
	  uchar mask= 0xFF<<n; // e.g. for div=16, mask= 0xF0
              
      for (int j=0; j<nl; j++) {

		  uchar* data= image.ptr<uchar>(j);

          for (int i=0; i<nc; i++) {
 
            // process each pixel ---------------------
                 
            *data++= *data&mask + div/2;
 
            // end of pixel processing ----------------
 
            } // end of line                   
      }
}
           

二. 简洁的遍历自然是 STL

先上最优的代码

使用了模板Mat_  不仅简洁书写(不用写数据类型了),还加快效率。

// using MatIterator_ 
void colorReduce(cv::Mat &image, int div=64) {

	  // get iterators
	  cv::Mat_<cv::Vec3b> cimage= image;
	  cv::Mat_<cv::Vec3b>::iterator it=cimage.begin();
	  cv::Mat_<cv::Vec3b>::iterator itend=cimage.end();

	  for ( ; it!= itend; it++) { 
        
		// process each pixel ---------------------

        (*it)[0]= (*it)[0]/div*div + div/2;
        (*it)[1]= (*it)[1]/div*div + div/2;
        (*it)[2]= (*it)[2]/div*div + div/2;

        // end of pixel processing ----------------
	  }
}
           

相比以下的代码,上面的快2%

// using Mat_ iterator 
void colorReduce(cv::Mat &image, int div=64) {

	  // get iterators
	  cv::Mat_<cv::Vec3b>::iterator it= image.begin<cv::Vec3b>();
	  cv::Mat_<cv::Vec3b>::iterator itend= image.end<cv::Vec3b>();

	  for ( ; it!= itend; ++it) {
        
		// process each pixel ---------------------

        (*it)[0]= (*it)[0]/div*div + div/2;
        (*it)[1]= (*it)[1]/div*div + div/2;
        (*it)[2]= (*it)[2]/div*div + div/2;

        // end of pixel processing ----------------
	  }
}