OPENCVMat类存取方法元素访问汇总Word格式.docx
- 文档编号:19472834
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:11
- 大小:399.08KB
OPENCVMat类存取方法元素访问汇总Word格式.docx
《OPENCVMat类存取方法元素访问汇总Word格式.docx》由会员分享,可在线阅读,更多相关《OPENCVMat类存取方法元素访问汇总Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
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<
typename_Tp>
inline_Tp&
Mat:
at(…)//其中参数有多个,也就是说at函数有多个重载
∙返回值为Mat类型,Mat有个索引的重载,也就是[]符号的重载,用这个重载可以定位多通道数据,具体示例可以看下面代码。
下面的代码把红色通道值大于128的颜色的置为白色,左边为原图,右边为处理过后的图。
Code2:
{
Matimg=imread("
lena.jpg"
);
LenaOriginal"
img);
for(introw=0;
img.rows;
img.cols;
{
/*注意Mat:
at函数是个模板函数,需要指明参数类型,因为这张图是具有红蓝绿三通道的图,
所以它的参数类型可以传递一个Vec3b,这是一个存放3个uchar数据的Vec(向量).这里
提供了索引重载,[2]表示的是返回第三个通道,在这里是Red通道,第一个通道(Blue)用[0]返回*/
if(img.at<
Vec3b>
(row,col)[2]>
128)
img.at<
(row,col)=Vec3b(255,255,255);
LenaModified"
Output2:
Code3:
这段代码用的是Fn1的方式,效果和Code2等价,不过是处理三通道数据而已:
//主要是这里的代码
if(*(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1()*2)>
//[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;
Output3=Output2
Fn3:
使用Mat的一个模板子类Mat_<
的()符号重载定位一个像素
Code4:
Matm(400,400,CV_8UC3,Scalar(255,255,255));
//m2是Mat_<
类型的,因为m中元素的类型是CV_8UC3,可以用Vec3b存储3个通道的值
//注意Mat_<
CV_8UC3>
这种写法是错误的,因为CV_8UC3只是一个宏定义
//#defineCV_8UC3CV_MAKETYPE(CV_8U,3)
Mat_<
m2=m;
//for循环画一个红色的实心圆
for(inty=0;
y<
m.rows;
y++)
for(intx=0;
x<
x++)
if(pow(double(x-200),2)+pow(double(y-200),2)-10000.0<
0.00000000001)
//Mat_模板类实现了对()的重载,可以定位到一个像素
m2(x,y)=Vec3b(0,0,255);
Image"
Output4:
[看上去怎么有点不爽
]
Fn4:
ptr模板函数
Code5:
Matm(400,400,CV_8UC3,Scalar(226,46,166));
Before"
if(row%5==0)
//data是uchar*类型的,m.ptr<
uchar>
(row)返回第row行数据的首地址
//需要注意的是该行数据是按顺序存放的,也就是对于一个3通道的Mat,一个像素有
//有3个通道值,[B,G,R][B,G,R][B,G,R]...所以一行长度为:
//sizeof(uchar)*m.cols*m.channels()个字节
uchar*data=m.ptr<
(row);
m.cols;
data[col*3]=102;
//第row行的第col个像素点的第一个通道值Blue
data[col*3+1]=217;
//Green
data[col*3+2]=239;
//Red
After"
cout<
<
(int)m.at<
(0,0)[0]<
'
'
;
//利用Fn1介绍的方法输出一下像素值到控制台
(0,0)[1]<
(0,0)[2]<
endl;
Output5:
End:
Author:
Ggicci
谢谢阅读,有误希望指正!
--OpenCV初学者
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OPENCVMat 存取 方法 元素 访问 汇总