zoukankan      html  css  js  c++  java
  • 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;
        }

     

    作者:VShawn

    出处:http://www.cnblogs.com/singlex/

    本文版权归作者所有,欢迎转载,但未经博客作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Windows下安装redis,并与PHP使用
    php中的一些小细节(1)
    MIME类型
    Oracle与SQL Server事务处理的比较
    php+memcached缓存技术实例
    B-树
    平衡二叉树(AVL)
    树--二叉查找树(二叉排序树)
    八种常见的排序算法
    反转一个值中的最后n位
  • 原文地址:https://www.cnblogs.com/singlex/p/4106702.html
Copyright © 2011-2022 走看看