OpenCV2+入门系列(三):遍历图像的几种方法

  根据OpenCV中Mat类型的结构和内存中存储方式,此处给出三种对图像进行遍历的方法。首先给出基础的读取图片代码,在中间替换三种遍历方法即可,本文中,程序将遍历图像并将所有像素点置为255,所有运行结果中命令行里的数字为程序执行时间

#include "stdafx.h"
#include <opencv2/core/core.hpp>
#include "highgui.h"
#include <iostream>
using namespace cv;
using namespace std;
int main() {
    Mat image = imread("D:\\Users\\Documents\\WinForm\\cpp_learn\\teach1\\Debug\\img.jpg",CV_LOAD_IMAGE_COLOR);//读取img.jpg到image中,此处可以写相对路径也可以写绝对路径
    namedWindow("图片1");//定义一个名为“图片1”的窗口
    imshow("图片1", image);//在窗口“图片1”中显示image
    
    double time = static_cast<double>(cv::getTickCount());
    
    //遍历元素
    
    time = static_cast<double>(cv::getTickCount()) - time;
    time /= cv::getTickFrequency();
    cout<<time<<endl;
    
    namedWindow("图片2");//定义一个名为“图片1”的窗口
    imshow("图片2", image);//在窗口“图片1”中显示image
    waitKey(0);
    return 1;
}

 

一、一个一个点的读取

  作为最低效率的一种方法,本法的思想就是从第一行第一列开始依次读第一行第二列、第三列,然后是第二行、第三行。其核心代码就是

image.at<uchar>(i,j)//读取灰度图像的点
image.at<cv::Vec3b>(i,j)[0]//读取彩色图像点的0通道

该方法可以读取图像中i行j列的点,代码如下:

    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            //Do anything you want
            if(image.channels() == 1)
            {
                image.at<uchar>(i,j) = 255;
            }
            else if(image.channels() == 3)
            {
                image.at<cv::Vec3b>(i,j)[0] = 255;
                image.at<cv::Vec3b>(i,j)[1] = 255;
                image.at<cv::Vec3b>(i,j)[2] = 255;
            }
        }
    }

二、 通过指针遍历图像

  由于Mat图像在内存中是连续排布的,因此定义指针指向行首地址后,指针每+1就会移到下一个元素上,此时直接操作指针所指内容就可以实现图像的操作。

    int image_rows = image.rows;//行数
    int elementCount = image.cols*image.channels();//每行元素数
    if (image.isContinuous())//如果图像没有经过填补 内存是连续排序
    {
        //则把图像看成行数X每行元素数个元素的一行,只进行一次循环
        elementCount = elementCount*image_rows;
        image_rows = 1;
    }
    for (int i = 0; i < image_rows; i++)
    {
        uchar* linehead = image.ptr<uchar>(i);//每行的起始地址
        for (int j = 0; j < elementCount; j++)
        {
            //遍历元素 Do anything you want
            linehead[j] = 255;
        }
    }

  值得注意的是,在内存上行与行之间的元素可能不是连续的(有时为提高效率,会将行元素填补为4的倍数),因此如果要连续用指针遍历图像,首先应判断图像是否有填补。

三、迭代器遍历

  这个和指针比较像,不细说了,上代码。

    Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
    Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
    for (; it!= itend; it++)
    {
        (*it)[0] = 255;
        (*it)[1] = 255;
        (*it)[2] = 255;
    }

 

转载于:https://www.cnblogs.com/singlex/p/4106702.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值