Opencv中图像的遍历与像素操作

OpenCV中表示图像的数据结构是cv::Mat,Mat对象本质上是一个由数值组成的矩阵。矩阵的每一个元素代表一个像素,对于灰度图像,像素是由8位无符号数来表示(0代表黑,255代表白);对于彩色图像,每个像素是一个三元向量,即由三个8位无符号数来表示三个颜色通道(Opencv中顺次为蓝、绿、红)。 
我们先来介绍下cv::Mat类的获取像素的成员函数at(),其函数原型如下:

template<typename _Tp> _Tp& at(int i0, int i1);
//由于Mat可以存放任意数据类型的元素,所以该函数是用模板函数来实现的
//它本身不会进行任何数据类型转换,在调用的过程中需要指明像素的数据类型
//即要与矩阵中的数据类型相匹配。如:
img.at<uchar>(i,j)=255
img.at<cv::Vec3b>(i,j)[0]=255

在OpenCV中一般有四种图像遍历的方式,第一种自然是最平凡的数组遍历啦。为方便起见,以下所有的示例都是In-place变换操作。

1、数组遍历

在这里我们通过操作像素的办法来实现图像的镜像变换,即实现flip(img,img,1)的功能。代码如下:

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp> using namespace std;
using namespace cv; void Flip(Mat &img)
{
int rows=img.rows;
int cols=img.cols;
for(int i=0; i<rows; i++)
{
for(int j=0; j<cols/2; j++)
{
uchar t;
if(img.channels()==1)
{
t=img.at<uchar>(i,j);
img.at<uchar>(i,j)=img.at<uchar>(i,cols-1-i);
img.at<uchar>(i,cols-1-i)=t;
}
else if(img.channels()==3)
{
for(int k=0; k<3; k++)
{
t=img.at<Vec3b>(i,j)[k];
img.at<Vec3b>(i,j)[k]=img.at<Vec3b>(i,cols-1-j)[k];
img.at<Vec3b>(i,cols-1-j)[k]=t;
}
}
}
}
} int main()
{
Mat img1=imread("test.jpg"); //将任意一张名为test.jpg的图片放置于工程文件夹test中
imshow("First",img1);
if(!img1.data)
{
cout<<"error! The image is not built!"<<endl;
return -1;
}
Flip(img1);
imshow("Second",img1);
waitKey();
return 0;
}

效果如下: 

2、指针遍历

OpenCV中cv::Mat类提供了成员函数ptr得到图像任意行的首地址。ptr函数是一个模板函数,其原型为:

template<typename _Tp> _Tp* Mat::ptr(int i=0)

在这里我们通过操作像素的办法来实现图像的水平反转,即实现flip(img,img,0)的功能。代码如下:

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp> using namespace std;
using namespace cv; void Flip(Mat &img)
{
int rows=img.rows;
int cols=img.cols*img.channels();
for(int i=0; i<rows/2; i++)
{
uchar *p=img.ptr<uchar>(i);
uchar *q=img.ptr<uchar>(rows-1-i);
uchar t;
for(int j=0; j<cols;j++)
{
t=*p;
*p++=*q;
*q++=t;
}
}
} int main()
{
Mat img1=imread("test.jpg"); //将任意一张名为test.jpg的图片放置于工程文件夹test中
imshow("First",img1);
if(!img1.data)
{
cout<<"error! The image is not built!"<<endl;
return -1;
}
Flip(img1);
imshow("Second",img1);
waitKey();
return 0;
}

效果如下: 

指针遍历图像的过程中,我们可能会受以往遍历矩阵的影响,得到图像首行地址后,想直接通过一个循环去遍历rows*cols*img.channels()的内存,但是考虑到一些多媒体处理芯片在行的长度为是4或8的倍数时,对图像的处理会更加高效,所以OpenCV中对图像的每行会填补一些额外像素(不显示、不保存),将填补后的行的长度称为关键字,成员变量step代表以字节为单位的图像的有效宽度。因此,我们只有在图像的有效宽度等于图像的真实宽度,即没有填补时,进行一重循环遍历。我们可以通过cv::Mat的成员函数isContinuous来判断图像是否对行进行了填充,返回值为真,表示没有对行进行填充,反之填充。此外,我们可以通过cv::Mat的成员变量data得到图像的首地址,等效于上面程序中的一种写法如下:

