一.行/列访问

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

最新文章

  1. JSON 格式说明
  2. [Jquery]网页定位导航特效
  3. JavaScript的语法要点 3 - Calling Context
  4. dom树的介绍,及原理分析
  5. 开发安全的Web程序
  6. android之frame动画详解
  7. Django教程:第一个Django应用程序(4)
  8. Spring相框:AOP详细说明
  9. node.js爬虫爬取拉勾网职位信息
  10. Oracle数据库ora-01722 错误小记
  11. [转]Java - 集合框架完全解析
  12. [洛谷P2234][HNOI2002] 营业额统计 - Treap
  13. 使用Genymotion遇到的坑_Genymotion无法启动_unable to start the virtual device
  14. Day035--Python--管道, Manager, 进程池, 线程切换
  15. PySpider 爬虫系统
  16. CGroup 介绍、应用实例及原理描述【转】
  17. 错误类型“Microsoft.Office.Interop.Word.ApplicationClass”未定义构造函数
  18. 李宏毅机器学习笔记1:Regression、Error
  19. github入门教程:第一步
  20. bzoj1650 / P2855 [USACO06DEC]河跳房子River Hopscotch / P2678 (noip2015)跳石头

热门文章

  1. 怎么在notepad里面,将字符串替换成换行
  2. git&#160;基本命令详细解释
  3. Java简单高精度合集
  4. (水题)洛谷 - P1618 - 三连击(升级版)
  5. bzoj 2648: SJY摆棋子【KD-tree】
  6. bzoj4145 [AMPPZ2014]The Prices(状压dp)
  7. 不常见偏门的Bug,Spring Boot IDEA 静态资源 图片访问404,初学者之殇
  8. maven在window下的环境变量配置
  9. 第二类Stirling数初探 By cellur925
  10. pycharm 激活码激活