OpenCV 4 中文文档(更新介绍部分)

OpenCV 4 中文文档

原文https://www.docs.opencv.org/4.5.3/

目录

  • OpenCV 4 中文文档
    • 一、介绍
      • 一、API概念
        • 1. cv Namespace(cv名称空间)
        • 2. 自动内存管理
        • 3. 输出数据的自动分配
        • 4. 饱和算法
        • 5. 固定像素类型。模板的有限使用
        • 6. 输入阵列和输出阵列
        • 7. 错误处理
        • 8. 多线程和可重入性

一、介绍

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::vectorcv::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_ptrcv::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(int, char**)
{
    VideoCapture cap(0);
    if(!cap.isOpened()) return -1;
    Mat frame, edges;
    namedWindow("edges", WINDOW_AUTOSIZE);
    for(;;)
    {
        cap >> frame;
        cvtColor(frame, edges, COLOR_BGR2GRAY);
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
        Canny(edges, edges, 0, 30, 3);
        imshow("edges", edges);
        if(waitKey(30) >= 0) break;
    }
    return 0;
}

阵列帧由 >> 操作自动分配,因为视频捕获模块知道视频帧分辨率和位深度。阵列边缘由 cvtColor 函数自动分配。它与输入数组具有相同的大小和位深度。通道数为1,因为传递了颜色转换代码 cv::color_BGR2GRAY ,这意味着彩色到灰度的转换。注意,在循环体的第一次执行期间,帧和边仅分配一次,因为所有下一个视频帧具有相同的分辨率。如果您以某种方式更改视频分辨率,阵列将自动重新分配。
该技术的关键组件是 Mat::create 方法。它采用所需的数组大小和类型。如果数组已经具有指定的大小和类型,则该方法不执行任何操作。否则,它将释放先前分配的数据(如果有)(这部分涉及减少引用计数器并将其与零进行比较),然后分配所需大小的新缓冲区。大多数函数为每个输出数组调用 Mat::create 方法,因此实现了自动输出数据分配。
此方案的一些显著例外是 cv::MixChannelcv::RNG::fill 和其他一些函数和方法。他们无法分配输出数组,因此你必须提前这样做。

4. 饱和算法

作为一个计算机视觉库,OpenCV处理很多图像像素,这些像素通常以紧凑的、每通道8位或16位的形式编码,因此具有有限的值范围。此外,图像上的某些操作,如颜色空间转换、亮度/对比度调整、锐化、复杂插值(双立方插值、Lanczos)可能会产生超出可用范围的值。如果只存储结果的最低8(16)位,则会产生视觉伪影,并可能影响进一步的图像分析。为了解决这个问题,使用了所谓的饱和算法。例如,要将操作结果r存储到8位图像中,你可以找到0…255范围内最接近的值:
I ( x , y ) = m i n ( m a x ( r o u n d ( r ) , 0 ) , 255 ) I(x,y)=min(max(round(r),0),255) I(x,y)=min(max(round(r),0),255)
类似的规则适用于8位有符号、16位有符号和无符号类型。这种语义在库中随处可见。在C++代码中,它使用类似于标准C++ CAST操作的 cv::saturate_cast<> 函数。见上文公式的实施情况:

I.at<uchar>(y, x) = saturate_cast<uchar>(r);

其中 cv::uchar 是OpenCV 8位无符号整数类型。在优化的SIMD代码中,使用了诸如ppaddusb, packuswb等SSE2指令。它们有助于实现与C++代码完全相同的行为。

注:当结果为32位整数时,不应用饱和。

5. 固定像素类型。模板的有限使用

模板是C++的一大特色,它能够实现非常强大、高效且安全的数据结构和算法。但是,模板的广泛使用可能会显著增加编译时间和代码大小。此外,如果只使用模板,则很难将接口和实现分开。这对于基本算法来说可能很好,但对于计算机视觉库来说并不好,因为在计算机视觉库中,单个算法可能跨越数千行代码。因此,为了简化其他语言(如Python、Java、Matlab)绑定的开发,这些语言根本没有模板或模板功能有限,当前的OpenCV实现基于多态性和运行时模板调度。在运行时调度太慢(如像素访问操作符)、不可能(通用 cv::Ptr 实现)或非常不方便( cv::saturate_cast<>() )的地方,当前的实现引入了小模板类、方法和函数。在当前OpenCV版本的任何其他地方,模板的使用都是有限的。
因此,库可以操作的基本数据类型集是有限的。也就是说,数组元素应具有以下类型之一:

  • 8-bit unsigned integer (uchar)
  • 8-bit signed integer (schar)
  • 16-bit unsigned integer (ushort)
  • 16-bit signed integer (short)
  • 32-bit signed integer (int)
  • 32-bit floating-point number (float)
  • 64-bit floating-point number (double)
  • 多个元素的元组,其中所有元素都具有相同的类型(上述元素之一)。元素为元组的数组称为多通道数组,与元素为标量值的单通道数组相反。通道的最大可能数量由 CV_CN_MAX 常量定义,该常量当前设置为512。

