三种访问Mat中元素的方法为:
- 指针访问
- 迭代器iterator
- 动态地址访问
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