为了构建计算机视觉应用程序,需要学会访问图像内容,有时也要修改或创建图像,如何操作图像的像素,就需要遍历一幅图像并处理每一个像素。现在我们就来介绍OpenCV三种图像像素的遍历方法:

一、 用cv::Mat类的at方法扫描图像
利用cv::Mat的at(int x,int y)方法可以访问元素,其中x是行号,y是列号。在编译时必须明确方法返回值的类型,因为cv::Mat可以接受任何类型的元素,所以程序员需要指定返回值的预期类型。正因为如此,at方法被实现成一个模板方法。在调用at方法时,你必须指定图像元素的类型,例如:

001

002

003

004

// 单通道图像

image.at<uchar>(i,j)= 255;

// 三通道图像

image.at<cv::Vec3b>(i, j) = cv::Vec3b(255, 255, 255);

用cv::Mat类的at方法扫描图像代码如下:

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

void visit_mat_by_at(cv::Mat &img)

{

    for (int i = 0; i < img.rows; i++)

    {

        for (int j = 0; j < img.cols; j++)

        {

            // 单通道图像

            if (img.channels() == 1)

            {

                img.at<uchar>(i, j) += 50;

            }

            // 三通道图像

            else

            {

                img.at<cv::Vec3b>(i, j)[0] += 50;

                img.at<cv::Vec3b>(i, j)[1] += 50;

                img.at<cv::Vec3b>(i, j)[2] += 50;

            }

        }

    }

}

二、 用指针扫描图像
一般来说,用指针扫描图像比较高效。在大多数图像处理任务中,执行计算时你都需要对图像的所有像素进行扫描。需要访问的像素数量非常庞大,因此你必须采用高效的方式来执行这个任务。

用指针扫描图像代码如下:

001

002

003

004

005

006

007

008

009

010

011

void visit_mat_by_pointer(cv::Mat &img)

{

    for (int i = 0; i < img.rows; i++)

    {

        uchar *data = img.ptr<uchar>(i);

        for (int j = 0; j < img.cols * img.channels(); j++)

        {

            data[j] += 50;

        }

    }

}

三、 用迭代器扫描图像
在面向对象编程时,我们通常用迭代器对数据集合进行循环遍历。迭代器是一种类,专门用于遍历集合的每个元素,并能隐藏遍历过程的具体细节。标准模板库(Standard Template Library,STL)对每个集合类都定义了对应的迭代器类,OpenCV也提供了cv::Mat的迭代器类,并且与C++ STL中的标准迭代器兼容。

用迭代器扫描图像代码如下:

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

void visit_mat_by_iterator(cv::Mat &img)

{

    // 单通道图像

    if (img.channels() == 1)

    {

        cv::Mat_<uchar>::iterator begin = img.begin<uchar>();

        cv::Mat_<uchar>::iterator end = img.end<uchar>();

        for (auto it = begin; it != end; it++)

        {

            *it += 50;

        }

    }

    // 三通道图像

    else

    {

        cv::Mat_<cv::Vec3b>::iterator begin = img.begin<cv::Vec3b>();

        cv::Mat_<cv::Vec3b>::iterator end = img.end<cv::Vec3b>();

        for (auto it = begin; it != end; it++)

        {

            (*it)[0] += 50;

            (*it)[1] += 50;

            (*it)[2] += 50;

        }

    }

}

测试代码:

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

#include <iostream>

#include <opencv2/opencv.hpp>

int main()

{

    // 单通道图像

    cv::Mat img1(3, 4, CV_8UC1, 100);

    std::cout << "单通道图像像素修改前:" << std::endl;

    std::cout << img1 << std::endl;

    visit_mat_by_at(img1);

    //visit_mat_by_pointer(img1);

    //visit_mat_by_iterator(img1);

    std::cout << "单通道图像像素修改后:" << std::endl;

    std::cout << img1 << std::endl;

    // 三通道图像

    cv::Mat img2(3, 4, CV_8UC3, cv::Scalar(100, 150, 200));

    std::cout << "三通道图像像素修改前:" << std::endl;

    std::cout << img2 << std::endl;

    visit_mat_by_at(img2);

    //visit_mat_by_pointer(img2);

    //visit_mat_by_iterator(img2);

    std::cout << "三通道图像像素修改后:" << std::endl;

    std::cout << img2 << std::endl;

    cv::waitKey();

    return 0;

}

运行结果:

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

单通道图像像素修改前:

[100, 100, 100, 100;

 100, 100, 100, 100;

 100, 100, 100, 100]

单通道图像像素修改后:

[150, 150, 150, 150;

 150, 150, 150, 150;

 150, 150, 150, 150]

三通道图像像素修改前:

[100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200;

 100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200;

 100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200]

三通道图像像素修改后:

[150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250;

 150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250;

 150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250]

