opencv基础_3(Mat数据结构剖析)

1、Mat对象与IplImage对象。

(1)、Mat对象是OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分。其中头部有图像宽度、高度和通道等,数据不有data等。

(2)、IplImage是从2001OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题。

2、Mat对象构造函数与常用方法。

(1)、常用构造函数如下:

Mat():无参构造函数。

Mat(int rows, int cols, int type):创建指定宽高和通道的图像。Mat(1080,1920, CV_8CU1 )表示创建大小为1920x1080一通的图像

Mat(Size size, int type):和第二个构造函数一样。

Mat(int rows, int cols, int type, const Scalar &s):创建指定宽高和通道的图像,并可以给每个通道赋初始值。

Mat(int ndims, const int* sizes, int type):创建n维图像。

Mat(const Mat& m):创建和m对像通道大小一样的图像,并把m的数部分复制给新对象。

Mat(const Mat& m, const Rect& roi):从m对象复制大小为Rect的图像,来创建新对象。

(2)、常用函数:

void copyTo(Mat mat):把自己数据拷贝给mat,属于深拷贝。

Mat clone():克隆出一个新对象,属于深拷贝。

int channels():获取图像的通道数。

int depth():获取图像的位数,8,16,32,64位。

bool empty():判断图像是否为空。空返回true,不空返回false。

uchar* ptr(i=0):获取第i行的图像数据指针。

3、Mat对象使用

(1)、部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分
Mat A= imread(imgFilePath);
Mat B(A)  // 只复制头部数和指针,数据部分和B共用。这里就要说一下Mat的引用机制,只要不是深拷贝,被引用的引用次数就+1,只有所有引用者被释放掉,被引用者的数据内存才会释放。例如:只有B对象结束,并且A结束,A图像的数据部分才会释放,这就是Mat的引用机制,节省内存。

(2)、完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现
Mat F = A.clone(); 或 Mat G; A.copyTo(G);

4、Mat对象使用-四个要点

(1)、输出图像的内存是自动分配的
(2)、使用OpenCV的C++接口,不需要考虑内存分配问题
(3)、赋值操作和拷贝构造函数只会复制头部分
(4)、使用clone与copyTo两个函数实现数据完全复制

5、Mat对象创建

(1)、cv::Mat::Mat构造函数
    Mat M(2,2,CV_8UC3, Scalar(0,0,255))
    其中前两个参数分别表示行(row)跟列(column)、第三个CV_8UC3中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3,第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数目一致

(2)、创建多维数组cv::Mat::create
     int sz[3] = {2,2,2};     
    Mat  L(3,sz, CV_8UC1, Scalar::all(0));

6、Mat数据排列

Mat mat(4, 3, CV_8UC1, Scalar(255)),创建了4行3列8位无符号的图像,并初始化位255。数据排列如下:

255 255 255

255 255 255

255 255 255

255 2552 55

7、获取图像像素 和 修改图像像素

坐标是从0开始的,并且是相对图像原点的位置,图像原点或者是左上角。

假设有8-bit 1-通道的图像mat,获取Point(x, y)的像素值

方法一:

uchar* data = mat.ptr<uchar>(y);  

获取:char value = data[x];

修改:data[x] = 30

方法二:

cv::Vec3b vb = mat.at<cv::Vec3b>(y,  x);

uchar value = vb[0];

方法三:

获取:uchar value = (uchar)(mat.data + matSrc.step * y)[x];

修改:mat.data * x + 0 + matSrc.step * y = 30;

假设有8-bit 3-通道的图像mat,获取Point(x, y)的像素值

方法一:

uchar* data = mat.ptr<uchar>(y);  

获取:

uchar b = data[x + 0];

uchar g = data[x + 1];

uchar r = data[x + 2];

修改:

data[x + 0] = 30;

data[x + 1] = 30;

data[x + 2] = 30;

方法二:

uchar vb= mat.at<cv::Vec3b>(100,  105);

uchar b = vb[0];

uchar g = vb1];

uchar r = vb[2];

方法三:

获取:

uchar b= (uchar)(mat.data + matSrc.step * y)[x + 0];

uchar g= (uchar)(mat.data + matSrc.step * y)[x + 1];

uchar r= (uchar)(mat.data + matSrc.step * y)[x + 2];

修改

mat.data * x + 0 + matSrc.step * y = 30;

mat.data * x + 1 + matSrc.step * y = 30;

mat.data * x + 2 + matSrc.step * y = 30;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mark-puls

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值