OpenCV学习笔记二:操作像素
来源:互联网 发布:梦幻口袋版炼兽笼数据 编辑:程序博客网 时间:2024/05/29 15:29
一、存取像素值
Mat的成员函数at(int x,int y)用于存取第x行,第y例的像素值。存取像素值时必须知道图像的数据类型,因此at函数实现为模板函数,调用时需指定类型,例如对单通道图和彩色图:
//注:指定的数据类型一定要与图像的实际类型吻合//单通道image.at< uchar >(x,y) = 255;//双通道image.at<Vec3b>(x,y)[channel] = 255;
如果嫌调用函数时指定模板参数麻烦,可以使用Mat的模板子类Mat_,其重载了()操作符,可以直接存取像素值,像这样:
Mat_<uchar> image;image(x,y) = 255;
二、图像遍历
遍历图像前最好先了解Mat的一些成员的意义
- data:Mat中的一个指针,指向存放图像数据的内存
- channels():图像的通道数,比如灰度图channels = 1
- type():矩阵的数据类型,比如CV_8U,CV_8UC3等
- depth():图像的深度,可以理解为矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 type为 CV_16SC2,一个2通道的16位的有符号整数。那么,depth则是CV_16S。Mat.depth()中得到的是一个 0 – 6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可见 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;
- rows:图像矩阵的行数
- cols:图像矩阵的列数
- step:每行的字节数
- elemSize:每个像素的大小,对于short型三通道矩阵(CV_16SC3),elemSize = 6
- ptr(int x):返回第x行的首地址
1、通过指针遍历图像
对于三通道的彩色图像,内存中前三个字节对左上角像素的三个通道值,接下来的三个字节对应第一行第二个像素(OpenCV采用BGR通道顺序)。因此可以以如下方式遍历图像:
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] = 255;//处理每一个通道值 }}
2使用迭代器遍历图像
OpenCV为Mat提供了与STL迭代器兼容的迭代器。一个Mat实例的迭代器可以通过创建MatIterator_实例来得到。类似于Mat_,下划线表明其是一个模板类。
MatIterator_<Vec3b> it;MatConstIterator_<Vec3b> itc;//也可以使用定义在Mat_内部的迭代器类型Mat_<Vec3b>::iterator it;Mat_<Vec3b>::const_iterator itc;
然后,可以像这样遍历图像:
Mat_<Vec3b>::iterator it = image.begin<Vec3b>();Mat_<Vec3b>::iterator itend = image.end<Vec3b>();//遍历for(;it != itend;++it){ (*it)[channel] = 255;//处理每个channel}
*图像遍历的一些建议
- 图像原地处理更快
- 指针处理更快,但迭代器更简单
- at方法适合随机存取,不适合遍历
- 如果要对一个像素进行N种运算,那么在一次循环内完成要比分别用N个循环,每次循环只作一种运算高效得多
- 图像行与行之间往往存储是不连续的,但是有些图像可以是连续的,Mat提供了一个检测图像是否连续的函数isContinuous()。当图像连通时,我们就可以把图像完全展开,看成是一行。1中的两重循环可以简化为一层。
- 待补充
3、简单的图像运算
图像可以以不同的方式组合。因为它们只是一般的矩阵,所以它们可以做各种矩阵运算:加、减、乘、除、转置等。
以图像相加为例,当我们需要将一些图像叠加在一起时,就需要用到图像加法。通过调用add,更准确地说是addWeighted来完成。
addWeighted(image1,0.7,image2,0.9,0,result);//OpenCV重载了大多数算术操作符,因此上式也等价于//result = 0.7*image1 + 0.9*image2 + 0;
图像加法只能用于两张图像大小一致的情况,对于大小不一致的情况,则需要定义感兴趣区域(ROI)。
//定义ROI为image1的大小,这样就可以用图像加法了Mat imageROI = image(Rect(100,100,image1.cols,image1.rows);imageROI = addWeighted(imageROI,0。5,image1,0.7,0,imageROI);//imageROI = 0.5*imageROI + 0.7 * image1;
0 0
- Opencv学习笔记之二:操作像素
- OpenCV学习笔记二:操作像素
- opencv学习笔记 二 操作像素
- 我的OpenCV学习笔记(二):操作每个像素
- OpenCV学习笔记(二):存取像素
- 【OpenCV学习笔记】一.操作像素
- 【OpenCV学习笔记 005】 操作像素
- 【OpenCV学习笔记】三、操作像素
- opencv入门笔记之二 操作图像像素点
- 学习Opencv 2.4.9(二) ---操作像素
- 学习Opencv 2.4.9(二) ---操作像素
- 学习Opencv 2.4.9(二) ---操作像素
- 图像的像素点操作【OpenCV学习笔记3】
- OpenCV学习笔记(1)——操作像素
- 【opencv学习笔记.1】操作像素画圆
- openCV学习笔记(四):图像遍历和像素操作
- opencv学习(4)像素操作
- 【从零学习openCV】opecv操作像素
- 中间件
- IndexOutOfBoundsException: Inconsistency detected. Invalid item position
- libcef内核 chromium 渲染硬件加速软件渲染知识点
- 欢迎使用CSDN-markdown编辑器
- java基础
- OpenCV学习笔记二:操作像素
- 编写界面
- Linux内核分析——简单分析汇编代码
- 如何删除SQL Server 2005 Compact Edition数据库由于标题限制只能删除部分
- Hwadee实训--day10
- mysql中获取一天、一周、一月时间数据的各种sql语句写法
- [Untiy&随机数&C#]怎样加上一个随机的数,并且在一定的范围内
- 洛谷 P1791 线段覆盖
- 文章标题