今天刚看了一个公开课,学到了更多的访问像素的方法。
1、借助at<>()模板函数访问像素
2、借助迭代器访问
3、借助ptr<>()函数访问
4、借助Mat对象的step数组属性进行访问(不推荐容易越界)
// op_pixels.cpp: 采用四种方法访问像素
//
#include "stdafx.h"
#include<iostream>
#include<opencv2\highgui\highgui.hpp>
#include<ctime>
#include<cmath>
using namespace std;
using namespace cv;
int main()
{
Mat m(200,200,CV_8UC3),n(200, 200, CV_8UC3), l(200, 200, CV_8UC3),p(200,200,CV_8UC1);
clock_t startTime, endTime;//用来记录这几种方法的时间
int colNum = m.cols;
int rowNum = m.rows;
//采用at<Vec3b>(i,j)访问像素,效率是最低的,我画了一个圆
startTime = clock();
for(int i=0;i<colNum;i++)
for (int j = 0; j < rowNum; j++)
{
if(pow(i-100,2)+pow(j-100,2)-2500<=100 && pow(i - 100, 2) + pow(j - 100, 2) - 2500 >=-100)
{
m.at<Vec3b>(i, j)[2] = 255;
}
}
endTime = clock();
cout << "使用at()方法所花费的时间为:" << (double)(endTime - startTime) / CLOCKS_PER_SEC << "秒" << endl;
imshow("at方法生成的圆", m);
//采用迭代器的方式来访问,由于没有i,j因此没有画圆,只是做了一些简单的变换
startTime = clock();
RNG rng; //opencv提供的一个生成随机数的类
Mat_<Vec3b>::iterator itbegin, itend;
for (itbegin = n.begin<Vec3b>(), itend = n.end<Vec3b>(); itbegin != itend; itbegin++)
{
int rand = rng.uniform(0,255);
if (rand % 3 == 0)
(*itbegin)[2] = 255;
}
endTime = clock();
cout << "使用迭代器方法所花费的时间为:" << (double)(endTime - startTime) / CLOCKS_PER_SEC << "秒" << endl;
imshow("迭代器访问生成的图", n);
//采用c数组风格访问图像元素,这部分也是画一个圆
startTime = clock();
for (int i = 0; i < rowNum; i++)
{
Vec3b *data = l.ptr<Vec3b>(i);
for (int j = 0; j < colNum; j++)
{
if (pow(i - 100, 2) + pow(j - 100, 2) - 2500 <= 100 && pow(i - 100, 2) + pow(j - 100, 2) - 2500 >= -100)
{
data[j][2] = 255;
}
}
}
endTime = clock();
cout << "使用类似c数组方法所花费的时间为:" << (double)(endTime - startTime) / CLOCKS_PER_SEC << "秒" << endl;
imshow("采用c数组风格访问图像生成的圆", l);
//采用指针计算方式进行访问,但是不推荐用这种方式,很容易会越界产生错误
for(int i=0;i<colNum;i++)
for (int j = 80; j < 120; j++) //j代表了行数
{
*(p.data + p.step[0]*j+p.step[1]*i)=255; //p是一个1*1的矩阵,step[0]中存储的是第一维中每个元素包含了多少个第二维的元素,因此step[0]=200,step[1]表示的是第二维中的每个元素有多少个第三维的元素,因此step[1]=1
}
imshow("p修改后的图", p);
waitKey(0);
return 0;
}
运行结果截图如下:令我意外的是使用迭代器时间反而比使用at<>()方法时间还要长