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;
    }

时间: 2024-10-11 01:19:42

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

Xen入门系列三【Xen 管理工具 xm】

xm命令是管理Xen的最基本的工具,可以通过xm --help 来获得帮助. 1. 列出所有正在运行的虚拟操作系统 # xm list PS[1]:可缩写为 xm li2. 启动虚拟机 # 通过配置文件启动虚拟机 # xm create <ConfigFile> # 通过虚拟机名称启动虚拟机,虚拟机必需已存在 xm list 中 # xm start <DomainName> 参数说明: ConfigFile:虚拟机配置文件 DomainName: 虚拟机名称 PS[2]:很多教程

RxJava入门系列三,响应式编程

RxJava入门系列三,响应式编程 在RxJava入门系列一,我向你介绍了RxJava的基础架构.RxJava入门系列二,我向你展示了RxJava提供的多种牛逼操作符.但是你可能仍然没能劝服自己使用RxJava,这一篇博客里我将向你展示RxJava提供的其他优势,没准了解了这些优势,你就真的想去使用RxJava了. 异常处理 直到目前为止,我都没有去介绍onComplete()和onError()方法.这两个方法是用来停止Observable继续发出事件并告知观察者为什么停止(是正常的停止还是因

C语言快速入门系列(三)

C语言快速入门系列(三) 结构化的程序设计 -----------------------------------转载请注明出处:coder-pig 本节引言: 在前面的学习中,我们对C语言的基本语法进行了了解,可以暂时理解成我们学了单词; 现在要做得就是学语法,也就是算法;就是构成一个一个基本的程序! 在这一节中我们要学习的是C语言中的输入输出,以及程序的三种结构(顺序,选择,循环结构) 本节学习路线图: 正文: 1.字符输入/输出函数 2.格式输入/输出函数 跟前面的单个字符的输入输出不同,

[转]C# 互操作性入门系列(三):平台调用中的数据封送处理

传送门 C#互操作系列文章: C#互操作性入门系列(一):C#中互操作性介绍 C#互操作性入门系列(二):使用平台调用调用Win32 函数 C#互操作性入门系列(三):平台调用中的数据封送处理 C#互操作性入门系列(四):在C# 中调用COM组件 本专题概要 数据封送介绍 封送Win32数据类型 封送字符串的处理 封送结构体的处理 封送类的处理 小结 一.数据封送介绍 看到这个专题时,大家的第一个疑问肯定是--什么是数据封送呢?(这系列专题中采用假设朋友的提问方式来解说概念,就是希望大家带着问题

C# 互操作性入门系列(三):平台调用中的数据封送处理

好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------------------------------------------------------------------- C#互操作系列文章: C#互操作性入门系列(一):C#中互操作性介绍 C#互操作性入门系列(二):使用平台调用调用Win32 函数 C#互操作性入门系列(三):平台调用中的数据封

mybatis入门系列三之类型转换器

mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名,java类属性类型-数据库字段类型 前面两个都容易设置,但是第三点要求经常会出现java类型和数据库的存储类型不一样, 例如java类型是String,数据库中存储的是char.varchar.text 对于一般常见的类型对应,mybatis已经内部包含了类型转换器,使String类型的java属性

c#图像处理入门(-bitmap类和图像像素值获取方法)

c#图像处理入门 -bitmap类和图像像素值获取方法 一.Bitmap类 Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象.该类的主要方法和属性如下: 1. GetPixel方法和SetPixel方法:获取和设置一个图像的指定像素的颜色. 2. PixelFormat属性:返回图像的像素格式. 3. Palette属性:获取和设置图像所使用的颜色调色板. 4. Height Width属性:返回图像的高度和

【JAVA】遍历Map的四种方法

public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>();  map.put("1", "value1");  map.put("2", "value2");  map.put("3", "value3");    //第一种:普

几何画板中作函数图像的几种方法

随着社会的发展,现代教学很多的地方都有了多媒体教学,这就需要一些教学软件的辅助了,几何画板就是其中之一.一些老师在使用几何画板的过程中,常常涉及到函数图象的绘制.因此,很多用户对这方面教程是非常的感兴趣的.下面就给大家分享一下几何画板中作函数图像的几种方法? 一.直接法 例1  画函数y=sinx在R上的图象. 操作步骤:单击“图表”菜单下“绘制新函数”f(x)=sinx. 二.轨迹法 例2  画函数y=(1/4)x^2在区间[-2,3]上的图象. 操作步骤: (1)单击“绘图”菜单下“绘制点”