OPENCVMat类存取方法元素访问汇总.docx
- 文档编号:6459054
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:11
- 大小:399.08KB
OPENCVMat类存取方法元素访问汇总.docx
《OPENCVMat类存取方法元素访问汇总.docx》由会员分享,可在线阅读,更多相关《OPENCVMat类存取方法元素访问汇总.docx(11页珍藏版)》请在冰豆网上搜索。
OPENCVMat类存取方法元素访问汇总
Opencv
----Mat类
∙cv:
:
Mat
∙depth/dims/channels/step/data/elemSize
Mat矩阵中数据元素的地址计算公式:
addr(Mi0,i1,…im-1)=M.data+M.step[0]*i0+M.step[1]*i1+…+M.step[m-1]*im-1。
其中m=M.dims是指M的维度
i.data:
Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存(uchar*data).
ii.row:
行;col:
列;rows:
行数;cols:
列数。
iii.dims:
Mat所代表的矩阵的维度,如3*4的矩阵为2维,3*4*5的为3维.
iv.channels:
通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说3*4矩阵中一共12个元素,如果每个元素有三个值,那么就说这个矩阵是3通道的,即channels=3。
常见的是一张彩色图片有红、绿、蓝三个通道。
但是opencv用imread(opencv读图的函数)读进来的图像,三通道存放顺序为B、G、R。
v.depth:
深度,即每一个像素的位数(bits),在opencv的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位;
vi.step:
是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意step1(step/elemSize1),M.step[m-1]总是等于elemSize,M.step1(i)返回的是第i维的步长,因此M.step1(m-1)总是等于channels,m是M的维度;这里是解释步长step[k]的,步长也可以看作是与第k维的存储单位,在2维的矩阵中,因为存储是按照行的顺序存储的,整个矩阵存储为一个平面,所以第k=0维的步长也就是单位肯定就是一行所占的字节数;如果是3维的话,第0维是按照面为单位来存储的,第1维是按照行为单位来存储的,第2维是按照元素类型为单位存储的,每个元素类型是基本类型(即uchar,float,short等等)与通道数的乘积...;也就是基本数据类型与通道数组成元素,多个元素组成了行,多行组成了面,多个面组成了3维体,多个3维体组成4维超体。
。
。
以此类推,如此看来某一维的步长应该等于高一维的步长step*低一维的大小size。
vii.elemSize:
矩阵中每一个元素的数据大小,如果是n通道,就是(n*数据类型)。
如果Mat中的数据的数据类型是CV_8U那么elemSize=1,CV_8UC3那么elemSize=3,CV_16UC2那么elemSize=4;记住另外有个elemSize1表示的是矩阵中数据类型的大小,即elemSize/channels的大小。
图片分析1:
考虑二维情况(storedrowbyrow)按行存储
上面是一个3X4的矩阵,假设其数据类型为CV_8U,也就是单通道的uchar类型
∙这是一个二维矩阵,那么维度为2(M.dims==2);
∙M.rows==3;M.cols==4;
∙sizeof(uchar)=1,那么每一个数据元素大小为1(M.elemSize()==1,M.elemSize1()==1);
∙CV_8U得到M.depth()==0,M.channels()==1;
∙因为是二维矩阵,那么step数组只有两个值,step[0]和step[1]分别代表一行的数据大小和一个元素的数据大小,则M.step[0]==4,M.step[1]==1;
∙M.step1(0)==M.cols=4;M.step1
(1)==1;
假设上面的矩阵数据类型是CV_8UC3,也就是三通道
∙M.dims==2;M.channels()==3;M.depth()==0;
∙M.elemSize()==3(每一个元素包含3个uchar值)M.elemSize1()==1(elemSize/channels)
∙M.step[0]==M.cols*M.elemSize()==12,M.step[1]==M.channels()*M.elemSize1()==M.elemSize()==3;
∙M.step(0)==M.cols*M.channels()==12;M.step
(1)==M.channels()==3;
图片分析2:
考虑三维情况(storedplanebyplane)按面存储
上面是一个3X4X6的矩阵,假设其数据类型为CV_16SC4,也就是short类型
∙M.dims==3;M.channels()==4;M.elemSize1()==sizeof(short)==2;
∙M.rows==M.cols==–1;
∙M.elemSize()==M.elemSize1()*M.channels()==M.step[M.dims-1]==M.step[2]==2*4==8;
∙M.step[0]==4*6*M.elemSize()==192;
∙M.step[1]==6*M.elemSize()==48;
∙M.step[2]==M.elemSize()==8;
∙M.step1(0)==M.step[0]/M.elemSize()==48/2==96(第一维度(即面的元素个数)*通道数);
∙M.step1
(1)==M.step[1]/M.elemSize()==12/2==24(第二维度(即行的元素个数/列宽)*通道数);
∙M.step1
(2)==M.step[2]/M.elemSize()==M.channels()==4(第三维度(即元素)*通道数);
End
以上为Mat的存放形式
以下为Mat的一些操作方法
具体使用方法
Fn1:
利用step。
Code1:
intmain()
{
//新建一个uchar类型的单通道矩阵(grayscaleimage灰度图)
Matm(400,400,CV_8U,Scalar(0));
for(intcol=0;col<400;col++)
{
for(introw=195;row<205;row++)
{
//获取第[row,col]个像素点的地址并用*符号解析
*(m.data+m.step[0]*row+m.step[1]*col)=255;
}
}
imshow("canvas",m);
cvWaitKey();
return0;
}
Output1:
Code1只是演示了单通道的情况,对于多通道的例子,请看Code2然后再看Code3。
Fn2:
使用Mat:
:
at函数
∙原型template
:
at(…)//其中参数有多个,也就是说at函数有多个重载
∙返回值为Mat类型,Mat有个索引的重载,也就是[]符号的重载,用这个重载可以定位多通道数据,具体示例可以看下面代码。
下面的代码把红色通道值大于128的颜色的置为白色,左边为原图,右边为处理过后的图。
Code2:
intmain()
{
Matimg=imread("lena.jpg");
imshow("LenaOriginal",img);
for(introw=0;row { for(intcol=0;col { /*注意Mat: : at函数是个模板函数,需要指明参数类型,因为这张图是具有红蓝绿三通道的图, 所以它的参数类型可以传递一个Vec3b,这是一个存放3个uchar数据的Vec(向量).这里 提供了索引重载,[2]表示的是返回第三个通道,在这里是Red通道,第一个通道(Blue)用[0]返回*/ if(img.at img.at } } imshow("LenaModified",img); cvWaitKey(); return0; } Output2: Code3: 这段代码用的是Fn1的方式,效果和Code2等价,不过是处理三通道数据而已: intmain() { Matimg=imread("lena.jpg"); imshow("LenaOriginal",img); for(introw=0;row { for(intcol=0;col { //主要是这里的代码 if(*(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1()*2)>128) { //[row,col]像素的第1通道地址被*解析(blue通道) *(img.data+img.step[0]*row+img.step[1]*col)=255; //[row,col]像素的第2通道地址被*解析(green通道),关于elemSize1函数的更多描述请见Fn1里所列的博文链接 *(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1())=255; //[row,col]像素的第3通道地址被*解析(red通道) *(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1()*2)=255; } } } imshow("LenaModified",img); cvWaitKey(); return0; } Output3=Output2 Fn3: 使用Mat的一个模板子类Mat_ Code4: intmain() { Matm(400,400,CV_8UC3,Scalar(255,255,255)); //m2是Mat_ //注意Mat_ //#defineCV_8UC3CV_MAKETYPE(CV_8U,3) Mat_ //for循环画一个红色的实心圆 for(inty=0;y { for(intx=0;x { if(pow(double(x-200),2)+pow(double(y-200),2)-10000.0<0.00000000001) { //Mat_模板类实现了对()的重载,可以定位到一个像素 m2(x,y)=Vec3b(0,0,255); } } } imshow("Image",m); cvWaitKey(); return0; } Output4: [看上去怎么有点不爽 ] Fn4: 使用Mat: : ptr模板函数 Code5: intmain() { Matm(400,400,CV_8UC3,Scalar(226,46,166)); imshow("Before",m); for(introw=0;row { if(row%5==0) { //data是uchar*类型的,m.ptr //需要注意的是该行数据是按顺序存放的,也就是对于一个3通道的Mat,一个像素有 //有3个通道值,[B,G,R][B,G,R][B,G,R]...所以一行长度为: //sizeof(uchar)*m.cols*m.channels()个字节 uchar*data=m.ptr for(intcol=0;col { data[col*3]=102;//第row行的第col个像素点的第一个通道值Blue data[col*3+1]=217;//Green data[col*3+2]=239;//Red } } } imshow("After",m); cout<<(int)m.at cout<<(int)m.at cout<<(int)m.at cvWaitKey(); return0; } Output5: End: Author: Ggicci 谢谢阅读,有误希望指正! --OpenCV初学者
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OPENCVMat 存取 方法 元素 访问 汇总