[OpenCV2]使用迭代器遍历指针

来源:互联网 发布:最小的中文linux系统 编辑:程序博客网 时间:2024/04/28 21:48

在面向对象的程序中,在一个循环数据的收集中通常使用迭代器.迭代器是一个专门的类用了保存每个元素.对于一个给定的集合,如何获取每个元素的操作是看不到的.这个信息隐藏的原理的应用使得遍历容器更容易.此外,无论使用什么类型的的集合都是相似的.标准库模版(STL)有一个容器类和它的每一个集合类都是相关的.OpenCV提供了一个cv::Mat容器类,这个类与C++STL中的标准容器是兼容的.

Getting ready

在这一节中,我们还是使用颜色缩减的例子说明.

How to do it ...

对于一个cv::Mat对象,迭代器对象包含了首先创建一个cv::MatIterator_object的操作.在cv::Mat_subclass的情况中,这个下划线表名这是一个模版的方法.图像容器通常被用来返回图像元素,但是在编译的时候必须要知道返回类型.所以容器被声明如下:

cv::MatIterator_<cv::Vec3b> it;

作为另一种选择,你也可使用Mat_template类 定义容器类型:

 cv::Mat_<cv::Vec3b>::iterator it;

通常使用begin和end容器方法循环遍历像素.因此我们的颜色缩减功能如下:

void colorReduce(cv::Mat &image, int div=64) {     // obtain iterator at initial position     cv::Mat_<cv::Vec3b>::iterator it=                image.begin<cv::Vec3b>();     // obtain end position     cv::Mat_<cv::Vec3b>::iterator itend=                image.end<cv::Vec3b>();     // loop over all pixels     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 ----------------     }}
要牢记容器的返回类型是cv::Vec3b,因为我们处理的是彩色图像.每个彩色通道使用重载操作符[]被存取.

How it works...

使用容器,无论是何种类型的集合,总是使用相同的模式.

首先,使用适当的专门的类在这里我们使用cv::Mat_<cv::Vec3b>::iterator(or cv::MatLterator_<cv::Vec3b>)创建容器对象.

你会获得一个在开始位置处的容器初始值(在我们的例子中,图像左上角的点),使用begin方法.在例子中,使用image.beigin<cv::Vec3b>()方法实现.你可以在迭代器上进行计算.例如:

如果你希望在一个图像的第二行开始,你可以使用image.begin<cv::Vec3b>()+image.rows初始化cv::Mat容器.容器的结束位置除了使用end方法,其他操作是相似的.然而,这个迭代器仅仅在你需要的几个的外侧.可以对迭代器进行计算,例如,如果你希望当迭代器指针到达图像最后一行前停止. 可以 end<cv::Vec3b>()-image.rows.

一旦你的容器初始化完毕,你就应当穿件循环遍历所有的元素直到结束.一个典型的while循环如下:

while (it!= itend) {                // process each pixel ---------------------         …        // end of pixel processing ----------------        ++it;     }
这个重载操作符++是用来移动到下一个元素的.你可以指定更大的步距.例如 it+=10会使得每次移动10像素.

最终,在循环操作中,你使用重载操作符*可以范围当前像素的值.(例如,element =*it读取;*it = element 写入).注意,也是可以创建一个常量容器的.如果你收到一个const cv::Mat引用或者你希望当前循环不会修改cv::Mat的初始值.可以如下定义:

     cv::MatConstIterator_<cv::Vec3b> it;or:     cv::Mat_<cv::Vec3b>::const_iterator it;

There's more...

在本节,使用模版方法begin和end获取容器的初始位置和结束位置.在我们这一章的第一个例子中,我们也可以使用cv::Mat_instance .这样在使用begin和end方法时就不需要指定模版类型了,因为当cv::Mat_reference创建的时候.

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


See also

使用迭代器遍历循环的效率将在以后讨论

如果你对面向对象编程不熟悉容器的使用,他们在ANSIC++中是如何操作的,你需要阅读STL容器的说明.简单的方法是你可以在网站上输入关键字"STL Iterator",你会获得大量的参考文献.