OpenCV2:第五章 访问图像
一.行/列访问
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:第五章 访问图像的更多相关文章
- OpenCV2:第三章 读取图像
一.简介 将图像文件读入内存,可以用cv::imread()函数 二.读取图像 Mat imread(const string& filename,int flags=1); Mat: 如果读 ...
- OpenCV2:第四章 导出图像
一.简介 一般我们用OpenCV来处理图像数据的时候,OpenCV已经把图像数据包装成一个图像数据类,我们只需要对类成员的像素值进行修改就行了. 但是在Windows开发的WinSDK/MFC中,对图 ...
- [HeadFrist-HTMLCSS学习笔记]第五章认识媒体:给网页添加图像
[HeadFrist-HTMLCSS学习笔记]第五章认识媒体:给网页添加图像 干货 JPEG.PNG.GIF有何不同 JPEG适合连续色调图像,如照片:不支持透明度:不支持动画:有损格式 PNG适合单 ...
- opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)
#include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgu ...
- (转)iOS Wow体验 - 第五章 - 利用iOS技术特性打造最佳体验
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第五章译文精选,其余章节将陆续放出.上一篇:Wow ...
- Gradle 1.12用户指南翻译——第四十五章. 应用程序插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- opencv 3 core组件进阶(1 访问图像中的像素)
访问图像像素的三类方法 ·方法一 指针访问:C操作符[ ]; ·方法二 迭代器iterator; ·方法三 动态地址计算. #include <opencv2/core/core.hpp> ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (22) -----第五章 加载实体和导航属性之延迟加载
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第五章 加载实体和导航属性 实体框架提供了非常棒的建模环境,它允许开发人员可视化地使 ...
随机推荐
- 使用AES128加密字符串
import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.apache.c ...
- 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 ...
- UVa 1643 Angle and Squares (计算几何)
题意:有n个正方形和一个角(均在第一象限中),使这些正方形与这个角构成封闭的阴影区域,求阴影区域面积的最大值. 析:很容易知道只有所有的正方形的对角形在一条直线时,是最大的,然后根据数学关系,就容易得 ...
- Codeforces686C【dfs】
题意: n,m<=1e9 设定一天n小时,一小时m分钟, 显示时间的是一个7进制的表, 问你在一天里出现多少个时刻,表中的数字要都不相同. 思路: 因为7进制,显示的数字肯定是0-7之间的. 然 ...
- 基础BFS+DFS poj3083
//满基础的一道题 //最短路径肯定是BFS. //然后靠右,靠左,就DFS啦 //根据前一个状态推出下一个状态,举靠左的例子,如果一开始是上的话,那么他的接下来依次就是 左,上 , 右 , 下 // ...
- bzoj 5294: [Bjoi2018]二进制【动态dp+线段树】
不太清楚是不是动态dp--? 这个维护其实和最大连续子段差不多,维护l[x][y],r[x][y],m[x][y]分别表示包含左儿子的01个数为(x,y)的区间个数,包含右儿子的01个数为(x,y)的 ...
- touch的基本用法
touch的基本功能是改变文件的时间戳,以下是三种常用用法: 1.创建一个空文件 以当前时间为时间戳创建一个空文件.$ touch touch.txt //touch.txt不存在 2.更改文件时间戳 ...
- camshift.py OpenCv例程阅读
源码在这 #!/usr/bin/env python ''' Camshift tracker ================ This is a demo that shows mean-shif ...
- 易爆物(X-Plosives )基础并查集
#include <iostream> #include <algorithm> using namespace std; + ; int fa[maxn]; int Find ...
- 跟我一起玩Win32开发(8):绘图(A)
从本篇开始,我就不吹牛皮,那就吹吹兔皮吧.说说与绘图有关的东东. 要进行绘制,首先要得到一个DC,啥是DC呢?按字面翻译叫设备上下文,也可以翻译为设备描述表,它主要指API为我们封装了一些与显示设备相 ...