Opencv 矩阵基础

来源:互联网 发布:淘淘居淘宝小号 编辑:程序博客网 时间:2024/06/08 13:42

Opencv 矩阵基础

简介

image_container

Opencv 是一个致力于解决数字图像处理的开源库。在进行数字图像处理之前,我们首先需要了解 Opencv 的图像表达方式。如上图所示,任何数字图像都是由多个点(像素点)的数值组成的,Opencv 自定义了一个类来表示图像–Mat 类。

Mat

Opencv 是一个C++库,那么 Mat 类肯定就涉及内存的分配和释放的问题了。值得庆幸的是,Opencv 的开发者们已经为我们做了大部分的工作。Mat 类是不需要手动分配/释放内存的。当我们新建一个 Mat 实例时,根据我们给出的参数,Mat 类的构造函数已经自动分配了合适的内存了。至于 Mat 实例的释放,就类似于 C++ Boost 库中的智能指针一样,当没有任何引用的时候,Mat 实例会自动释放已经分配的内存。

Mat 包含两个部分:矩阵头部和矩阵指针。顾名思义,矩阵头部包含矩阵的一些基本信息,比如矩阵大小,矩阵的存储方式(稍后再讲),矩阵的指针等等。矩阵指针是指向包含图像像素值的矩阵的指针。

这样的格式方便了我们之前提到的 Mat 自动分配/释放内存的实现。Opencv 使用了引用计数的方法来实现内存管理, 即每个 Mat 实例都有自己的矩阵头部,但是他们共享了同一个矩阵指针。并且 Mat 类的复制操作只是执行矩阵头部和矩阵指针的复制,不再分配任何的内存, 这样做节省内存的同时,也节省了内存分配的时间。当然如果需要重新分配内存(例如,不希望数据操作影响原始数据),可以使用 Opencv 提供的额外函数(copyTo() 或者 clone())来实现。

Mat A, C;  // 创建矩阵头部, 矩阵指针为NULL A = imread(argv[1], IMREAD_COLOR); // 读取图像,分配内存Mat B(A);  // 复制构造函数C = A;// 赋值操作

上面所有实例具有同一个矩阵指针,但是具有不同的矩阵头部。当我们只对图像中某一区域感兴趣的时候,我们可以使用创建一个新的矩阵头部。比如创建一个图像的感兴趣区域(ROI),我们可以这样操作:

Mat D (A, Rect(10, 10, 100, 100) ); // 使用举行选择框选择Mat E = A(Range::all(), Range(1,3)); // 使用行列边界

矩阵 DE 具有和矩阵 A 一样的矩阵指针,不同的矩阵头部。

关于Mat的使用,需要记住一下几点:

  • 函数输出的 Mat 矩阵是自动分配内存的,除非特殊指定。
  • 当我们使用 Opencv 的C++接口时,我们不需要考虑内存管理的问题。
  • 赋值操作和复制构造函数只是复制了矩阵的头部和指针,不再分配内存。
  • 如果需要重新分配图像内存或者深度复制矩阵的话,那么可以使用 clone()copyTo() 函数。

存储方式

存储方式是指 Mat 矩阵如何存储像素值, 它包括两个部分:颜色系统和数据类型。颜色系统是指当前图像使用的颜色标识方案,比如RGB, HSV等, Mat 是以多通道的方式来存储图像数据的。数据类型是指每个像素每个通道的数据类型,比如8bit, 16bit, 32bit, 浮点型。这是举例来说明通道的意思,对于灰度图像,它只有一个通道;对于RGB图像,它具有R,G,B三个通道。Opencv 定义了一系列的宏来表示不同类型的矩阵,这些宏不局限于表达图像,它可以表达任何形式的矩阵。稍后的文章里会有详细的介绍。

0 0