OpenCV 4 中文文档
原文https://www.docs.opencv.org/4.5.3/
目录
一、介绍
OpenCV(开源计算机视觉库:http://opencv.org)是一个开源库,它包括数百种计算机视觉算法。该文件描述了OpenCV 2.x API,它本质上是一个C++ API,而不是基于C的OpenCV 1.x API(C API 自 OpenCV 2.4 发布以来已弃用且未使用"C"编译器进行测试)。
OpenCV 具有模块化结构,这意味着该包包括多个共享或静态库。提供以下模块:
- 核心功能(core):定义基本数据结构的紧凑型模块,包括密集的多维阵列 Mat 和所有其他模块使用的基本功能。
- 图像处理(imgproc) : 图像处理模块,包括线性和非线性图像过滤、图像几何变换(大小、仿射和透视扭曲、基于通用表的重映射)、色彩空间转换、直方图等。
- 视频分析(video):包括运动估计、背景消除和对象跟踪算法的视频分析模块。
- 相机校准和 3D 重建(calib3d):基本的多视图几何算法、单声相机和立体相机校准、对象姿势估计、立体声通信算法和 3D 重建元素。
- 2D 功能框架(features2d):显著特征探测器、描述符和描述符匹配器。
- 对象检测(objdetect):检测预定类的对象和实例(例如,人脸、眼睛、杯子、人、汽车等)。
- 高级GUI (highgui):简单UI功能的易用界面。
- 视频 I/O (videoio ):易于使用的视频捕获和视频编解码器接口。
- 其他一些辅助模块,如FLNN和谷歌测试包装器,Python绑定等。
文档的其他章节描述了每个模块的功能。但首先,请务必熟悉库中彻底使用的常见 API 概念。
一、API概念
1. cv Namespace(cv名称空间)
所有 OpenCV 类和函数都放在 cv
命名空间中。因此,要从您的代码访问此功能,请使用 cv::
说明符或 using namespace cv;
标识:
#include "opencv2/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2, cv::RANSAC, 5);
...
或
#include "opencv2/core.hpp"
using namespace cv;
...
Mat H = findHomography(points1, points2, RANSAC, 5 );
...
某些当前或未来的 OpenCV 外部名称可能与 STL 或其他库冲突。在这种情况下,使用显式命名空间说明符来解决名称冲突:
Mat a(100, 100, CV_32F);
randu(a, Scalar::all(1), Scalar::all(std::rand()));
cv::log(a, a);
a /= std::log(2.);
2. 自动内存管理
OpenCV 自动处理所有内存。
首先,函数和方法使用的 std::vector
、cv::Mat
和其他数据结构具有析构函数,可在需要时释放底层内存缓冲区。这意味着析构函数并不总是像 Mat 那样释放缓冲区。他们考虑了可能的数据共享。析构函数递减与矩阵数据缓冲区关联的参考计数器。当且仅当引用计数器达到零时,即当没有其他结构引用同一缓冲区时,才会释放缓冲区。类似地,当复制 Mat 实例时,并没有真正复制实际数据。相反,引用计数器递增以记住相同数据的另一个所有者。还有 Mat::clone
方法可以创建矩阵数据的完整副本。请参阅下面的示例:
// create a big 8Mb matrix
//创建一个大的 8Mb 矩阵
Mat A(1000, 1000, CV_64F);
// create another header for the same matrix;
// this is an instant operation, regardless of the matrix size.
//为相同矩阵创建另一个标题;
//这是一个即时操作,无论矩阵大小如何。
Mat B = A;
// create another header for the 3-rd row of A; no data is copied either
//为第3行创建另一个标题;任何一个数据都没有复制
Mat C = B.row(3);
// now create a separate copy of the matrix
//现在创建一个单独的矩阵副本
Mat D = B.clone();
// copy the 5-th row of B to C, that is, copy the 5-th row of A to the 3-rd row of A.
//复制B的第5行到C,即复制A的第5行到A的第3行。
B.row(5).copyTo(C);
// now let A and D share the data; after that the modified version of A is still referenced by B and C.
//现在让A和D共享数据;之后修改了A仍被B和C引用的版本。
A = D;
// now make B an empty matrix (which references no memory buffers),
// but the modified version of A will still be referenced by C,
// despite that C is just a single row of the original A
//现在让B变为一个空矩阵(没有内存缓冲区的引用),
//但A修改后的版本将仍然被C引用,
//尽管C只是原来A中的一行
B.release();
// finally, make a full copy of C. As a result, the big modified
// matrix will be deallocated, since it is not referenced by anyone
//最后,制作C的完整副本。结果,大修改了
//矩阵将被释放,因为它没有被任何人引用
C = C.clone();
你看到使用 Mat
和其他基本结构很简单。但是在不考虑自动内存管理的情况下创建高级类甚至用户数据类型呢?对于他们而言,OpenCV提供了类似于C ++ 11的 std::hared_ptr
的 cv::Ptr
模板类。因此,不要使用普通指针:
T* ptr = new T(...);
你可以使用:
Ptr<T> ptr(new T(...));
//或者
Ptr<T> ptr = makePtr<T>(...);
Ptr< T>
封装指向T实例的指针和与指针关联的引用计数器。有关详细信息,请参见 cv::Ptr
说明。
3. 输出数据的自动分配
OpenCV自动释放内存,并在大多数情况下自动为输出函数参数分配内存。因此,如果函数有一个或多个输入数组(例如cv::Mat
)和一些输出数组,则输出数组将自动分配或重新分配。输出数组的大小和类型由输入数组的大小和类型决定。如果需要,这些函数将使用额外的参数来帮助确定输出数组属性。
例如:
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main(i