前言
在面向对象的编程中,循环数据集合通常是使用迭代器完成的。迭代器是专门为遍历集合的每个元素而构建的类,隐藏了如何迭代给定集合中每个元素的具体操作。信息隐藏原理的应用使扫描集合更容易、更安全;同时,无论使用什么类型的集合,迭代的形式都是相似的。标准模板库 (Standard Template Library
, STL
) 具有与其每个集合类相关联的迭代器类。而 OpenCV
同样提供了一个 cv::Mat
迭代器类,该类与 C STL
中的标准迭代器兼容。在本节中,我们使用继续减色任务讲解如何使用迭代器扫描图像。
使用迭代器扫描图像
Cv::Mat
实例的迭代器对象可以通过首先创建一个 cv::MatIterator_
对象来获得。与 cv::Mat_
的情况一样,下划线表示这是一个模板子类。实际上,由于图像迭代器用于访问图像元素,因此在编译时必须知道返回类型。迭代器声明如下:
cv::MatIterator_<cv::Vec3b> it;
复制代码
或者,也可以使用 Mat_
模板类中定义的迭代器类型:
cv::Mat_<cv::Vec3b>::iterator it;
复制代码
接下来,我们将迭代器应用于颜色减少任务。
要将迭代器应用于颜色减少任务,需要执行以下步骤。
1. 我们使用常见的开始和结束迭代器方法循环像素。首先,我们必须获得开始位置:
代码语言:javascript复制// 在初始位置获取迭代器
cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
复制代码
2. 然后,我们必须获得迭代器的结束位置:
代码语言:javascript复制// 获取结束位置
cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
复制代码
3. 接下来,我们必须循环迭代器直到结束位置:
代码语言:javascript复制// 循环所有像素
for ( ; it!= itend; it) {
复制代码
4. 最后,对像素应用颜色减少算法:
代码语言:javascript复制(*it)[0]= (*it)[0]/div*div div/2;
(*it)[1]= (*it)[1]/div*div div/2;
(*it)[2]= (*it)[2]/div*div div/2;
复制代码
由于我们正在处理彩色图像,以上代码中的迭代器会返回一个 cv::Vec3b
实例,使用解引用运算符 []
可以访问每个颜色通道元素。
无论扫描哪种类型的集合,使用迭代器始终需要遵循相同的模式。首先,使用适当的专用类创建迭代器对象,在以上代码中,我们使用了 cv::Mat_<cv::Vec3b>::iterator
(或 cv::MatIterator_<cv::Vec3b>
)。
然后,获取在起始位置(在以上代码中为图像的左上角)处使用 begin
方法初始化的迭代器。使用 cv::Mat
实例,可以通过 image.begin<cv::Vec3b>()
获取起始位置。我们也可以在迭代器上使用算术。例如,如果希望从图像的第二行开始迭代,可以在 image.begin<cv::Vec3b>() image.cols
处初始化 cv::Mat
迭代器。集合的结束位置的获取方式类似,但使用的是 end
方法。也可以在结束迭代器上使用算术;例如,如果希望在最后一行之前停止,最终迭代将在迭代器到达 image.end<cv::Vec3b>()-image.cols
时停止。