c++图像遍历方式以及底层原理

key1:使用指针遍历,这是最常见的方式。

使用cv::Mat类型的属性,rows是Mat类型的行数,cols是列数,channels()是通道数,那么对于图像的每一行,都有cols*channels()个像素点,所以我们可以对所有行进行遍历,然后对于特定一行,遍历所有像素点,代码如下:

int nl= image.rows; // 行数
// 每行的元素数量
int nc= image.cols * image.channels();
for (int j=0; j<nl; j++) {
    // 取得行 j 的地址
    uchar* data= image.ptr<uchar>(j);
    for (int i=0; i<nc; i++) {
        // 处理每个像素 ---------------------
        data[i]= 0;
        // 像素处理结束 ----------------
    } // 一行结束
}

ptr是一个模板属性,可以用来获取地址,相同的一个属性也可以用at。

而我们为什么要按行遍历而不直接从第一个元素位置直接遍历nl*nc个呢?

这是因为在彩色图像中,图像数据缓冲区的前 3 字节表示左上角像素的三个通道的值,接下来的 3字节表示第 1 行的第 2 个像素,以此类推(注意 OpenCV 默认的通道次序为 BGR)。一个宽 W高 H 的图像所需的内存块大小为 W×H×3 uchars。不过出于性能上的考虑,我们会用几个额外的像素来填补行的长度。这是因为,如果行数是某个数字(例如 8)的整数倍,图像处理的性能可能会提高,因此最好根据内存配置情况将数据对齐。所以并不一定每行最后一个元素后边一定是下一行的第一个元素!

我们可以使用isContinuous()来检查是的有填充,如果没有填充,isContinuous()会返回true,所以我们可以采用下边方法遍历:

int nl= image.rows; // 行数
// 每行的元素总数
int nc= image.cols * image.channels();
if (image.isContinuous()) {
// 没有填充的像素
     nc= nc*nl;
     nl= 1; // 它现在成了一个一维数组
}

for (int j=0; j<nl; j++) {
    uchar* data= image.ptr<uchar>(j);
    for (int i=0; i<nc; i++) {
        *data++ = 0;
    } // 一行结束
}

key2:使用迭代器

使用OpenCV的cv::Mat 实例的迭代器,首先要创建一个 cv::MatIterator_对象。跟 cv::Mat_类似,这个下划线表示它是一个模板子类。因为图像迭代器是用来访问图像元素的,所以必须在编译时就明确返回值的类型。可以这样定义彩色图像的迭代器:

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

也可以使用在 Mat_模板类内部定义的 iterator 类型:

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

然后就可以使用常规的迭代器方法 begin 和 end 对像素进行循环遍历了。不同之处在于它们仍然是模板方法。

举个例子,对一张彩色图片进行遍历的代码为:

// 迭代器
cv::Mat_<cv::Vec3b>::iterator it= image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend= image.end<cv::Vec3b>();

// 扫描全部像素
for ( ; it!= itend; ++it) {
    //对像素点的处理
    (*it)[0] = 255;
    (*it)[1] = 255;
    (*it)[2] = 255;
}

原文链接:https://javaforall.cn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SetMaker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值