对于这些基本类型,将应用以下枚举:

enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };

可以使用以下选项指定多通道(n通道)类型:

  • CV_8UC1CV_64FC4常数(适用于从1到4的多个通道)
  • CV_8UC(n)CV_64FC(n)or CV_MAKETYPE(CV_8U, n)CV_MAKETYPE(CV_64F, n) 编译时通道数大于4或未知时的宏。

注:CV_32FC1 == CV_32F, CV_32FC2 == CV_32FC(2) == CV_MAKETYPE(CV_32F, 2), and CV_MAKETYPE(depth, n) == ((depth&7) + ((n-1)<<3). 这意味着常数类型由深度形成,取最低的3位,通道数减1,取下一个 log2(CV_CN_MAX)位。

例如:

Mat mtx(3, 3, CV_32F); 
// make a 3x3 floating-point matrix
// 创建一个3x3浮点矩阵

Mat cmtx(10, 1, CV_64FC2); 
// make a 10x1 2-channel floating-point
// matrix (10-element complex vector)
// 创建一个10x1的2通道浮点值
// 矩阵(10元素的复杂向量)

Mat img(Size(1920, 1080), CV_8UC3); 
// make a 3-channel (color) image of 1920 columns and 1080 rows.
// 创建一个有1920列和1080行的3通道(彩色)图像。

Mat grayscale(image.size(), CV_MAKETYPE(image.depth(), 1)); 
// make a 1-channel image of the same size and same channel type as img
// 创建一个与img的尺寸和通道类型相同的单通道图像。

无法使用OpenCV构造或处理包含更复杂元素的数组。此外,每个函数或方法只能处理所有可能数组类型的子集。通常,算法越复杂,支持的格式子集越小。见以下此类限制的典型示例:

  • 人脸检测算法仅适用于8位灰度或彩色图像。
  • 线性代数函数和大多数机器学习算法仅适用于浮点数组。
  • 基本函数,如 cv::add,支持所有类型。
  • 颜色空间转换函数支持8位无符号、16位无符号和32位浮点类型。

每个功能支持的类型子集已根据实际需要定义,并可在将来根据用户请求进行扩展。

6. 输入阵列和输出阵列

许多OpenCV函数处理密集的二维或多维数值数组。通常,此类函数将cppMat作为参数,但在某些情况下,使用std::vector<>(例如,对于点集)或 cv::Matx<>(对于3x3单应矩阵等)更方便。为了避免API中的许多重复,引入了特殊的“代理”类。基本的“代理”类是 cv::InputArray。它用于在函数输入上传递只读数组。派生自InputArray类cv::OutputArray用于指定函数的输出数组。通常,你不应该关心这些中间类型(也不应该显式地声明这些类型的变量)——它将自动工作。您可以假设可以始终使用Matstd::vector<>cv::Matx<>cv::Vec<>cv::Scalar代替InputArray/OutputArray。如果函数具有可选的输入或输出数组,而你没有想要或不想要,请传递cv::noArray()

7. 错误处理

OpenCV使用异常来表示严重错误。当输入数据具有正确的格式并且属于指定的值范围,但由于某种原因(例如,优化算法没有收敛)算法无法成功时,它将返回一个特殊的错误代码(通常,只是一个布尔变量)。
异常可以是 cv::Exception 类或其派生类的实例。反过来,cv::Exceptionstd::Exception的派生。因此,它可以在代码中优雅地使用其他标准的C++库组件来处理。
通常使用CV_Error(errcode, description)宏或printf-like的CV_Error_(errcode, (printf-spec, printf-args))变量引发异常,或者使用CV_Assert(condition)宏检查条件并在不满足条件时引发异常。对于性能关键代码,CV_DbgAssert(condition)仅保留在调试配置中。由于自动内存管理,所有中间缓冲区在发生突然错误时自动释放。如果需要,只需添加try语句即可捕获异常:

try
{
    ... // call OpenCV
}
catch (const cv::Exception& e)
{
    const char* err_msg = e.what();
    std::cout << "exception caught: " << err_msg << std::endl;
}

8. 多线程和可重入性

当前的OpenCV实现是完全可重新输入的。也就是说,可以从不同线程调用不同类实例的相同函数或相同方法。同样,相同的Mat也可以在不同的线程中使用,因为引用计数操作使用特定于体系结构的原子指令。

热门文章

暂无图片
编程学习 ·

exe4j详细使用教程(附下载安装链接)

一、exe4j介绍 ​ exe4j是一个帮助你集成Java应用程序到Windows操作环境的java可执行文件生成工具&#xff0c;无论这些应用是用于服务器&#xff0c;还是图形用户界面&#xff08;GUI&#xff09;或命令行的应用程序。如果你想在任务管理器中及Windows XP分组的用户友好任务栏…
暂无图片
编程学习 ·

AUTOSAR从入门到精通100讲(126)-浅谈车载充电系统通信方案

01 引言 本文深入研究车载充电系统策略,设计出一套基于电动汽车电池管理系统与车载充电机的CAN通信协议,可供电动汽车设计人员参考借鉴。 02 电动汽车充电系统通讯网络 电动汽车整车控制系统中采用的是CAN总线通信方式,由一个整车内部高速CAN网络、内部低速CAN网络和一个充电…
暂无图片
编程学习 ·

CMake(九):生成器表达式

当运行CMake时&#xff0c;开发人员倾向于认为它是一个简单的步骤&#xff0c;需要读取项目的CMakeLists.txt文件&#xff0c;并生成相关的特定于生成器的项目文件集(例如Visual Studio解决方案和项目文件&#xff0c;Xcode项目&#xff0c;Unix Makefiles或Ninja输入文件)。然…
暂无图片
编程学习 ·

47.第十章 网络协议和管理配置 -- 网络配置(八)

4.3.3 route 命令 路由表管理命令 路由表主要构成: Destination: 目标网络ID,表示可以到达的目标网络ID,0.0.0.0/0 表示所有未知网络,又称为默认路由,优先级最低Genmask:目标网络对应的netmaskIface: 到达对应网络,应该从当前主机哪个网卡发送出来Gateway: 到达非直连的网络,…
暂无图片
编程学习 ·

元宇宙技术基础

请看图&#xff1a; 1、通过AR、VR等交互技术提升游戏的沉浸感 回顾游戏的发展历程&#xff0c;沉浸感的提升一直是技术突破的主要方向。从《愤怒的小鸟》到CSGO,游戏建模方式从2D到3D的提升使游戏中的物体呈现立体感。玩家在游戏中可以只有切换视角&#xff0c;进而提升沉浸…
暂无图片
编程学习 ·

flink的伪分布式搭建

一 flink的伪分布式搭建 1.1 执行架构图 1.Flink程序需要提交给 Job Client2.Job Client将作业提交给 Job Manager3.Job Manager负责协调资源分配和作业执行。 资源分配完成后&#xff0c;任务将提交给相应的 Task Manage。4.Task Manager启动一个线程以开始执行。Task Manage…
暂无图片
编程学习 ·

十进制正整数与二进制字符串的转换(C++)

Function one&#xff1a; //十进制数字转成二进制字符串 string Binary(int x) {string s "";while(x){if(x % 2 0) s 0 s;else s 1 s;x / 2;}return s; } Function two&#xff1a; //二进制字符串变为十进制数字 int Decimal(string s) {int num 0, …
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统&#xff1a; 微信小程序——辩论管理前台涉及技术&#xff1a;WXML 和 WXS…
暂无图片
编程学习 ·

树莓派驱动DHT11温湿度传感器

1&#xff0c;直接使用python库 代码如下 import RPi.GPIO as GPIO import dht11 import time import datetimeGPIO.setwarnings(True) GPIO.setmode(GPIO.BCM)instance dht11.DHT11(pin14)try:while True:result instance.read()if result.is_valid():print(ok)print(&quo…
暂无图片
编程学习 ·

ELK简介

ELK简介 ELK是三个开源软件的缩写&#xff0c;Elasticsearch、Logstash、Kibana。它们都是开源软件。不过现在还新增了一个 Beats&#xff0c;它是一个轻量级的日志收集处理工具(Agent)&#xff0c;Beats 占用资源少&#xff0c;适合于在各个服务器上搜集日志后传输给 Logstas…
暂无图片
编程学习 ·

Linux 基础

通常大数据框架都部署在 Linux 服务器上&#xff0c;所以需要具备一定的 Linux 知识。Linux 书籍当中比较著名的是 《鸟哥私房菜》系列&#xff0c;这个系列很全面也很经典。但如果你希望能够快速地入门&#xff0c;这里推荐《Linux 就该这么学》&#xff0c;其网站上有免费的电…
暂无图片
编程学习 ·

Windows2022 无线网卡装不上驱动

想来 Windows2022 和 windows10/11 的驱动应该差不多通用的&#xff0c;但是死活装不上呢&#xff1f; 搜一下&#xff0c;有人提到 “默认安装时‘无线LAN服务’是关闭的&#xff0c;如果需要开启&#xff0c;只需要在“添加角色和功能”中&#xff0c;选择开启“无线LAN服务…
暂无图片
编程学习 ·

【嵌入式面试宝典】版本控制工具Git常用命令总结

目录 创建仓库 查看信息 版本回退 版本检出 远程库 Git 创建仓库 git initgit add <file> 可反复多次使用&#xff0c;添加多个文件git commit -m <message> 查看信息 git status 仓库当前的状态git diff 差异对比git log 历史记录&#xff0c;提交日志--pret…
暂无图片
编程学习 ·

用Postman生成测试报告

newman newman是一款基于nodejs开发的可以运行postman脚本的工具&#xff0c;使用Newman&#xff0c;可以直接从命令运行和测试postman集合。 安装nodejs 下载地址&#xff1a;https://nodejs.org/en/download/ 选择自己系统相对应的版本内容进行下载&#xff0c;然后傻瓜式安…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…