您的位置:首页 > 运维架构

【学习OpenCV】—— 深入了解 cv::Mat

2016-04-16 10:34 363 查看
rows:行数,或者高度;cols:列数,或者宽度

实现原理

cv::Mat 有两个必不可少的组成部分,一个头部,一个数据块。

class CV_EXPORTS Mat
{
public:

int flags;
//! the matrix dimensionality, >= 2
int dims;
//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
int rows, cols;

//! pointer to the data
uchar* data;

}


cv::Mat 头部属性主要有:cols、rows 或 channels,而数据块(uchar* data)包含了图像中所有像素的值。

cv::Mat 有一个很重要的特性,就是只有在明确要求时((copyTo、clone)),内存块才会被复制。实际上,大多数操作都只仅仅复制了 cv::Mat 的头部信息,因此多个对象会同时指向同一个数据块。这种内存管理模式可以提高应用程序的运行效率,避免内存泄露。

cv::Mat image1(240, 320, CV_8U, 100);


我们需要指定每个矩阵元素的类型,CV_8U 表示每个像素对应一个字节,U表示无符号,字母S则是有符号。对于彩色图像,可用 CV_8UC3(C表示channel)

我们可以随时用 create 方法分配或重新分配图像的数据块,如果图像已经分配,首先其原来的内容会被释放。出于对性能的考虑,如果新的大小和类型与原来的相同,就不会重新分配内存(可以想象,会直接覆盖)。

// 重新分配一个新图像
// (仅在大小或类型不同时)
image1.create(200, 200, CV_8U);


一旦没有了指向 cv::Mat 对象的引用,分配的内存就会被自动释放。这一点可避免 C++ 动态内存分配(new)中常常发生的内存泄露问题。这是 OpenCV2 中的一个关键机制,通过 cv::Mat 实现引用计数(reference count)和浅复制。当在两个图像之间赋值时,图像数据(也即像素)并不会被复制,此时两个图像指向同一个内存块。

一些细节

cv::Mat image = cv::imread("...");


(1)Mat 类型

if (image.type() == CV_8U)
image.at<uchar>(i, j) = ...;

if (image.type() == CV_8UC3)
image.at<cv::Vec3b>(i, j)[0] = ...;
image.at<cv::Vec3b>(i, j)[1] = ...;
image.at<cv::Vec3b>(i, j)[2] = ...;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: