一.行/列访问

1.单行/单列访问

Mat Mat::row(int i) const

Mat Mat::col(int j) const

2.多行/多列访问

Range(start,end);

Range::all();  // 表示所有行或列

Mat A;
Mat B=A(Range::(5,9),Range(1,3)); //表示5-9行(不包括9),1-3列(不包括3)

二.区域访问

1.CRect

//在图像的右下角定义一个ROI
cv::Mat imageROI(image,cv::Rect(image.cols-logo.cols,
image.rows-logo.rows,
logo.cols,
logo.rows)); 或者
cv::Mat imageROI=image(cv::Rect(image.cols-logo.cols,
image.rows-logo.rows,
logo.cols,
logo.rows));

2.CSize

三.像素访问

1.at()访问

使用at()函数代码可读性高,效率不是很高,使用at()函数必须用两个循环实现

注意访问顺序,先访问行(外循环rows)(指针在高的第一行)

再访问列(内循环cols)(指针移动宽的每一行)

template <typename _Tp> inline _Tp& Mat::at(int i0, int i1)

template <typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const

template <typename _Tp> inline _Tp& Mat::at(Point pt)

template <typename _Tp> inline const _Tp& Mat::at(Point pt) const

template <typename _Tp> inline _Tp& Mat::at(int i0)

template <typename _Tp> inline const _Tp& Mat::at(int i0) const

template <typename _Tp> inline _Tp& Mat::at(int i0, int i1, int i2)

template <typename _Tp> inline const _Tp& Mat::at(int i0, int i1, int i2) const

template <typename _Tp> inline _Tp& Mat::at(const int* idx)

template <typename _Tp> inline const _Tp& Mat::at(const int* idx) const

template <typename _Tp, int n> _Tp& Mat::at(const Vec<int, n>& idx)

template <typename _Tp, int n> inline const _Tp& Mat::at(const Vec<int, n>& idx) const

at()函数是模板函数,可以自定义类型

其中at<uchar>表示单通道图像,at<cv::Vec3b>表示三通道图像

//遍历像素值

#include <iostream>
#include "opencv2/opencv.hpp" using namespace std; int main(int argc, char* argv[]) { cv::Mat grayim(600, 800, CV_8UC1);
cv::Mat colorim(600, 800, CV_8UC3); //遍历所有像素,并设置像素值
for(int i = 0;i < grayim.rows; ++i)
for(int j = 0; j < grayim.cols; ++j)
grayim.at<uchar>(i,j) = (i+j)%255; //遍历所有像素,并设置像素值
for(int i=0; i<colorim.rows; ++i)
for(int j=0; j<colorim.cols; ++j)
{ cv::Vec3b pixel;
pixel[0] = i%255; //Blue
pixel[1] = j%255; //Green
pixel[2] = 0; //Red
colorim.at<cv::Vec3b>(i,j) = pixel;
} cv::imshow("grayim",grayim);
cv::imshow("colorim",colorim); cv::waitKey(0); return 0; }

2.ptr()访问

注意at()函数返回的是一个uchar变量类型,而ptr()函数返回的是一个uchar*指针类型

ptr()函数和at()函数都需要两个循环来遍历像素.虽然它返回的是指针,索引速度比较快,但是指针不进行类型以及越界检查

它的访问顺序是跟at()函数有点像,先获取首个行指针,再遍历列指针

inline uchar* Mat::ptr(int y)

inline const uchar* Mat::ptr(int y) const

template<typename _Tp> inline _Tp* Mat::ptr(int y)

template<typename _Tp> inline const _Tp* Mat::ptr(int y) const

inline uchar* Mat::ptr(int i0, int i1)

intline const uchar* Mat::ptr(int i0, int i1) const

template<typename _Tp> inline _Tp* Mat::ptr(int i0, int i1)

template<typename _Tp> inline const _Tp* Mat::ptr(int i0, int i1) const

inline uchar* Mat::ptr(int i0, int i1, int i2)

inline const uchar* Mat::ptr(int i0, int i1, int i2) const

template<typename _Tp> inline _Tp* Mat::ptr(int i0, int i1, int i2)

template<typenmae _Tp> inline const _Tp* Mat::ptr(int i0, int i1, int i2) const

inline uchar* Mat::ptr(const int* idx)

inline const uchar* Mat::ptr(const int* idx) const

#include <iostream>
#include "opencv2/opencv.hpp" using namespace std; int main(int argc, char* argv[]) { cv::Mat grayim(600,800,CV_8UC1);
cv::Mat colorim(600,800,CV_8UC3); //遍历所有像素,并设置像素值
for( int i = 0; i < grayim.rows; ++i) { //获取第i行首像素指针
uchar* p = grayim.ptr<uchar>(i); //对第i的每个像素操作
for(int j = 0;j < grayim.cols; ++j)
p[j] = (i+j)%255;
} //遍历所有像素,并设置像素值
for( int i = 0; i<colorim.rows; ++i) { //获取第i行首像素指针
cv::Vec3b* p=colorim.ptr<cv::Vec3b>(i);
for( int j = 0; j < colorim.cols; ++j) {
p[j][0] = i%255; //Blue
p[j][1] = j%255; //Green
p[j][2] = 0; //Red
}
} imshow("grayim", grayim);
imshow("colorim", colorim);
cv::waitKey(0); return 0;
}

3.迭代器访问

迭代器访问有点像at()函数访问,虽然它只需要一个循环,但是它的可读性没有at()函数清楚

MatIterator_是一个类模板,而at()函数是函数模板

MatIterator_类似于STL中的迭代器,根据迭代器开头和结尾一直遍历

template<typename _Tp>

class MatIterator_ : public MatConstIterator_<_Tp>

{

public:

  typedef _Tp* pointer;

  typedef _Tp& reference;

  typedef std::random_access_iterator_tag iterator_category;

  

  MatIterator_();

  MatIterator_(Mat_<_Tp>* _m);

  MatIterator_(Mat_<_Tp>* _m, int _row, int _col = 0);

  MatIterator_(const Mat_<_Tp>* _m, Point _pt);

  MatIterator_(const Mat_<_Tp>* _m, const int* _idx);

  MatIterator_(const MatIterator_& it);

  MatIterator_& operator = (const MatIterator_<_Tp>& it);

  _Tp& operator *() const;

  _Tp& operator [](ptrdiff_t i) const;

  MatIterator_& operator += (ptrdiff_t ofs);

  MatIterator_& operator -= (ptrdiff_t ofs);

  MatIterator_& operator -- ();

  MatIterator_  operator --  (int);

  MatIterator_& operator ++ ();

  MatIterator_  operator ++ (int);

};

#include <iostream>
#include "opencv2/opencv.hpp" using namespace std; int main(int argc, char* argv[]) { cv::Mat grayim(600, 800, CV_8UC1);
cv::Mat colorim(600, 800, CV_8UC3); //遍历所有像素,并设置像素值
cv::MatIterator_<uchar> grayit, grayend; for( grayit = grayim.begin<uchar>(), grayend = grayim.end<uchar>(); grayit != grayend; ++grayit)
*grayit = rand()%255; //遍历所有像素,并设置像素值
cv::MatIterator_<cv::Vec3b> colorit,colorend; for( colorit = colorim.begin<cv::Vec3b>(), colorend = colorim.end<cv::Vec3b>(); colorit != colorend; ++colorit) { (*colorit)[0] = rand()%255; //Blue
(*colorit)[1] = rand()%255; //Green
(*colorit)[2] = rand()%255; //Red
} //显示结果
cv::imshow("grayim", grayim);
cv::imshow("colorim", colorim); cv::waitKey(0); return 0; }

4.模板访问

//用Mat_模板操作图像
cv::Mat_<uchar> im2(image);
im2(50,100)=0; // 访问第50行,第100列处那个值

5.查找表访问

LUT(Look Up Table,查找表)是一张像素灰度值的映射表,它将采样到的灰度值经过图像处理(替换 反转  赋值 阈值 二值化 灰度变化等),利用映射关系变换成相应的灰度值

OpenCV中LUT查找表包含256个元素,应用于单通道或相同类型的多通道数据,用于减少图像映射的时间复杂度

cv::Mat inverseColor6(cv::Mat srcImage)
{ int row = srcImage.rows;
int col = srcImage.cols;
cv::Mat tempImage = srcImage.clone(); // 建立LUT 反色table
uchar LutTable[256];
for (int i = 0; i < 256; ++i)
LutTable[i] = 256 - i; cv::Mat lookUpTable(1, 256, CV_8U);
uchar* pData = lookUpTable.data; // 建立映射表
for (int i = 0; i <256; ++i)
pData[i] = LutTable[i]; // 应用搜索表进行查找
cv::LUT(srcImage, lookUpTable, tempImage); return tempImage;
}

四.例子

1.减色

(1)指针
//test.cpp

void colorReduce(cv::Mat image,int div=64){

	int nl=image.rows;  //行数

	//每行的元素数量
int nc=image.cols*image.channels(); for(int j=0;j<nl;j++){ //取得行j的地址
uchar* data=image.ptr<uchar>(j); for(int i=0;i<nc;i++){ //处理每个像素
data[i]=data[i]/div*div+div/2; } } }
(2)迭代器
void colorReduce(cv::Mat image,int div=64){

	//在初始位置获得迭代器
cv::Mat_<cv::Vec3b>::iterator it=image.begin<cv::Vec3b>(); //获得结束位置
cv::Mat_<cv::Vec3b>::iterator itend=image.end<cv::Vec3b>(); //循环遍历所有像素
for(;it!=itend;++it){ //处理每个像素
(*it)[0]=(*it)[0]/div*div+div/2;
(*it)[1]=(*it)[1]/div*div+div/2;
(*it)[2]=(*it)[2]/div*div+div/2; } }

2.锐化

