OpenCV中访问图像像素的三种方法及快慢比较

三种访问Mat中元素的方法为:

  1. 指针访问
  2. 迭代器iterator
  3. 动态地址访问

1.用指针访问像素

指针访问像素利用的是C语言中的操作符[].从处理时间上看这种方法最快。Mat.ptr<>(i)取第i行的首地址,列数是Mat.cols列数乘以Mat.channels()通道数,元素一共就有列数*行数*通道数。

Mat image1=imread("name.jpg",1);
for(int i=0;i<image1.rows;i++)
{
    uchar* data=image1.ptr<uchar>(i);
    for(int j=0;j<image1.cols*image1.channels();j++)
    {
        cout<<int(data[j]);
    }
    cout<<endl;
}

2.用迭代器访问元素

使用迭代器访问与c++中STL迭代器类似。在迭代法中,我们需要获取图像矩阵的begin和end,然后增加迭代知道begin=end。将*操作符加载迭代器指针前,即可访问当前指向的内容。正向迭代器会指向下一个。

Mat image2=imread("name.jpg",1);
Mat_<Vec3b>::iterator it=image2.begin<Vec3b>();
Mat_<Vec3b>::iterator itend+image2.end<Vec3b>();
for(;it!=itend;++it)
{
    cout<<"B channel:"<<(*it)[0]<<"G channel:"<<(*it)[1]<<"R channel:"<<(*it)[3]<<endl;
}

3.动态地址访问

动态地址主要使用的是Mat类型的at方法实现的,这种方法比较容易理解,不过速度是最慢的。

Mat image3=imread("name.jpg",1);
for(int i=0;i<image3,rows;i++)
    for(int j=0;j<image3.cols;j++)
    {
        cout<<"B channel:"<<image3.at<Vec3b>(i,j)[0]<<"G channel:"<<image3.at<Vec3b>(i,j)[1]<<"R channel:"<<image3.at<Vec3b>(i,j)[2]<<endl;
    }

4.举例

以实现缩减像素颜色为例(就是将像素除以缩小的比例再乘以该比例,如比例为10,0-9范围的像素值全为0,10-19全变成1,256种值就变成26种值了),分别用三种方法写三个函数实现,完成例程如下:

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>

using namespace std;
using namespace cv;

void colorReduce1(Mat& inputImage,Mat& outputImage,int div); 
void colorReduce2(Mat& inputImage,Mat& outputImage,int div);
void colorReduce3(Mat& inputImage,Mat& outputImage,int div);

int main()
{
	Mat srcimage=imread("1.jpg",1);
	resize(srcimage,srcimage,Size(640,480));
	imshow("srcImage:",srcimage);
	Mat dstimage;
	dstimage.create(srcimage.rows,srcimage.cols,srcimage.type());
	double time0=static_cast<double>(getTickCount());
	colorReduce2(srcimage,dstimage,32);
	time0=(double)(getTickCount()-time0)/getTickFrequency();
	cout<<"the process time is:"<<time0<<endl;
	imshow("dstimage",dstimage);

	waitKey(0);
	return 0;
}

void colorReduce1(Mat& inputImage,Mat& outputImage,int div) //ptr
{
	outputImage=inputImage.clone();
	int rowNumber=outputImage.rows;
	int colNumber=outputImage.cols*outputImage.channels();
	for(int i=0;i<rowNumber;i++)
	{
		uchar* data=outputImage.ptr<uchar>(i);
		for(int j=0;j<colNumber;j++)
		{
			data[j]=data[j]/div*div+div/2;
		}
	}
}

void colorReduce2(Mat& inputImage,Mat& outputImage,int div) //iterator
{
	outputImage=inputImage.clone();
	Mat_<Vec3b>::iterator it =outputImage.begin<Vec3b>();
	Mat_<Vec3b>::iterator itend=outputImage.end<Vec3b>();
	for(;it!=itend;++it)
	{
		(*it)[0]=(*it)[0]/div*div+div/2; //three channels
		(*it)[1]=(*it)[1]/div*div+div/2;
		(*it)[2]=(*it)[2]/div*div+div/2;
	}
}

void colorReduce3(Mat& inputImage,Mat& outputImage,int div) //Mat.at<>()
{
	outputImage=inputImage.clone();
	int rowNumber=outputImage.rows;
	int colNumber=outputImage.cols;
	for(int i=0;i<rowNumber;i++)
	{
		for(int j=0;j<colNumber;j++)
		{
			outputImage.at<Vec3b>(i,j)[0]=outputImage.at<Vec3b>(i,j)[0]/div*div+div/2;
			outputImage.at<Vec3b>(i,j)[1]=outputImage.at<Vec3b>(i,j)[1]/div*div+div/2;
			outputImage.at<Vec3b>(i,j)[2]=outputImage.at<Vec3b>(i,j)[2]/div*div+div/2;
		}
	}
}

一样的处理,

指针访问用时:0.0072s

迭代器用时:0.1108s

at访问用时:0.1798s

猜你喜欢

转载自blog.csdn.net/zbr794866300/article/details/103721388