uchar *p=img.data;    //首行首地址
*p += img.step; //次行首地址
……

3、迭代器遍历

只要对对C++稍有了解,就知道迭代器是专门用于遍历数据集合的一种非常重要的特殊的类,用其遍历隐藏了在给定集合上元素迭代的具体实现方式。C++的STL为每个容器类型都提供了迭代器,OpenCV同样为cv::Mat提供了与STL迭代器兼容的迭代器。

cv::Mat实例的迭代器可以通过创建一个cv::MatIterator_的实例来得到,由于这是一个模板类,所以在声明时需指定图像像素的数据类型。

cv::MatIterator_<cv::Ver3b> it;

另外可使用定义在Mat_内部的迭代器类型

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

在这里我们通过操作像素的办法来实现图像中心对称反转。代码如下:

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp> using namespace std;
using namespace cv; void Flip(Mat &img)
{
uchar t;
if(img.channels()==1)
{
Mat_<uchar>::iterator it=img.begin<uchar>();
Mat_<uchar>::iterator itend=img.end<uchar>();
itend--; //通过end成员函数得到的迭代器已超出集合,所以在这里自减
for(;it<itend;it++,itend--)
{
t=*it;*it=*itend;*itend=t;
}
}
else if(img.channels()==3)
{
Mat_<Vec3b>::iterator it=img.begin<Vec3b>();
Mat_<Vec3b>::iterator itend=img.end<Vec3b>();
itend--;
for(;it<itend;it++,itend--)
for(int k=0; k<3; k++)
{
t=(*it)[k];(*it)[k]=(*itend)[k];(*itend)[k]=t;
}
}
} int main()
{
Mat img1=imread("test.jpg"); //将任意一张名为test.jpg的图片放置于工程文件夹test中
imshow("First",img1);
if(!img1.data)
{
cout<<"error! The image is not built!"<<endl;
return -1;
}
Flip(img1);
imshow("Second",img1);
waitKey();
return 0;
}

效果如下: 