void sharpen(const cv::Mat& image,cv::Mat& result){

	//判断是否需要分配图像数据,如果需要,就分配
result.create(image.size(),image.type());
int nchannels=image.channels(); //获得通道数 //处理所有行(除了第一行和最后一行)
for(int j=1;j<image.rows-1;j++){ const uchar* previous=image.ptr<const uchar>(j-1); //上一行
const uchar* current=image.ptr<const uchar>(j); //当前行
const uchar* next=image.ptr<const uchar>(j+1); //下一行 uchar* output=result.ptr<uchar>(j); //输出行 for(int i=nchannels;i<(image.cols-1)*nchannels;i++){ *output++=cv::saturate_cast<uchar>(
5*current[i]-current[i-nchannels]-current[i+nchannels-previous[i]-next[i]]); }
} //把未处理的像素设为0
result.row(0).setTo(cv::Scalar(0));
result.row(result.rows-1).setTo(cv::Scalar(0));
result.col(0).setTo(cv::Scalar(0));
result.col(result.cols-1).setTo(cv::Scalar(0)); } int main()
{ cv::Mat imag1=cv::imread("a.jpg");
cv::Mat result; sharpen(imag1,result); cv::namedWindow("Image");
cv::imshow("Image",result); cv::waitKey(0); system("pause");
return 0;
}

OpenCV2:第五章 访问图像的更多相关文章

  1. OpenCV2:第三章 读取图像

    一.简介 将图像文件读入内存,可以用cv::imread()函数 二.读取图像 Mat imread(const string& filename,int flags=1); Mat: 如果读 ...

  2. OpenCV2:第四章 导出图像

    一.简介 一般我们用OpenCV来处理图像数据的时候,OpenCV已经把图像数据包装成一个图像数据类,我们只需要对类成员的像素值进行修改就行了. 但是在Windows开发的WinSDK/MFC中,对图 ...

  3. [HeadFrist-HTMLCSS学习笔记]第五章认识媒体:给网页添加图像

    [HeadFrist-HTMLCSS学习笔记]第五章认识媒体:给网页添加图像 干货 JPEG.PNG.GIF有何不同 JPEG适合连续色调图像,如照片:不支持透明度:不支持动画:有损格式 PNG适合单 ...

  4. opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)

    #include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgu ...

  5. (转)iOS Wow体验 - 第五章 - 利用iOS技术特性打造最佳体验

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第五章译文精选,其余章节将陆续放出.上一篇:Wow ...

  6. Gradle 1.12用户指南翻译——第四十五章. 应用程序插件

    本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  7. opencv 3 core组件进阶(1 访问图像中的像素)

    访问图像像素的三类方法 ·方法一 指针访问:C操作符[ ]; ·方法二 迭代器iterator; ·方法三 动态地址计算. #include <opencv2/core/core.hpp> ...

  8. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (22) -----第五章 加载实体和导航属性之延迟加载

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第五章 加载实体和导航属性 实体框架提供了非常棒的建模环境,它允许开发人员可视化地使 ...

随机推荐

  1. 使用AES128加密字符串

    import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.apache.c ...

  2. View Controller Programming Guide for iOS---(三)---Using View Controllers in Your App

    Using View Controllers in Your App Whether you are working with view controllers provided by iOS, or ...

  3. UVa 1643 Angle and Squares (计算几何)

    题意:有n个正方形和一个角(均在第一象限中),使这些正方形与这个角构成封闭的阴影区域,求阴影区域面积的最大值. 析:很容易知道只有所有的正方形的对角形在一条直线时,是最大的,然后根据数学关系,就容易得 ...

  4. Codeforces686C【dfs】

    题意: n,m<=1e9 设定一天n小时,一小时m分钟, 显示时间的是一个7进制的表, 问你在一天里出现多少个时刻,表中的数字要都不相同. 思路: 因为7进制,显示的数字肯定是0-7之间的. 然 ...

  5. 基础BFS+DFS poj3083

    //满基础的一道题 //最短路径肯定是BFS. //然后靠右,靠左,就DFS啦 //根据前一个状态推出下一个状态,举靠左的例子,如果一开始是上的话,那么他的接下来依次就是 左,上 , 右 , 下 // ...

  6. bzoj 5294: [Bjoi2018]二进制【动态dp+线段树】

    不太清楚是不是动态dp--? 这个维护其实和最大连续子段差不多,维护l[x][y],r[x][y],m[x][y]分别表示包含左儿子的01个数为(x,y)的区间个数,包含右儿子的01个数为(x,y)的 ...

  7. touch的基本用法

    touch的基本功能是改变文件的时间戳,以下是三种常用用法: 1.创建一个空文件 以当前时间为时间戳创建一个空文件.$ touch touch.txt //touch.txt不存在 2.更改文件时间戳 ...

  8. camshift.py OpenCv例程阅读

    源码在这 #!/usr/bin/env python ''' Camshift tracker ================ This is a demo that shows mean-shif ...

  9. 易爆物(X-Plosives )基础并查集

    #include <iostream> #include <algorithm> using namespace std; + ; int fa[maxn]; int Find ...

  10. 跟我一起玩Win32开发(8):绘图(A)

    从本篇开始,我就不吹牛皮,那就吹吹兔皮吧.说说与绘图有关的东东. 要进行绘制,首先要得到一个DC,啥是DC呢?按字面翻译叫设备上下文,也可以翻译为设备描述表,它主要指API为我们封装了一些与显示设备相 ...