说明我们完成遍历图像,并成功修改图像像素,至此大功告成~

OpenCV计算机视觉编程之三种图像像素的遍历方法相关推荐

  1. c++ opencv数字图像处理:访问图像像素,遍历图像像素

    文章目录 前言 一.访问图像像素 1.访问(j,i)处像素 2.例子:在图像中加入白色椒盐噪声 二.遍历图像像素 1.指针扫描 2.opencv自带的卷积运算:filter2D 前言 数字图像处理c+ ...

  2. OpenCV计算机视觉编程篇三《处理图像的颜色》

    前言 前期回顾: OpenCV计算机视觉编程篇二<操作像素> 上面这篇里面写了操作像素相关. 本章包括以下内容: 用策略设计模式比较颜色: 用 GrabCut 算法分割图像: 转换颜色表示 ...

  3. opencv计算机视觉编程攻略 第2版,OpenCV计算机视觉编程攻略(第2版)pdf

    摘要 1. 50多个知识点的案例解读,全面掌握基础知识与进阶内容 2. 学习OpenCV重要的图像操作类和函数 3. 初学者和从业者即查即用的工具书 4. 掌握计算机视觉与图像处理的基础知识与概念 O ...

  4. 【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析

    [-] 一开胃菜之一  关于OpenCV的命名空间 二开胃菜之二  关于Mat类型 三图像的载入和显示 imread函数 namedWindow函数 imshow函数 四输出图像到文件imwrite函 ...

  5. python计算机视觉编程——基本的图像操作和处理

    python计算机视觉编程--第一章(基本的图像操作和处理) 第1章 基本的图像操作和处理 1.1 PIL:Python图像处理类库 1.1.1 转换图像格式--save()函数 1.1.2 创建缩略 ...

  6. opencv3计算机视觉python语言实现pdf_对比《OpenCV计算机视觉编程攻略第3版》《OpenCV 3计算机视觉Python语言实现第2版》PDF代码......

    OpenCV 3是一种先进的计算机视觉库,可以用于各种图像和视频处理操作,通过OpenCV 3 能很容易地实现一些有前景且功能先进的应用(比如:人脸识别或目标跟踪等).从图像处理的基本操作出发,计算机 ...

  7. OpenCV计算机视觉编程攻略之行人检测

    OpenCV计算机视觉编程攻略之行人检测,OpenCV 提供了一个基于HOG 和SVM且经过训练的行人检测器,可以用这个SVM 分类器以不同尺度的窗口扫描图像,在完整的图像中检测特定物体. 原图如下: ...

  8. OpenCV计算机视觉编程攻略之生成椒盐噪声实现

    OpenCV计算机视觉编程攻略(第3版)P21的访问像素值,生成椒盐噪声实现. 运行结果图片,截图如下: 看书留下记录,代码如下: #include <random> #include & ...

  9. OpenCV计算机视觉编程攻略之提取图片轮廓-使用Canny函数

    OpenCV计算机视觉编程攻略之提取图片轮廓-使用Canny函数,很方便..代码如下: #include <vector> #include <iostream> #inclu ...

最新文章

  1. WordPress标签
  2. iOS - OC 术语表
  3. JavaScript类型总览(图)
  4. c++内存分配的方式
  5. shell编程系列23--shell操作数据库实战之mysql命令参数详解
  6. Android之线程池
  7. Linux软件包管理之源码包、脚本安装包
  8. GPU服务器硬件及软件
  9. c语言的常用英语单词和翻译,c语言通用英语词汇带翻译
  10. BigWorld用到的第三方库
  11. PrintWindow截取隐藏窗口
  12. java Apache poi 操作word生成word目录(根据word模板生成word文件)
  13. svn多分支开发合并技巧(idea or tortoiseSVN)
  14. matlab画概率密度图
  15. 桌面被关闭,如何在任务管理器中打开桌面?
  16. 安装算量软件快速选择计算图元
  17. QtQuick 移动端开发实战系列(7)_屏幕旋转实现(Android)
  18. 惊!Linux居然可以这样破解WiFi密码,竟然是?
  19. drtek收音机使用说明_德劲1103收音机【简易操作指南】.【使用说明书】.高清版...
  20. (ZZ)毕业五年拉开大家差距的原因

热门文章

  1. 当一个项目中同时存在webroot和webcontext时
  2. Oracle 分析及动态采样
  3. ASP.NET Excel导入到SQL Server数据库
  4. Wormholes 虫洞 BZOJ 1715 spfa判断负环
  5. UICollectionView框架总结
  6. 前端开发实习生的第一天
  7. C# 多线程并发锁模式-总结
  8. vmware上给根分区增加空间以及创建逻辑卷
  9. 希捷发布世界最薄、最快2TB硬盘:7毫米
  10. H5存储------localStorage和sessionStorage