Opencv中图像的遍历与像素操作的更多相关文章

  1. OpenCV中图像算术操作与逻辑操作

    OpenCV中图像算术操作与逻辑操作 在图像处理中有两类最重要的基础操作各自是图像点操作与块操作.简单点说图像点操作就是图像每一个像素点的相关逻辑与几何运算.块操作最常见就是基于卷积算子的各种操作.实 ...

  2. OpenCV中图像的格式Mat 图像深度

    opencv中图像的格式Mat 有图像的定义,图像深度.类型格式等,其中Mat的参数depth为深度,深度反应出图像颜色像素值: 关于数据的储存:(转) Mat_<uchar>对应的是CV ...

  3. OpenCV中图像的BGR格式及Img对象的属性说明

    1. 图像的BGR格式说明 OpenCV中图像读入的数据格式是numpy的ndarray数据格式.是BGR格式,取值范围是[0,255]. 如下图所示,分为三个维度: 第一维度:Height 高度,对 ...

  4. opencv——图像遍历以及像素操作

    摘要 我们在图像处理时经常会用到遍历图像像素点的方式,在OpenCV中一般有四种图像遍历的方式,在这里我们通过像素变换的点操作来实现对图像亮度和对比度的调整. 补充: 图像变换可以看成 像素变换--点 ...

  5. [OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V (一)

    部分 V图像特征提取与描述 OpenCV-Python 中文教程(搬运)目录 29 理解图像特征 目标本节我会试着帮你理解什么是图像特征,为什么图像特征很重要,为什么角点很重要等.29.1 解释 我相 ...

  6. [OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V (二)

    部分 V图像特征提取与描述 OpenCV-Python 中文教程(搬运)目录 34 角点检测的 FAST 算法 目标 • 理解 FAST 算法的基础 • 使用 OpenCV 中的 FAST 算法相关函 ...

  7. 深入学习OpenCV中图像灰度化原理,图像相似度的算法

    最近一段时间学习并做的都是对图像进行处理,其实自己也是新手,各种尝试,所以我这个门外汉想总结一下自己学习的东西,图像处理的流程.但是动起笔来想总结,一下却不知道自己要写什么,那就把自己做过的相似图片搜 ...

  8. HTML5 canvas图像绘制方法与像素操作属性和方法

    图像绘制方法 drawImage()        向画布上绘制图像.画布或视频 像素操作属性和方法 width                                返回 ImageData ...

  9. opencv中图像伪彩色处理(C++ / Python)

    使用OpenCV的预定义的颜色映射来将灰度图像伪彩色化. 1. colormap(色度图)是什么? 假设我们想在地图上显示美国不同地区的温度.我们可以把美国地图上的温度数据叠加为灰度图像——较暗的区域 ...

随机推荐

  1. python 特性:height-->while

    """ 出题:height 女生找对象 男生在1米-1.5米之间 小强你在哪里? 男生在1.5-1.7米之间 没有安全感 男生在1.7 - 1.8米之间 帅哥 留个电话 ...

  2. java里面的标识符、关键字和类型

    1. 注释  Java中有三种注释:   (1) // -单行注释,注释从“//”开始,终止于行尾:   (2)  -多行注释,注释从““结束:   (3)  -是Java特有的doc注释,这种注释主 ...

  3. [译文]casperjs使用说明-使用命令行

    使用命令行 Casperjs使用内置的phantomjs命令行解析器,在cli模块里,它传递参数位置的命名选项 但是不要担心不能熟练操控CLI模块的API,一个casper实例已经包含了cli属性,允 ...

  4. CF765F Souvenirs 离线+线段树+主席树

    $ \color{#0066ff}{ 题目描述 }$ A县旁,连绵着一条长度为 n 的山脉,这条山脉由 n 座山峰组成,第 i 座山 峰的高度为 ai.作为著名的旅游县城,每天来到山脉游玩的旅客络绎不 ...

  5. poi操作Excel并修改单元格背景色

    废话不多说,直接来代码!!! 其中标红的才是重点!!! 代码中有时可以不用创建新文件, 如果报错的话可以通过创建新文件来进行操作(懒,没去找报错原因),不过原文件也会被修改. 操作之前做好备份!操作之 ...

  6. POJ_3268 Silver Cow Party 【最短路】

    一.题面 POJ3268 二.分析 该题的意思就是给定了一个由每个节点代表农场的有向图,选定一个农场X办party,其余农场的都要去,每个农场的cow都走最短路,走的时间最久的cow耗时多少. 了解题 ...

  7. 知了课堂 Python Flask零基础 笔记整理

    目录 起步 安装Python2.7: Python虚拟环境介绍与安装: pip安装flask: 认识url: URL详解 web服务器和应用服务器以及web应用框架: Flask 第一个flask程序 ...

  8. 使用maven搭建ssm框架的javaweb项目

    目前主流的javaweb项目,常会用到ssm(Spring+Spring MVC+Mybatis)框架来搭建项目的主体框架,本篇介绍搭建SSM框架的maven项目的实施流程.记之共享! 一.SSM框架 ...

  9. Qt4.8.5移植

    这两天搞了Qt移植 因为不小心 耽误了挺多时间 但是也比较好的掌握了   现在记录一下 准备工具: tslib-1.16 qt-everywhere-opensource-src-4.8.5.tar ...

  10. Oracle PL/SQL编程之基础

    1.简介:pl/sql块由三个部分组成:定义部分.执行部分.例外处理部分,如下所示: declare: /*定义部分---定义常量.变量.游标.例外.复杂数据类型 begin /*执行部分---要执行 ...