opencv学习-Mat类图像的遍历
原图:
2.1 简单存取像素值
// Mat类图像遍历.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img=imread("1.jpg");
Size size=Size(600,400);
resize(img,img,size);
//遍历方式
//1 简单存取像素值
switch(img.channels())
{
case 1:
{for(int i=0;i<img.rows;i++)
{
for(int j=0;j<img.cols;j++)
{
img.at<uchar>(i,j)=0;
}
}
break;
}
case 3:
{
for(int i=0;i<img.rows;i++)
{
for(int j=0;j<img.cols;j++)
{
img.at<Vec3b>(i,j)[0]=0;
img.at<Vec3b>(i,j)[1]=0;
}
}
break;
}
}
namedWindow("celtics",1);
imshow("celtics",img);
waitKey(0);
return 0;
}
由于opencv颜色顺序为BGR,将前面两种颜色置0,得到红色分量。
结果:
2.2 指针遍历
// Mat类图像遍历.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img=imread("1.jpg");
Size size=Size(600,400);
resize(img,img,size);
//遍历方式
// 2 指针
int nrows=img.rows;
int ncols=img.cols*img.channels();
if(img.isContinuous())
{
ncols*=nrows;
nrows=1;
}
uchar *data;
for(int j=0;j<nrows;j++)
{ data=img.ptr<uchar>(j);
for(int i=0;i<ncols;i+=3)
{
data[i]=0;
data[i+1]=0;
}
}
namedWindow("celtics",1);
imshow("celtics",img);
waitKey(0);
return 0;
}
同样将B、G分量置0,得到红色分量。
结果:
2.3 迭代器
// Mat类图像遍历.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img=imread("1.jpg");
Size size=Size(600,400);
resize(img,img,size);
//遍历方式
//3 迭代器
//迭代1 Mat_内部迭代器
//Mat_<Vec3b>::iterator it=img.begin<Vec3b>();
//Mat_<Vec3b>::iterator itend=img.end<Vec3b>();
//迭代2 Mat 实例迭代器 模板类
MatIterator_<Vec3b> it=img.begin<Vec3b>();
MatIterator_<Vec3b> itend=img.end<Vec3b>();
for(;it!=itend;it++)
{
(*it)[0]=0;
(*it)[1]=0;
}
namedWindow("celtics",1);
imshow("celtics",img);
waitKey(0);
return 0;
}
结果:
2.4 遍历效率比较
// Mat类图像遍历.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img=imread("1.jpg"),img1,img2,img3;
Size size=Size(600,400);
resize(img,img,size);
//遍历方式
//1 简单存取像素值
img1=img;
double t1=static_cast<double>(getTickCount());
switch(img1.channels())
{
case 1:
{for(int i=0;i<img1.rows;i++)
{
for(int j=0;j<img1.cols;j++)
{
img1.at<uchar>(i,j)=0;
}
}
break;
}
case 3:
{
for(int i=0;i<img1.rows;i++)
{
for(int j=0;j<img1.cols;j++)
{
img1.at<Vec3b>(i,j)[0]=0;
img1.at<Vec3b>(i,j)[1]=0;
}
}
break;
}
}
t1=static_cast<double>(getTickCount())-t1;
t1/=getTickFrequency();
//2 指针
img2=img;
double t2=static_cast<double>(getTickCount());
int nrows=img2.rows;
int ncols=img2.cols*img.channels();
if(img2.isContinuous())
{
ncols*=nrows;
nrows=1;
}
uchar *data;
for(int j=0;j<nrows;j++)
{ data=img2.ptr<uchar>(j);
for(int i=0;i<ncols;i+=3)
{
data[i]=0;
data[i+1]=0;
}
}
t2=static_cast<double>(getTickCount())-t2;
t2/=getTickFrequency();
//3 迭代器
//迭代1 Mat_内部迭代器
//Mat_<Vec3b>::iterator it=img.begin<Vec3b>();
//Mat_<Vec3b>::iterator itend=img.end<Vec3b>();
//迭代2 Mat 实例迭代器 模板类
img3=img;
double t3=static_cast<double>(getTickCount());
MatIterator_<Vec3b> it=img3.begin<Vec3b>();
MatIterator_<Vec3b> itend=img3.end<Vec3b>();
for(;it!=itend;it++)
{
(*it)[0]=0;
(*it)[1]=0;
}
t3=static_cast<double>(getTickCount())-t3;
t3/=getTickFrequency();
//时间效率比较
cout<<"简单存取时间(ms)"<<t1<<endl;
cout<<"指针遍历时间(ms)"<<t2<<endl;
cout<<"迭代器遍历时间(ms)"<<t3<<endl;
namedWindow("celtics",1);
imshow("celtics",img);
waitKey(0);
return 0;
}
结果:
总结:
迭代方式最慢,指针遍历效果最好,简单存取一般用于随机位置读写。