首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

SUBSCRIBE / SUBACK / UNSUBSCRIBE / UNSUBACK 报文格式

SUBSCRIBE / SUBACK / UNSUBSCRIBE / UNSUBACK 报文格式

OASIS MQTT 5.0:§3.8 SUBSCRIBE§3.9 SUBACK§3.10 UNSUBSCRIBE§3.11 UNSUBACK
Topic / 通配符 / 共享订阅概念见:01-主题与发布订阅模型.md


1. SUBSCRIBE(§3.8)

1.1 Fixed Header

Type Flags
8 必须 0010(bit1=1)

1.2 Variable Header

1
Packet Identifier → Properties(5.0)

常见 Properties:

属性 作用
Subscription Identifier 订阅标识;后续 PUBLISH 可带回,便于 Client 分流回调
User Property 自定义

1.3 Payload:订阅列表

由一个或多个订阅组成,每项:

1
2
3
4
┌─────────────────────┬──────────────────┐
│ Topic Filter │ Subscription │
│ (UTF-8 String) │ Options (1 byte) │
└─────────────────────┴──────────────────┘

Subscription Options(1 字节,5.0)

1
2
3
4
5
6
 bit7-6      bit5-4     bit3      bit2       bit1-0
┌──────────┬──────────┬─────────┬──────────┬─────────┐
│ Reserved │ Retain │ Retain │ No Local │ Maximum │
│ =0 │ Handling │ As Pub.*│ │ QoS │
└──────────┴──────────┴─────────┴──────────┴─────────┘
* bit3: RAP — Retain As Published(名称以规范为准)
字段 含义
Maximum QoS Client 愿接受的最大 QoS(0/1/2)
No Local 1=不接收自己在同连接上发布的消息
Retain As Published 转发时保留原消息 RETAIN 标志
Retain Handling 0=发送保留消息;1=仅新订阅发送;2=不发送保留消息

3.1.1:Payload 每项仅为 Topic Filter + Requested QoS(1 字节,高 6 位必须为 0)

1.4 Topic Filter 规则(摘要)

  • 可含 + / # 通配符(# 须单独一层且在末尾)
  • MQTT 5 共享订阅:$share/{ShareName}/{TopicFilter}
  • 非法 Filter → Server 在 SUBACK 返回失败 Reason,或协议错误处理

2. SUBACK(§3.9)

2.1 Fixed Header

Type=9,Flags=0000

2.2 Variable Header

1
Packet Identifier → Properties(5.0)(Reason String、User Property…)

2.3 Payload:Reason Code 列表

  • 按订阅顺序一一对应 SUBSCRIBE Payload 中的每一项
  • 每个 1 字节
Reason(例) 含义
0x00 Granted QoS 0
0x01 Granted QoS 1
0x02 Granted QoS 2
0x80 Unspecified error
0x83 Implementation specific error
0x87 Not authorized
0x8F Topic Filter invalid
0x91 Packet Identifier in use
0x97 Quota exceeded
0x9E Shared Subscriptions not supported
0xA1 Subscription Identifiers not supported
0xA2 Wildcard Subscriptions not supported

要点:Granted QoS 可以低于 Requested QoS;Client 必须以 SUBACK 为准。

3.1.1:Payload 为 Return Code(0x00/0x01/0x02/0x80)。


3. UNSUBSCRIBE(§3.10)

3.1 Fixed Header

Type=10,Flags=0010

3.2 Variable Header

Packet Identifier + Properties(5.0)。

3.3 Payload

一个或多个 Topic Filter(UTF-8 String),无 Options 字节。


4. UNSUBACK(§3.11)

4.1 Fixed Header

Type=11,Flags=0000

4.2 Variable Header

Packet Identifier + Properties(5.0)。

4.3 Payload(MQTT 5)

每个 Topic Filter 对应 1 字节 Reason Code,例如:

Code 含义
0x00 Success
0x11 No subscription existed
0x80 Unspecified error
0x87 Not authorized
0x8F Topic Filter invalid

3.1.1:UNSUBACK 仅有 Packet Identifier,无 Payload Reason 列表。


5. 时序示例

1
2
3
4
5
6
Client ── SUBSCRIBE  (P=10, filter=siteA/+/state, maxQoS=1) ──▶ Server
Client ◀─ SUBACK (P=10, reason=0x01 Granted QoS1) ─────── Server
Server ── PUBLISH (匹配消息) ─────────────────────────────▶ Client

Client ── UNSUBSCRIBE (P=11, filter=siteA/+/state) ──────────▶ Server
Client ◀─ UNSUBACK (P=11, reason=0x00) ─────────────────── Server

下一篇:14-PING-DISCONNECT-AUTH报文格式.md

PING / DISCONNECT / AUTH 报文格式

PING / DISCONNECT / AUTH 报文格式

OASIS MQTT 5.0:§3.12 PINGREQ§3.13 PINGRESP§3.14 DISCONNECT§3.15 AUTH
Keep Alive / 会话行为见:02-控制报文与会话.md11-CONNECT与CONNACK报文格式.md


1. PINGREQ(§3.12)

Type 12
Flags 0000
Remaining Length 0
Variable Header / Payload

用途:在 Keep Alive 周期内保活;证明 Client 存活且连接可用。

1
Fixed Header 仅 2 字节:0xC0 0x00

2. PINGRESP(§3.13)

Type 13
Flags 0000
Remaining Length 0
1
Fixed Header:0xD0 0x00

Server 必须响应 PINGREQ。Client 若收不到 PINGRESP,应按规范处理为连接故障。


3. DISCONNECT(§3.14)

3.1 方向

  • MQTT 5:Client→Server Server→Client 均可发送
  • MQTT 3.1.1:主要是 Client→Server;且报文极简

3.2 Fixed Header

Type=14,Flags=0000

3.3 Variable Header(MQTT 5)

1
Reason Code (1 byte) → Properties

Remaining Length 可为 0(等价 Reason=0x00 且无属性,规范允许的简写形式)。

常见 Reason Code

Code 含义(示例)
0x00 Normal disconnection
0x04 Disconnect with Will Message(Client 可请求仍发 Will)
0x80 Unspecified error
0x81 Malformed Packet
0x82 Protocol Error
0x87 Not authorized
0x88 Server busy
0x89 Server shutting down
0x8B Keep Alive timeout(Server→Client)
0x8D Session taken over
0x8E Topic Filter invalid
0x90 Topic Name invalid
0x93 Receive Maximum exceeded
0x94 Topic Alias invalid
0x95 Packet too large
0x96 Message rate too high
0x98 Administrative action
0x9C Use another server
0x9D Server moved
0xA0 Maximum connect time
0xA1 Subscription Identifiers not supported 等

常见 Properties

属性 作用
Session Expiry Interval Client 可在断开时改会话过期(有条件)
Reason String 可读原因
User Property 自定义
Server Reference 指向另一服务器

3.4 正常断开 vs 异常断开

情况 Will
发送 DISCONNECT(正常原因)后关连接 通常发布 Will
网络中断 / Keep Alive 超时 / 未发 DISCONNECT 可触发 Will(若已配置)

MQTT 5 的 0x04 Disconnect with Will Message 允许显式要求发送 Will。

3.5 MQTT 3.1.1 DISCONNECT

  • 仅 Fixed Header:0xE0 0x00
  • 无 Reason / Properties

4. AUTH(§3.15,仅 MQTT 5)

用于 Enhanced Authentication 多步交换(CONNECT 中声明 Authentication Method)。

4.1 Fixed Header

Type=15,Flags=0000

4.2 Variable Header

1
Authenticate Reason Code → Properties
Reason(例) 含义
0x00 Success
0x18 Continue authentication
0x19 Re-authenticate

Properties 必含/常含:

属性 作用
Authentication Method 方法名(与 CONNECT 一致)
Authentication Data 方法相关二进制挑战/应答
Reason String / User Property 诊断

4.3 典型流程(概念)

1
2
3
4
Client ── CONNECT (Auth Method=…) ──▶ Server
Client ◀─ AUTH (Continue + Data) ──── Server
Client ── AUTH (Continue + Data) ───▶ Server
Client ◀─ CONNACK (Success) ───────── Server

亦可在已连接状态下 Re-authenticate


5. 运维抓包提示

现象 看什么
周期性 C0 00 / D0 00 Keep Alive 正常
Server 发 DISCONNECT 0x8B Keep Alive 超时
Server 发 DISCONNECT 0x8D 同 ClientID 被顶号
AUTH 循环失败 Method/Data 或 Broker 插件配置

下一篇:15-Reason-Code与Properties目录.md

Reason Code 与 Properties 目录(MQTT 5)

Reason Code 与 Properties 目录(MQTT 5)

依据 OASIS MQTT 5.0 §2.2.2 Properties§2.4 Reason Code 及各控制报文章节整理
完整规范性定义以正式 HTML/PDF 为准:
https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html
MQTT 3.1.1 本目录所述 Properties / 细粒度 Reason Code 体系


1. Reason Code 使用位置

报文 是否常见带 Reason
CONNACK Connect Reason Code
PUBACK / PUBREC / PUBREL / PUBCOMP 发布流 Reason
SUBACK / UNSUBACK 每订阅/每过滤一项
DISCONNECT 断开原因
AUTH 认证步骤结果

0x00 在多数上下文表示成功;0x80 及以上通常表示错误(具体以该报文章节表格为准)。


2. 常用 Reason Code 速查(跨报文高频)

Code 名称(英文习惯) 典型场景
0x00 Success / Normal disconnection / Granted QoS0 成功
0x01 Granted QoS 1 SUBACK
0x02 Granted QoS 2 SUBACK
0x04 Disconnect with Will Message DISCONNECT
0x10 No matching subscribers PUBACK/PUBREC
0x11 No subscription existed UNSUBACK
0x18 Continue authentication AUTH
0x19 Re-authenticate AUTH
0x80 Unspecified error 多处
0x81 Malformed Packet 解析失败
0x82 Protocol Error 协议违规
0x83 Implementation specific error 实现特定
0x84 Unsupported Protocol Version CONNACK
0x85 Client Identifier not valid CONNACK
0x86 Bad User Name or Password CONNACK
0x87 Not authorized 鉴权失败
0x88 Server unavailable CONNACK
0x89 Server busy CONNACK / DISCONNECT
0x8A Banned CONNACK
0x8B Server shutting down / Keep Alive timeout 视报文
0x8C Bad authentication method CONNACK
0x8D Session taken over DISCONNECT
0x8F Topic Filter invalid SUBACK 等
0x90 Topic Name invalid PUBLISH 相关
0x91 Packet Identifier in use 订阅/发布
0x93 Receive Maximum exceeded 流控
0x94 Topic Alias invalid PUBLISH
0x95 Packet too large 包长
0x97 Quota exceeded 配额
0x99 Payload format invalid 载荷格式
0x9A Retain not supported CONNACK/相关
0x9B QoS not supported CONNACK
0x9C Use another server 重定向
0x9D Server moved 重定向
0x9E Shared Subscriptions not supported SUBACK
0x9F Connection rate exceeded CONNACK
0xA1 Subscription Identifiers not supported SUBACK
0xA2 Wildcard Subscriptions not supported SUBACK

同一数值在不同报文中的官方名称可能略有差别;排障时以该报文章节的 Reason Code 表为准。


3. Property Identifier 目录(常用)

ID 属性名 值类型 典型报文
0x01 Payload Format Indicator Byte PUBLISH, Will
0x02 Message Expiry Interval Four Byte PUBLISH, Will
0x03 Content Type UTF-8 String PUBLISH, Will
0x08 Response Topic UTF-8 String PUBLISH, Will
0x09 Correlation Data Binary PUBLISH, Will
0x0B Subscription Identifier Var Byte Int SUBSCRIBE, PUBLISH
0x11 Session Expiry Interval Four Byte CONNECT, CONNACK, DISCONNECT
0x12 Assigned Client Identifier UTF-8 String CONNACK
0x13 Server Keep Alive Two Byte CONNACK
0x15 Authentication Method UTF-8 String CONNECT, CONNACK, AUTH
0x16 Authentication Data Binary CONNECT, CONNACK, AUTH
0x17 Request Problem Information Byte CONNECT
0x18 Will Delay Interval Four Byte Will Properties
0x19 Request Response Information Byte CONNECT
0x1A Response Information UTF-8 String CONNACK
0x1C Server Reference UTF-8 String CONNACK, DISCONNECT
0x1F Reason String UTF-8 String 多种 ACK/DISCONNECT
0x21 Receive Maximum Two Byte CONNECT, CONNACK
0x22 Topic Alias Maximum Two Byte CONNECT, CONNACK
0x23 Topic Alias Two Byte PUBLISH
0x24 Maximum QoS Byte CONNACK
0x25 Retain Available Byte CONNACK
0x26 User Property UTF-8 String Pair 多处(可重复)
0x27 Maximum Packet Size Four Byte CONNECT, CONNACK
0x28 Wildcard Subscription Available Byte CONNACK
0x29 Subscription Identifier Available Byte CONNACK
0x2A Shared Subscription Available Byte CONNACK

未列出的 Identifier 见规范完整表;实现必须忽略无法识别属性或按规范报错(视报文规则)。


4. 与本库其它文档

主题 文档
报文总结构 10-MQTT控制报文格式总览.md
连接 11
发布/QoS 12
订阅 13
心跳/断开/认证 14
5.0 特性综述 04-MQTT5新特性.md
正式规范链接 09-规范与资料索引.md

5. 合规声明

本目录为便于联调的速查整理。字段强制条件、默认值、哪些属性可重复、错误时关闭连接还是仅丢包等,一律以 OASIS MQTT 5.0 正式文本对应章节的 Normative 表述为准

01 OpenCV 4.13.0 系统概述

01 OpenCV 4.13.0 系统概述

1.1 项目定位

OpenCV(Open Source Computer Vision Library)是以 C++ 为核心的跨平台计算机视觉基础库。
它用统一的数据结构和 API 覆盖图像处理、几何视觉、视频分析、传统机器学习与神经网络推理,
并通过模块化构建、运行时后端和多级优化适配桌面、服务器、移动端与嵌入式平台。

本篇分析对象是 OpenCV 4.13.0
源码中的版本宏位于:

1
modules/core/include/opencv2/core/version.hpp

其中 CV_VERSION_MAJORCV_VERSION_MINORCV_VERSION_REVISION
分别为 4130CV_VERSION_STATUS 为空。
运行时可使用 cv::getVersionString() 获取版本,
使用 cv::getBuildInformation() 获取本次构建的模块、依赖、CPU 特性和后端信息。

1.2 许可证与再发布边界

源码根目录 LICENSE 是 Apache License 2.0 全文,
因此 OpenCV 4.13.0 主体按 Apache License 2.0 授权。

工程使用时仍应区分三个层面:

层面 核验内容
OpenCV 主体 根目录 LICENSE 和源文件头部声明
随源码分发的第三方组件 3rdparty/ 下各组件自己的许可证与通知
系统或外部依赖 FFmpeg、GStreamer、Qt、OpenVINO、CUDA 等各自的授权和再分发要求

Apache License 2.0 通常允许使用、修改和再分发,
但要求保留适用的版权、许可证和通知,并包含专利条款。
本文不构成法律意见;产品发布前应按实际启用的组件生成许可证清单。

注意:OpenCV 的许可证不能替代外部编解码器、模型权重、摄像头 SDK
或加速运行时的许可证审查。构建配置不同,最终软件的第三方义务也可能不同。

1.3 核心能力

OpenCV 4.13.0 主仓库提供的主要能力包括:

  • 图像和多维数组表示、内存管理、基础算术与线性代数;
  • 颜色转换、滤波、形态学、阈值、边缘、轮廓和几何变换;
  • JPEG、PNG、TIFF、WebP、OpenEXR、AVIF 等格式的条件式接入;
  • 文件、摄像头、视频流和图像序列的统一输入输出接口;
  • 关键点、描述子、匹配、单应性和多视图几何;
  • 相机标定、PnP、立体匹配和三维重建基础算法;
  • 光流、背景建模、卡尔曼滤波与运动分析;
  • 级联检测、二维码等目标检测能力;
  • SVM、决策树、随机森林和神经网络等传统机器学习;
  • 图像拼接的特征、估计、接缝、曝光补偿和融合流水线;
  • ONNX、TensorFlow、Darknet 等模型格式的导入与前向推理;
  • G-API 计算图、流式执行和后端映射;
  • CPU SIMD、并行框架、HAL、IPP、OpenCL 和条件式设备后端。

1.4 能力边界

领域 OpenCV 的职责 不应期待的能力
经典视觉 提供算法、数据结构和组合接口 自动理解所有业务场景
深度学习 导入模型并执行推理 完整训练、分布式训练和实验管理
图像编解码 统一格式 API 任意构建都支持全部格式
视频与相机 统一捕获/写出接口 所有设备属性具有一致语义
GUI 调试和轻量交互 完整桌面 UI 框架
GPU/加速 提供若干计算路径 自动在所有输入上获得加速
三维视觉 标定、几何和部分重建能力 完整 SLAM 或三维引擎
扩展算法 主仓库稳定模块 自动包含额外模块仓库
媒体处理 帧级读写和部分属性控制 完整转码、编辑和封装工作流

OpenCV 的重点是“视觉计算构件”。
它通常与应用框架、媒体系统、模型训练框架、设备 SDK 和部署运行时组合使用。

1.5 源码根目录

以下结构以 OpenCV 4.13.0 发布源码根目录为基准。
目录项承担运行代码、构建、测试、文档或发布支持等不同职责:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
opencv-4.13.0/
├── .github/ # GitHub 工作流、议题和贡献协作配置
├── 3rdparty/ # 可随源码构建的第三方组件
├── apps/ # 命令行工具和交互式应用
├── cmake/ # 依赖探测、平台判断、模块和安装逻辑
├── data/ # 级联分类器等运行数据
├── doc/ # 官方文档与教程源文件
├── hal/ # 可选 HAL 实现与适配层
├── include/ # 全局聚合入口,如 opencv2/opencv.hpp
├── modules/ # OpenCV 功能模块主体
├── platforms/ # Android、Apple、Web、Linux 等构建支持
├── samples/ # C++、Python、DNN、GPU 等示例
├── CMakeLists.txt # 根构建入口
├── CONTRIBUTING.md # 贡献规则
├── COPYRIGHT # 版权说明
├── LICENSE # Apache License 2.0
├── README.md # 上游项目说明
└── SECURITY.md # 安全问题报告政策

发布包、源码归档和版本控制检出可能在隐藏文件或辅助文件上略有差异,
但构建和分析的主要入口如上。

模块内部的常见结构

1
2
3
4
5
6
7
8
9
modules/<module>/
├── include/opencv2/<module>/ # 对外安装的公开头文件
├── src/ # 内部头文件与实现
├── test/ # 正确性、回归和异常测试
├── perf/ # 性能测试
├── samples/ # 模块专属示例,可能不存在
├── misc/ # 绑定、打包或辅助元数据
├── cmake/ # 模块局部的构建逻辑,可能不存在
└── CMakeLists.txt # 模块声明和条件依赖

公开 API 与内部实现并非一一对应。
一个声明可能由多个平台文件、dispatch 单元、OpenCL 内核或插件共同实现。

1.6 模块分层

应用与语言层<br/>C++ / Python / Java / Objective-C / JavaScript接口与适配层<br/>公开头文件、InputArray/OutputArray、生成绑定高级流水线<br/>stitching / objdetect / dnn / gapi视觉算法<br/>imgproc / features2d / calib3d / video / mlI/O 与交互<br/>imgcodecs / videoio / highgui基础层<br/>core / flann优化与平台层<br/>dispatch / HAL / IPP / OpenCL / 并行外部系统<br/>格式库、媒体后端、GUI、设备和计算运行时

这是用于理解的逻辑分层,不是严格的无环分层规范。
例如某些模块具有可选依赖,G-API 和 DNN 也各自维护后端体系。
精确构建关系必须查看模块 CMakeLists.txt

基础数据与运行设施

core 是绝大多数代码的共同底座:

  • MatUMatSparseMat
  • InputArrayOutputArray
  • 标量、向量、点、尺寸、范围等小型类型;
  • 算术、归约、矩阵分解和随机数;
  • 并行接口、TLS、日志和追踪;
  • OpenCL 基础设施;
  • 错误码、异常和构建信息。

flann 提供近似最近邻搜索,常被特征匹配和几何模块使用。

通用视觉算法

imgproc 构成经典视觉主干。
features2dcalib3dvideo 在其上形成特征、几何和时序能力;
ml 主要依赖 core,提供传统机器学习算法。

边界与外部系统

imgcodecsvideoiohighgui 位于 OpenCV 与文件、设备、媒体框架和窗口系统的边界。
它们的公开接口相对稳定,但实际能力最依赖平台和构建配置。

高级图与流水线

stitching 组合多个基础模块形成完整拼接流水线。
dnn 导入并执行神经网络图。
gapi 将运算表达成计算图并映射到执行后端。
三者都不是简单的单函数算法集合。

1.7 cv::Mat 内存模型

头部与数据分离

cv::Mat 对象本身是一个矩阵头部,包含:

  • 类型标志;
  • 维数、每一维大小;
  • 行步长或多维步长;
  • 数据起始、当前视图起始和末端指针;
  • 指向共享管理块 UMatData 的指针;
  • 可选的 MatAllocator

像素或矩阵元素通常位于独立分配的缓冲区中。
因此复制一个 Mat 头部的成本与复制全部像素不同。

Mat A<br/>rows/cols/type/step/dataUMatData<br/>refcount/allocator/origdataMat B:浅拷贝ROI:偏移后的 data共享数据缓冲区

对应声明集中在:

1
modules/core/include/opencv2/core/mat.hpp

常规创建、释放、复制等实现可从以下文件继续跟踪:

1
2
modules/core/src/matrix.cpp
modules/core/src/matrix_operations.cpp

浅拷贝、深拷贝和 ROI

操作 典型语义 是否共享数据
拷贝构造/赋值 复制头部并增加引用计数
row()col()operator()(Rect) 创建子矩阵视图
clone() 分配并复制全部有效元素
copyTo() 向目标复制,可触发目标重分配 通常否
外部指针构造 包装用户缓冲区 由用户保证生命周期

OpenCV 的 Mat 不提供通用写时复制。
两个头部共享缓冲区时,通过任一可写视图修改数据,其他视图都可能看到变化。

引用计数与生命周期

UMatData 中存在 refcounturefcount
分别参与 MatUMat 侧的共享管理。
引用计数的增减是原子操作,但这不意味着对像素的并发读写自动安全。

需要区分:

  • 对象生命周期安全:不同头部释放共享缓冲区时通过引用计数协调;
  • 数据竞争安全:多个线程同时写同一缓冲区仍需应用自行同步;
  • 外部缓冲区安全:用用户指针构造时,OpenCV 通常不接管外部内存释放。

步长与连续性

二维交错图像常见地址计算为:

1
address(y, x) = data + y * step[0] + x * elemSize()

ROI、对齐和外部缓冲区可能使 step[0] 大于一行有效像素字节数。
只有 isContinuous() 为真时,才可把所有元素视为单段连续内存处理。

type() 同时编码元素深度和通道数,例如 CV_8UC3
elemSize() 是一个完整元素的字节数,
elemSize1() 是单通道标量的字节数。

输出分配协议

大多数函数使用 OutputArray 接收输出。
实现常调用目标对象的 create()

  1. 若现有尺寸和类型匹配,可复用缓冲区;
  2. 否则释放旧引用并重新分配;
  3. 输入输出别名是否允许,必须按具体 API 约定判断。

不能假设每次函数调用都新建内存,也不能假设所有函数都支持原地执行。

分配器

MatAllocator 定义分配、释放、映射、上传、下载和复制等接口。
默认 CPU Mat 使用标准分配器;
UMat 可借助分配器和 UMatData 管理主机与设备侧状态。
自定义分配器适合特殊内存,但必须严格满足对齐、生命周期和线程约定。

1.8 UMat 与透明 API

UMat 为 Transparent API(T-API)提供数据载体。
当 OpenCL 可用、被启用且具体函数存在适用内核时,
使用 UMat 的调用可以进入 OpenCL 路径。

主机数据UMat / UMatDataOpenCL 缓冲区与内核getMat()/映射

应避免在流水线中频繁执行 Mat → UMat → Mat
因为上传、下载、映射和同步可能抵消计算收益。
小图、短算子或不支持的类型也可能走 CPU 路径。

UMat 是条件式加速机制,不是独立 GPU 数组 API 的同义词。
是否启用 OpenCL 可通过 cv::ocl 相关接口和运行日志核验。

InputArrayOutputArrayInputOutputArray 是统一接收
MatUMat、向量等容器的代理,而非数据所有者。
从代理取出特定容器时可能发生映射或复制,别名和临时对象生命周期须按具体 API 处理。

1.9 错误模型

C++ 层

OpenCV 使用状态码枚举、断言宏和 cv::Exception 表达错误。
常见入口包括:

  • CV_ErrorCV_Error_
  • CV_AssertCV_DbgAssert
  • cv::error()
  • cv::redirectError()

主要声明位于:

1
2
modules/core/include/opencv2/core/base.hpp
modules/core/include/opencv2/core/utility.hpp

错误通常携带:

  • 数值状态码;
  • 错误文本;
  • 触发函数;
  • 源文件和行号。

在正常启用异常的 C++ 构建中,cv::error() 通常抛出 cv::Exception
应用边界应捕获 const cv::Exception&
并同时记录 what()、输入元数据、版本和构建信息。

1
2
3
4
5
6
7
8
try {
cv::Mat image = cv::imread("input.png");
if (image.empty()) {
throw std::runtime_error("image decode returned empty result");
}
} catch (const cv::Exception& e) {
std::cerr << "OpenCV error: " << e.what() << '\n';
}

返回值与异常并存

并非所有失败都抛异常:

  • imread() 解码失败常返回空 Mat
  • VideoCapture::open()read() 返回 bool
  • 查询属性可能返回特殊值;
  • 某些后端错误仅写日志。

因此必须同时检查返回值、输出是否为空和异常。

断言不是输入校验策略

CV_Assert 主要用于库内部前置条件。
应用对外部文件、网络输入和用户参数仍应主动校验,
不要依赖断言消息构建业务错误协议。

1.10 语言绑定

OpenCV 以 C++ API 为源头,通过模块声明和绑定生成器提供其他语言接口。
模块 CMake 中的 WRAP 列表表示该模块计划参与哪些绑定,
但最终可用性仍受 API 可包装性、平台和构建选项影响。

语言/环境 主要组织位置 特点
C++ 各模块 include/opencv2/ 原生 API,能力最完整
Python modules/python/ 与模块包装元数据 cv2 接口,数组常与 NumPy 协作
Java modules/java/ 与生成规则 JNI 包装,需关注原生对象释放
Objective-C modules/objc/WRAP objc 面向 Apple 平台
JavaScript platforms/js/WRAP js 通常基于 Emscripten/WASM,模块受裁剪

Python 绑定常将 C++ 异常转换为 cv2.error
Java 包装持有原生资源时需要遵循对应生命周期接口。
JavaScript 构建通常只包含显式白名单中的能力。

WRAP python 不表示所有重载都能原样出现在 Python。
模板、指针、回调和复杂容器可能需要专门包装或根本不导出。

1.11 构建与产物概览

CMakeLists.txt 负责:

  1. 检查平台、编译器和最低依赖版本;
  2. 建立构建选项;
  3. 探测 CPU 特性和第三方库;
  4. 扫描模块并解析依赖;
  5. 生成配置头、模块目标、绑定、测试和安装规则;
  6. 输出构建摘要。

典型产物包括:

  • opencv_coreopencv_imgproc 等模块库;
  • 可选的单体 opencv_world
  • Python/Java 等绑定;
  • 视频、GUI 或并行后端插件;
  • 工具、示例和测试程序;
  • CMake 包配置和 pkg-config 元数据(按配置生成)。

源码支持、构建启用、产物存在和运行时选中是四个不同状态。

1.12 源码阅读路线

路线 A:应用开发

  1. 掌握 Mat 的类型、步长、ROI 和复制语义;
  2. 跑通 imgcodecs → imgproc → highgui/imgcodecs
  3. 建立返回值和异常的双重检查;
  4. 再进入特征、标定、视频或 DNN 专题。

路线 B:定位一个 API

  1. modules/<module>/include/ 找声明;
  2. 在模块 CMakeLists.txt 确认依赖和条件;
  3. src/ 找同名函数或类方法;
  4. 跟踪 dispatch.cppsimd.hpp、HAL 或 OpenCL 分支;
  5. 阅读 test/ 确认行为;
  6. 阅读 perf/ 确认主要数据规模。

路线 C:平台适配

  1. 阅读根 CMake 和 cmake/ 中的平台探测;
  2. 区分内建后端与插件后端;
  3. 明确外部库版本、链接方式和部署目录;
  4. 用构建信息确认能力;
  5. 在目标设备验证格式、摄像头、窗口和加速路径。

路线 D:性能优化

  1. 测量端到端和单算子基线;
  2. 检查不必要的深拷贝、布局转换和同步;
  3. 查看 CPU dispatch、HAL、IPP、OpenCL 或设备后端;
  4. 验证线程数和并行后端;
  5. 同时检查速度、内存、精度和冷启动。

1.13 阅读时的注意事项

  • 不要仅凭头文件判断实际实现;
  • 不要仅凭 WITH_* 选项判断依赖已找到;
  • 不要把 HAVE_* 宏跨构建环境外推;
  • 不要假设 ROI 连续;
  • 不要把引用计数安全等同于数据线程安全;
  • 不要假设所有后端接受完全相同的属性;
  • 不要把 DNN 后端偏好当成不回退的强制契约;
  • 不要忽略首次初始化和数据搬运成本;
  • 不要用主仓库结论覆盖额外模块;
  • 不要在版本升级后沿用未经核验的源码路径。

1.14 后续阅读

  • 模块依赖、数据流、插件和执行路径:02_系统架构.md
  • 主要模块内部实现:03_核心模块详解.md
  • 按业务任务组合算法:04_算法流水线.md
  • HAL、SIMD、并行与加速:05_HAL与性能优化.md
  • 构建、调试、测试和部署:06_配置与使用.md
  • API 与实现文件定位:07_源码文件索引.md

02 OpenCV 4.13.0 系统架构

02 OpenCV 4.13.0 系统架构

2.1 架构不是一张模块图

OpenCV 的实际行为由多套机制叠加决定:

  1. 模块依赖:哪些 OpenCV 库可以参与构建;
  2. 外部依赖:哪些格式、设备、GUI 和加速能力被发现;
  3. 数据模型MatUMat、数组代理和张量怎样流转;
  4. 实现分派:通用 C++、SIMD、HAL、IPP、OpenCL 等如何选择;
  5. 后端注册:VideoIO、HighGUI、DNN、G-API 如何发现实现;
  6. 产物组织:分模块库、插件或 opencv_world 如何部署;
  7. 调用参数:数据类型、尺寸、后端偏好和设备状态如何影响单次执行。

因此,“OpenCV 支持某功能”至少要拆成:
源码有实现、CMake 找到依赖、实现进入产物、部署完整、运行时成功选中五个问题。

2.2 模块依赖语义

OpenCV 模块通常在 modules/<module>/CMakeLists.txt 中通过
ocv_add_module()ocv_define_module() 声明。

依赖可分为:

类型 典型写法 缺失时的结果
必需 OpenCV 模块 位置参数或 REQUIRED 后的模块 当前模块通常不能正常构建
可选 OpenCV 模块 OPTIONAL 后的模块 当前模块仍可构建,但部分 API/实现关闭
私有外部链接 PRIVATELINK_PRIVATE 影响实现,不传播为公共接口要求
包装目标 WRAP python java ... 决定绑定生成意图,不是算法依赖
条件功能 if(HAVE_*)if(WITH_*) 仅满足配置条件时编译

WITH_* 通常表达“用户希望启用”,
HAVE_* 通常表达“配置阶段确认可用”。
两者不能混用:设置 WITH_FFMPEG=ON 不保证最终 HAVE_FFMPEG 成立。

2.3 核验过的主干依赖

下表依据 OpenCV 4.13.0 各模块 CMake 声明整理:

模块 必需 OpenCV 依赖 可选 OpenCV 依赖 说明
core 无其他基础模块 cudev 全库底座;声明多语言包装
imgproc core 经典图像处理主干
imgcodecs imgproc 格式能力由外部库决定 依赖会传递到 core
videoio imgprocimgcodecs 媒体后端由平台/外部库决定 支持内建和插件实现
highgui imgproc imgcodecsvideoio Android 与其他平台包装声明略有差异
features2d imgproc flann 调试配置还可引入 highgui
calib3d imgprocfeatures2dflann LAPACK 是可探测的外部增强 标定和多视图几何
video imgproc calib3ddnn 部分跟踪器依赖 DNN
objdetect coreimgproccalib3d dnn DNN 缺失时相关能力条件编译
dnn coreimgproc 多种计算后端 DNN CUDA 还要求 CUDA、cuBLAS、cuDNN
stitching imgprocfeatures2dcalib3dflann CUDA 模块和额外特征模块 高级组合模块
gapi imgproc,以及内部图基础 ade videocalib3d 和推理/流式后端 找不到 ade 时模块会禁用
world core 起始并聚合选中模块 内容取决于整体构建 不是独立算法层

表中的“可选”不表示不重要。
例如 video 缺少 dnn 仍可构建,但若干基于模型的跟踪器不会进入可用接口。

2.4 外部依赖:必需与可选

构建系统的基础要求

OpenCV 根工程由 CMake 驱动,并以 C 和 C++ 项目配置。
可工作的 C/C++ 工具链、平台标准库和 CMake 是构建基础。
Python、Java、Ant、NumPy 等只在生成相应绑定或工具时需要。

常见可选依赖

能力域 代表依赖 缺失后的典型影响
JPEG libjpeg-turbo 或 JPEG 库 JPEG 读写不可用
PNG libpng/libspng 与 zlib PNG 读写不可用
TIFF libtiff TIFF 读写不可用
JPEG 2000 OpenJPEG/Jasper 对应格式不可用或受策略限制
WebP/AVIF/JPEG XL 对应格式库 对应格式不可用
OpenEXR OpenEXR EXR 能力关闭或受运行策略限制
医学/地理影像 GDCM/GDAL 专用格式和元数据能力关闭
视频文件/流 FFmpeg、GStreamer 对应容器、协议和编解码路径不可用
摄像头 V4L2、MSMF、AVFoundation 等平台 API 对应设备后端不可用
GUI Qt、GTK、Wayland、Win32、Cocoa 等 imshow 等能力受限或不可用
并行 TBB、OpenMP、平台并发框架 退回其他并行后端或串行路径
数值库 LAPACK 等 部分数值实现无法使用外部优化
DNN CPU/图后端 Protobuf、OpenVINO 等 模型格式或执行后端受限
DNN CUDA CUDA Toolkit、cuBLAS、cuDNN CUDA DNN 后端不可构建
OpenCL OpenCL 头、加载机制和运行时 T-API/OpenCL 路径不可用

有些第三方库可使用系统版本,也可构建 3rdparty/ 中的副本;
具体策略由 CMake 选项和平台决定。

“必需”是相对于目标能力

core + imgproc 最小构建而言,FFmpeg 不是必需依赖;
对“必须读取 H.264 MP4”的产品需求而言,某个能完成该任务的视频后端就是业务必需依赖。
架构评审应同时记录“模块构建必需”和“产品功能必需”。

2.5 从 API 到实现

公开声明通常位于 modules/<module>/include/opencv2/<module>/
入口实现通常位于 src/*.cpp*.dispatch.cpp*.simd.hpp
opencl/*.cl 分别是 CPU 分发、向量化主体和 OpenCL 内核的重要线索。
入口通常先校验参数并创建输出,再按数据条件选择通用、优化或外部后端。

典型调用链:GaussianBlur

cv::GaussianBlur 的公开接口属于 imgproc
4.13.0 的主要入口位于:

1
modules/imgproc/src/smooth.dispatch.cpp

调用链可概括为:

cv::GaussianBlur参数、核大小、边界类型校验"适用 OpenCL/专用路径?"OpenCL 或专用实现"HAL/IPP 等可处理?"优化实现CPU 滤波引擎/dispatchdst

具体选择受输入深度、通道、核大小、边界类型、输出对象种类和构建宏影响。
不能把该图理解成每次都按固定顺序执行全部判断。

典型调用链:imread

cv::imread() 的公开声明在 opencv2/imgcodecs.hpp
实现入口位于:

1
modules/imgcodecs/src/loadsave.cpp

该文件中的 ImageCodecInitializer 保存已注册解码器和编码器,
findDecoder() 通过读取文件签名字节选择解码器,而不是只信任扩展名。

格式库ImageDecoder解码器集合imread/loadsave.cpp应用格式库ImageDecoder解码器集合imread/loadsave.cpp应用imread(filename, flags)findDecoder(filename)比较文件签名新解码器实例readHeader()创建目标 MatreadData()调用对应格式实现像素数据

imwrite() 则主要根据文件扩展名选择编码器。
读取失败常返回空 Mat,应用必须检查 empty()
参数错误或内部断言也可能抛出 cv::Exception

典型调用链:VideoCapture

核心入口位于:

1
2
3
modules/videoio/src/cap.cpp
modules/videoio/src/videoio_registry.cpp
modules/videoio/src/backend_plugin.cpp

VideoCapture::open() 根据输入类型和 apiPreference
遍历支持“按索引捕获”“按文件名捕获”或“按流捕获”的后端。
注册表维护后端 ID、名称、优先级和工厂。

VideoCapture::open"指定 apiPreference?"过滤并排序注册后端获取内建或插件工厂逐个尝试 create/open"打开成功?"保存 IVideoCaptureread()grab()retrieve(OutputArray)

read()cap.cpp 中组合 grab()retrieve()
成功打开不保证每个属性均可设置,也不保证属性单位在所有后端一致。

运行时可通过以下配置影响 VideoIO:

  • OPENCV_VIDEOIO_PRIORITY_LIST:提高列出的后端优先级;
  • OPENCV_VIDEOIO_PRIORITY_<name>:调整或以 0 禁用某后端;
  • OPENCV_VIDEOIO_PLUGIN_PATH:补充插件搜索路径。

环境配置必须在相关注册表初始化前设置,并应结合日志验证。

2.6 Mat 数据流

典型 CPU 图像流水线如下:

关键数据语义:

  • 解码器创建并填充目标 Mat
  • ROI 可能共享原缓冲区且不连续;
  • OutputArray::create() 可复用匹配的目标内存;
  • 通道顺序、色彩空间和深度必须显式管理;
  • 某些算法允许原地计算,另一些不允许;
  • 跨模块传递 Mat 通常不复制像素,但类型转换和布局转换会复制。

2.7 UMat 数据流

当输入或输出是 UMat 时,支持 Transparent API 的实现可使用 OpenCL:

高效用法是让一串兼容算子持续处理 UMat
尽量推迟 getMat() 或下载。

以下情况可能破坏收益:

  • 每个算子后都转回 Mat
  • 输入很小,内核启动成本占主导;
  • 算子或数据类型没有 OpenCL 实现;
  • 主机访问触发同步;
  • OpenCL 运行时不可用或被禁用;
  • OpenCL 路径内部因条件不满足回退。

MatUMat 可以通过共同的数组代理进入相同 API,
但这不代表内部存储位置和同步成本相同。

2.8 I/O 与插件架构

imgcodecsHAVE_* 条件接入格式实现;
读取通常以文件签名选解码器,写入通常以扩展名选编码器。
OpenEXR 和 Jasper 等能力还可能受运行策略或强制选项影响。

VideoIO 插件与注册

modules/videoio/CMakeLists.txt 默认在多数桌面平台允许插件,
并提供:

  • VIDEOIO_ENABLE_PLUGINS
  • VIDEOIO_PLUGIN_LIST
  • opencv_videoio_plugins 聚合目标。

FFmpeg、GStreamer、Media SDK/oneVPL、MSMF 等可按配置成为插件或内建实现。
注册表对不同输入形态维护可用后端列表,并按优先级选择。

部署时要同时考虑:

  1. OpenCV 主库;
  2. VideoIO 插件;
  3. 插件依赖的第三方动态库;
  4. 操作系统设备权限;
  5. 网络协议、容器和编解码器实际支持;
  6. ABI/API 兼容性。

HighGUI 后端

highgui 的模块必需依赖是 imgproc
imgcodecsvideoio 为可选模块依赖。
实现由平台和 CMake 探测选择 Qt、GTK、Wayland、Win32、Cocoa、
Framebuffer 等路径,并支持部分 UI 插件机制。

主要入口和后端组织位于:

1
2
3
modules/highgui/src/window.cpp
modules/highgui/src/backend.cpp
modules/highgui/src/window_*.cpp

OPENCV_UI_BACKEND 可请求特定 UI 后端,
但目标后端必须已构建且能成功初始化。
无头服务器上 imshow() 失败通常是部署环境问题,不是图像算法问题。

2.9 DNN 架构

dnn 必需依赖 coreimgproc
其工作可拆成模型导入、内部图、内存/张量、层实现和执行后端。

主要 API 入口与实现:

1
2
3
4
modules/dnn/include/opencv2/dnn/dnn.hpp
modules/dnn/src/net.cpp
modules/dnn/src/net_impl.cpp
modules/dnn/src/layers/

Net::setPreferableBackend()setPreferableTarget() 只表达偏好组合。
是否成功取决于:

  • 后端是否进入构建;
  • 运行时和设备是否存在;
  • 模型每个算子是否受支持;
  • 数据类型、动态形状和精度是否兼容;
  • 回退策略是否允许;
  • 后端初始化是否成功。

DNN CUDA 后端的 CMake 条件明确要求 CUDA、cuBLAS 和 cuDNN。
仅启用 CUDA 基础模块不足以保证 DNN CUDA 可用。

2.10 G-API 架构

G-API 使用 GMatGScalar 等描述计算,
先构建图,再编译并执行。

GMat/GScalar 操作表达式内部图元数据推导与编译 Pass内核包与后端匹配CPU / Fluid / OCL / Streaming / 推理后端批处理或流式结果

modules/gapi/CMakeLists.txt 明确要求 ade 目标;
缺少它时模块会被禁用。
G-API 必需依赖 imgproc,可选依赖 videocalib3d
另外按构建接入 OpenVINO、GStreamer、oneVPL 等能力。

G-API 的优势来自图级信息:

  • 合并或重排可执行阶段;
  • 选择不同内核包;
  • 构建流式处理;
  • 统一管理异构后端。

代价是需要显式描述图、编译参数和后端内核,
并非所有立即执行 API 都能自动转换。

2.11 opencv_world

modules/world/CMakeLists.txt 遍历被标记为 IS_PART_OF_WORLD 的已选模块,
收集其头文件、源文件和链接依赖后生成 opencv_world

它带来的变化是:

  • 应用侧链接库数量减少;
  • 模块符号聚合到一个产物;
  • 部署时仍可能需要插件和外部动态库;
  • 静态链接仍需处理传递依赖;
  • 未启用或被排除的模块不会自动出现;
  • 模块逻辑边界和命名空间不会因此消失。

world 是构建产物策略,不是比模块库多一套算法实现。

2.12 构建时选择

构建时决定:

  • BUILD_LISTBUILD_opencv_* 选择的模块;
  • 共享库或静态库;
  • 是否生成 opencv_world
  • CPU baseline 与 dispatch 指令集;
  • 是否启用 OpenCL、IPP、并行框架;
  • 找到哪些图像、视频、GUI 和 DNN 依赖;
  • 哪些后端内建,哪些生成插件;
  • 生成哪些语言绑定、测试和示例。

配置摘要是架构证据,应随二进制归档。

2.13 运行时选择

运行时还会继续决策:

时机 选择内容
进程初始化 CPU 能力、日志、线程和全局配置
首次使用模块 注册表、插件发现、设备上下文和缓存
打开媒体 后端优先级、输入类型和参数
单次图像调用 类型、尺寸、连续性、输出种类和优化条件
DNN 网络执行 后端、目标、算子支持和回退
UMat 调用 OpenCL 可用性、内核支持和同步状态

选择结果可能受环境变量、动态库搜索路径、设备权限和驱动改变。
可重复部署必须控制这些外部条件。

2.14 端到端典型链:相机预处理与 DNN

HighGUI/输出DNNImgprocVideoIO应用HighGUI/输出DNNImgprocVideoIO应用loop[每帧]VideoCapture::open(index, preference)注册表选择设备后端read(frame)Mat/BGRresize/cvtColor 或 blobFromImage预处理数据Net::setInput(blob)Net::forward()后端/目标执行与必要回退输出张量解码、缩放坐标、绘制imshow 或 VideoWriter::write

该链路中最常见的架构问题是:

  • 捕获后端输出格式不符合预期;
  • BGR/RGB、NCHW/NHWC、缩放和均值设置错误;
  • 每帧重复分配或上传下载;
  • DNN 后端未实际启用;
  • GUI 阻塞或服务器无显示后端;
  • 视频时间戳和处理速度不匹配。

2.15 架构排错顺序

定位某项能力时建议按以下顺序:

  1. 确认运行时加载的 OpenCV 版本;
  2. 保存 cv::getBuildInformation()
  3. 确认模块已进入构建;
  4. 核对模块必需和可选依赖;
  5. 找到公开声明和入口实现;
  6. 检查 WITH_*HAVE_* 和条件编译;
  7. 确认插件与第三方动态库部署;
  8. 开启相关日志,记录后端枚举和选择;
  9. 检查输入类型、布局、连续性和生命周期;
  10. 用最小用例区分配置、数据和算法问题;
  11. 阅读模块 test/ 的边界条件;
  12. 最后再做性能和精度比较。

2.16 注意事项

  • 模块 CMake 是依赖真相的重要来源,但最终目标仍受全局配置修改;
  • 格式扩展名存在不代表对应解码器已构建;
  • VideoIO 的同名属性在不同后端可能语义不同;
  • 插件加载成功不代表其第三方依赖和设备初始化成功;
  • Mat 浅拷贝会让跨阶段修改互相可见;
  • UMat 映射回主机通常是同步点;
  • DNN 指定后端不代表所有层都由该后端执行;
  • G-API 编译图的成本应与重复执行次数一起评估;
  • opencv_world 不消除插件和外部库依赖;
  • 性能结论必须基于目标二进制、目标设备和真实数据。

2.17 后续阅读建议

理解本篇后,可继续:

  • 03_核心模块详解.md 查看模块内部职责;
  • 04_算法流水线.md 查看更多任务级组合;
  • 05_HAL与性能优化.md 深入实现分派;
  • 06_配置与使用.md 将依赖和后端落到构建命令;
  • 07_源码文件索引.md 快速定位声明、实现、测试和性能文件。

OpenCV 4.13.0 核心模块手册

OpenCV 4.13.0 核心模块手册

1. 手册范围与源码阅读约定

本文面向使用、调试和二次开发 OpenCV 4.13.0 的工程人员。
内容以 OpenCV 4.13.0 主仓库源码为准,不把 opencv_contrib 中的扩展模块混入主库能力。
文中路径均相对于 OpenCV 源码根目录。
17 个模块按同一组问题展开:模块解决什么问题、公开接口在哪里、内部怎样分层、数据怎样进入和离开、性能由谁决定,以及应从哪些文件开始阅读。

源码阅读建议遵循以下顺序:

  1. 阅读 modules/<module>/CMakeLists.txt,确认强依赖、可选依赖和条件编译项。
  2. 阅读 modules/<module>/include/opencv2/,公开头文件才是稳定使用边界。
  3. 从公开 API 名称反查 modules/<module>/src/,定位调度层和通用实现。
  4. 检查 modules/<module>/test/,测试比注释更能说明空输入、类型和边界行为。
  5. 检查 modules/<module>/perf/,理解热点参数、基准尺寸和优化目标。
  6. 遇到 .dispatch.cpp.simd.hpp、OpenCL 或 CUDA 文件时,先区分基线实现与加速实现。
  7. 不要把“头文件中存在”理解为“当前构建一定可用”;很多后端受 CMake 配置和外部库影响。

常见数据约定:

  • InputArrayOutputArray 是适配层,可接收 Mat、部分 UMat、向量或数组集合。
  • Mat 是带步长的引用计数视图;ROI 通常不连续,不能默认 step == cols * elemSize()
  • UMat 允许透明 API 走 OpenCL,但并不保证每个算子都留在设备端。
  • 默认彩色图像通常采用 BGR 通道顺序,而不是 RGB。
  • 许多几何 API 接受 floatdouble;整数点会丢失亚像素精度。
  • Python 绑定由头文件注解生成,但某些 C++ 重载、模板和内部类不会原样暴露。

2. core:数据结构、运行时与数值基础

2.1 定位

core 是几乎所有 OpenCV 模块的基础依赖。
它提供矩阵容器、数组适配、标量与几何类型、内存管理、数值运算、并行框架、硬件能力检测、持久化和透明加速基础。
如果算法问题最终表现为类型、步长、引用计数、线程或分发问题,应先回到 core

2.2 关键公开类与 API

  • 数据对象:cv::Matcv::UMatcv::SparseMatcv::MatExpr
  • 类型与容器:ScalarPoint_Size_Rect_VecMatxRange
  • 抽象参数:InputArrayOutputArrayInputOutputArray 及数组集合版本。
  • 生命周期与扩展:AlgorithmPtrMatAllocator
  • 线性代数:gemmsolveinverteigenSVDecompPCASVD
  • 数组运算:addmultiplynormalizereducesplitmergeLUTminMaxLoc
  • 频域与随机:dftdctRNGrandurandnkmeans
  • 运行时:parallel_for_setNumThreadsgetBuildInformationcheckHardwareSupport
  • 持久化:FileStorageFileNode,支持 XML、YAML 和 JSON。

2.3 内部子系统与主要源码

  • modules/core/src/matrix.cppmatrix_operations.cppMat 分配、复制、表达式和常见操作。
  • modules/core/src/umatrix.cppUMat 生命周期、映射和设备/主机同步。
  • modules/core/src/arithm.dispatch.cpp:算术运算及运行时 CPU 分发。
  • modules/core/src/matmul.dispatch.cppmatrix_decomp.cpp:矩阵乘法与分解。
  • modules/core/src/alloc.cpp:对齐分配与内存接口。
  • modules/core/src/system.cpp:构建信息、硬件检测、错误和时间工具。
  • modules/core/src/parallel.cppparallel_impl.cpp:并行循环与后端适配。
  • modules/core/src/ocl.cppopencl/:OpenCL 上下文、程序缓存和内核。
  • modules/core/src/persistence*.cpp:配置序列化与格式解析。
  • modules/core/include/opencv2/core/hal/:供上层算子调用的 HAL 契约。

2.4 输入输出约束

  • Mat::type() 同时编码深度与通道数;CV_8UC3 不是三个独立矩阵。
  • 浅拷贝只增加引用计数;需要独立数据时使用 clone()copyTo()
  • reshape() 通常只改头信息,不重排元素;总元素标量数必须保持一致。
  • 原地运算是否安全取决于具体 API,不能由 InputOutputArray 名称之外自行推断。
  • 掩码一般要求 CV_8U 单通道,并与被处理数组的空间尺寸一致。
  • solveinvert 的数值可靠性依赖分解方法、条件数和输入深度。

2.5 执行与后端特点

  • CPU 路径可能经过编译期优化、运行时 SIMD 分发、IPP、HAL 或第三方线性代数库。
  • setUseOptimized(false) 可辅助对比基线实现,但不等于关闭所有外部后端。
  • parallel_for_ 的具体实现可能是内置线程池、TBB、OpenMP 或平台框架。
  • UMat 只有在 OpenCL 可用且算子实现支持时才有收益;频繁 getMat() 会触发同步。
  • 小矩阵上调度、分配和同步成本可能高于加速收益。

2.6 常见误区与阅读入口

  • 误区:把 ROI 当连续内存;应检查 isContinuous() 并尊重 step
  • 误区:依赖 Mat 离开作用域后仍保留外部裸指针;引用关系必须清晰。
  • 误区:认为多线程设置会让每个算法线性加速;内存带宽和算法内部并行度会限制收益。
  • 推荐先读 modules/core/include/opencv2/core/mat.hppmodules/core/include/opencv2/core.hpp
  • 再沿 matrix.cpparithm.dispatch.cppsystem.cppparallel_impl.cpp 阅读一次完整调用链。

3. imgproc:二维图像处理主体

3.1 定位

imgproc 覆盖颜色转换、滤波、几何变换、形态学、边缘、轮廓、直方图、分割和绘制。
它处在解码、视频采集之后,也常处在特征、标定、检测和 DNN 之前。

3.2 关键公开类与 API

  • 颜色:cvtColorcvtColorTwoPlanedemosaicingapplyColorMap
  • 滤波:filter2DsepFilter2DGaussianBlurmedianBlurbilateralFilter
  • 梯度与边缘:SobelScharrLaplacianCanny
  • 几何:resizewarpAffinewarpPerspectiveremapwarpPolar
  • 形态学:erodedilatemorphologyExgetStructuringElement
  • 二值与区域:thresholdadaptiveThresholdfloodFillconnectedComponentsWithStats
  • 形状:findContoursapproxPolyDPconvexHullmomentsfitEllipse
  • 检测与分割:HoughLinesPHoughCirclesmatchTemplatewatershedgrabCut
  • 直方图:calcHistcalcBackProjectequalizeHistCLAHE

3.3 内部子系统与主要源码

  • modules/imgproc/src/color.cppcolor_*.dispatch.cpp:颜色空间调度与实现。
  • modules/imgproc/src/filter.dispatch.cppbox_filter.dispatch.cpp:卷积和可分离滤波。
  • modules/imgproc/src/imgwarp.cpp:缩放、仿射、透视和重映射。
  • modules/imgproc/src/morph.dispatch.cpp:腐蚀、膨胀及形态学组合。
  • modules/imgproc/src/canny.cpphough.cpp:边缘和霍夫变换。
  • modules/imgproc/src/thresh.cpphistogram.cpp:阈值与直方图。
  • modules/imgproc/src/contours_new.cppconvhull.cpp:轮廓和几何形状。
  • modules/imgproc/src/connectedcomponents.cpp:连通域标记。
  • modules/imgproc/src/segmentation.cppgrabcut.cpp:分割算法。
  • modules/imgproc/src/opencl/:部分透明 API 的 OpenCL 内核。

3.4 输入输出约束

  • 颜色转换必须明确源格式;相同的三通道字节可被解释为 BGR、RGB、HSV 或 YUV。
  • 几何变换的 dsize 顺序是宽、高;矩阵坐标按列为 x、行为 y。
  • 插值适用于连续值,标签图和掩码通常应使用 INTER_NEAREST
  • findContours 主要接收 8 位单通道二值图;层级结构由检索模式决定。
  • watershed 的标记图要求 CV_32S,并会原地写回边界标记。
  • filter2Dddepth=-1 保持源深度,可能出现饱和截断。

3.5 执行与后端特点

  • 热点算子常通过 HAL、IPP、SIMD、OpenCL 或特定库分发。
  • 固定小核、可分离核和通用卷积走的路径可能不同。
  • remap 可用 convertMaps 预转换映射,适合重复处理同一几何关系。
  • 边界模式直接影响数值结果,BORDER_DEFAULT 不是所有算子的同一种数学外延。
  • 大图流水线应尽量复用输出缓冲,避免每步重新分配。

3.6 常见误区与阅读入口

  • 误区:对深度图、类别图使用普通线性缩放,造成无意义中间值。
  • 误区:混淆阈值返回值与输出图;threshold 返回实际使用的阈值。
  • 误区:轮廓坐标忽略 ROI 偏移;应使用 offset 或恢复全图坐标。
  • 推荐从 modules/imgproc/include/opencv2/imgproc.hpp 按功能组阅读。
  • 性能排查优先查看对应 .dispatch.cppopencl/perf/ 用例。

4. imgcodecs:静态图像编解码

4.1 定位与公开 API

imgcodecs 将文件或内存字节流转换为像素矩阵,也负责反向编码。
主要 API 是 imreadimreadmultiimdecodeimwriteimwritemultiimencode
辅助 API 包括 haveImageReaderhaveImageWriterimcountImageCollection
读取标志控制灰度/彩色、原深度、方向处理和缩放版本。
写入参数使用成对整数序列,参数语义由格式决定。

4.2 内部子系统与主要源码

  • modules/imgcodecs/src/loadsave.cpp:统一入口、编解码器选择、文件和内存适配。
  • modules/imgcodecs/src/grfmt_base.*grfmts.hpp:编解码器基类与注册集合。
  • modules/imgcodecs/src/grfmt_jpeg.cppgrfmt_png.cppgrfmt_tiff.cpp:常用格式。
  • modules/imgcodecs/src/grfmt_webp.cppgrfmt_avif.cppgrfmt_jpegxl.cpp:现代格式适配。
  • modules/imgcodecs/src/grfmt_exr.cppgrfmt_hdr.cpp:高动态范围格式。
  • modules/imgcodecs/src/exif.cpp:EXIF 方向等元数据处理。

4.3 约束、后端与误区

  • imread 失败返回空 Mat,调用方必须检查 empty()
  • 解码结果通常是 BGR/BGRA;位深和通道还受读取标志及编解码器能力影响。
  • imdecode 输入是连续字节缓冲,不是已解压像素。
  • 编解码能力取决于构建时发现的 JPEG、PNG、TIFF、OpenEXR、WebP 等库。
  • 扩展名常用于写入格式选择;读取侧还会检查签名字节。
  • 超大或恶意图片可能引发高内存占用,外部输入应设置尺寸和资源限制。
  • 误区:以为写入浮点矩阵到任意格式都能保留浮点精度;应核对目标格式。
  • 误区:忽略 EXIF 方向导致宽高和像素朝向与原始存储不一致。
  • 推荐入口:公开头 modules/imgcodecs/include/opencv2/imgcodecs.hpp,实现入口 loadsave.cpp

5. videoio:视频、相机与媒体后端统一层

5.1 定位与公开 API

videoio 统一视频文件、图像序列、相机、网络流和视频写出。
核心类是 VideoCaptureVideoWriter 和自定义流接口 IStreamReader
常用操作包括 openisOpenedreadgrabretrievegetsetwrite
videoio_registry 命名空间可查询已注册后端、相机后端和流后端。
CAP_PROP_*VIDEOWRITER_PROP_*VideoAccelerationType 描述跨后端属性。

5.2 内部子系统与主要源码

  • modules/videoio/src/cap.cppVideoCaptureVideoWriter 门面和后端选择。
  • modules/videoio/src/videoio_registry.cpp:后端注册、优先级与能力查询。
  • modules/videoio/src/backend_plugin.cpp:插件后端装载。
  • modules/videoio/src/cap_ffmpeg.cppcap_ffmpeg_impl.hpp:FFmpeg 适配。
  • modules/videoio/src/cap_gstreamer.cpp:GStreamer 管线适配。
  • modules/videoio/src/cap_v4l.cppcap_msmf.cppcap_avfoundation.mm:平台采集。
  • modules/videoio/src/cap_images.cpp:图像序列后端。
  • modules/videoio/src/cap_mjpeg_decoder.cppcap_mjpeg_encoder.cpp:内置 Motion JPEG 路径。

5.3 约束、后端与误区

  • read 合并 grabretrieve;多相机同步时可先分别 grabretrieve
  • 属性是后端能力请求,不保证 set 成功,也不保证读取值等于请求值。
  • 帧通常输出 BGR,但原始模式、深度相机和硬件解码可能返回其他布局。
  • FPS、帧号和时间戳在可变帧率、实时流及某些容器上可能不精确。
  • fourcc、封装格式、编码器和像素格式是不同概念。
  • FFmpeg、GStreamer、V4L2、MSMF、AVFoundation 等是否可用由构建和运行环境共同决定。
  • 硬件加速需要后端、设备和编解码器三方同时支持,不能只设置一个属性。
  • 误区:用无限阻塞的 read 充当可靠超时机制;实时系统应设计中断与重连。
  • 推荐入口:modules/videoio/include/opencv2/videoio.hppcap.cppvideoio_registry.cpp

6. highgui:窗口、事件与轻量交互

6.1 定位与公开 API

highgui 提供调试和轻量工具所需的窗口、键鼠事件、轨迹条和按钮接口。
主要 API 是 namedWindowimshowwaitKeywaitKeyExpollKeydestroyWindow
交互 API 包括 setMouseCallbackcreateTrackbarsetTrackbarPosselectROI
它不是完整 GUI 应用框架,也不负责图像编解码。

6.2 内部子系统与主要源码

  • modules/highgui/src/window.cpp:公共窗口 API 与兼容逻辑。
  • modules/highgui/src/backend.cpp:现代 UI 后端抽象和选择。
  • modules/highgui/src/window_gtk.cppwindow_QT.cpp:GTK 与 Qt 实现。
  • modules/highgui/src/window_w32.cppwindow_wayland.cpp:Windows 与 Wayland 实现。
  • modules/highgui/src/window_cocoa.mm:macOS Cocoa 实现。

6.3 约束、执行与误区

  • imshow 负责显示转换,但不同深度的映射规则不同;定量检查前应显式归一化。
  • waitKey 不只是等待按键,也驱动多数后端的事件处理。
  • 键码高位具有后端差异;需要完整键码时使用 waitKeyEx
  • GUI API 通常要求在主线程或固定 UI 线程调用,跨线程行为依平台而异。
  • 无显示服务器、容器或精简构建中,窗口后端可能不可用。
  • OpenGL 窗口能力受构建选项和上下文支持影响。
  • 误区:在生产服务端依赖 imshow;应把可视化与核心计算解耦。
  • 误区:在回调中做长耗时计算,阻塞整个事件循环。
  • 推荐入口:modules/highgui/include/opencv2/highgui.hppwindow.cppbackend.cpp

7. features2d:局部特征检测、描述与匹配

7.1 定位与关键 API

features2d 统一二维关键点、描述子及匹配器,是配准、检索、SLAM 前端和拼接的基础。
抽象基类 Feature2D 提供 detectcomputedetectAndCompute
检测与描述实现包括 SIFTORBBRISKKAZEAKAZE
检测器还包括 FastFeatureDetectorAgastFeatureDetectorGFTTDetectorMSERSimpleBlobDetector
匹配抽象为 DescriptorMatcher,常用实现是 BFMatcherFlannBasedMatcher
辅助接口包括 KeyPointDMatchdrawKeypointsdrawMatchesKeyPointsFilter
词袋接口包括 BOWTrainerBOWKMeansTrainerBOWImgDescriptorExtractor

7.2 内部子系统与主要源码

  • modules/features2d/src/feature2d.cpp:统一接口、序列化和工厂相关逻辑。
  • modules/features2d/src/sift.dispatch.cpporb.cppbrisk.cpp:主要特征实现。
  • modules/features2d/src/kaze/akaze.cpp:非线性尺度空间特征。
  • modules/features2d/src/fast.cppagast.cppgftt.cpp:角点检测。
  • modules/features2d/src/matchers.cpp:暴力与 FLANN 匹配适配。
  • modules/features2d/src/draw.cpp:关键点和匹配可视化。
  • modules/features2d/src/bagofwords.cpp:视觉词袋。

7.3 输入输出约束与执行特点

  • 输入图像通常应为单通道 8 位;部分实现会接受彩色后内部转换,但不应依赖隐式行为。
  • 掩码应为与图像同尺寸的 8 位单通道矩阵。
  • SIFT、KAZE 描述子通常为浮点向量,适配 L2 距离。
  • ORB、BRISK、AKAZE 的二进制描述子通常适配 Hamming 距离。
  • KeyPoint::size 是特征尺度直径,不是半径;angle=-1 表示未计算方向。
  • knnMatch 可能为某些查询返回少于 k 个候选,使用 Lowe 比率前必须检查长度。
  • crossCheck 与 KNN 比率测试是不同筛选策略。
  • 特征提取常受图像金字塔、阈值、最大特征数和边缘区域配置影响。

7.4 常见误区与阅读入口

  • 误区:把二进制描述子转换为 CV_32F 后用 KD-Tree,语义已被破坏。
  • 误区:仅凭描述子距离接受匹配;几何任务还应使用单应或基础矩阵做鲁棒验证。
  • 误区:把关键点顺序当作跨帧稳定 ID;检测结果没有这种保证。
  • 推荐入口:modules/features2d/include/opencv2/features2d.hpp
  • 实现阅读可从 feature2d.cpp、具体算法文件、matchers.cpp 串联。

8. flann:近似最近邻索引

8.1 定位与关键 API

flann 提供高维数据近似最近邻搜索,既可直接使用,也被 FlannBasedMatcher 调用。
公开门面是 cv::flann::Index
索引参数包括 KDTreeIndexParamsKMeansIndexParamsCompositeIndexParamsLshIndexParams
搜索参数由 SearchParams 控制检查次数、近似精度和排序行为。
核心操作是 buildknnSearchradiusSearchsaveload

8.2 内部子系统与主要源码

  • modules/flann/include/opencv2/flann/miniflann.hpp:OpenCV 风格的公开包装。
  • modules/flann/include/opencv2/flann/:索引、距离、矩阵和序列化模板实现。
  • modules/flann/src/miniflann.cppMat 与模板 FLANN 的桥接。
  • modules/flann/src/flann.cpp:C 接口和公共实现汇集。

8.3 约束、执行与误区

  • KD-Tree 等常规索引主要面向 CV_32F 特征和欧氏类距离。
  • LSH 面向二进制描述子;距离和索引类型必须与描述子语义一致。
  • 近似搜索以速度换召回率,checks 越大通常越接近精确结果。
  • 建索引有时间和内存成本,适合被多次查询的数据集。
  • 被索引数据的生命周期和连续性必须满足包装层要求,修改数据后应重建索引。
  • 误区:把 FLANN 结果当确定性全排序;近似算法、随机种子和并行可能影响候选。
  • 推荐入口:miniflann.hppminiflann.cpp,再进入对应索引模板头。

9. calib3d:相机标定与多视图几何

9.1 定位与关键 API

calib3d 处理三维视觉中的相机模型、位姿、极几何、三角化和立体匹配。
标定 API 包括 calibrateCameracalibrateCameraROstereoCalibratefisheye 命名空间。
位姿 API 包括 solvePnPsolvePnPRansacsolvePnPGenericrecoverPose
几何估计包括 findHomographyfindFundamentalMatfindEssentialMat
校正与投影包括 undistortinitUndistortRectifyMapstereoRectifytriangulatePoints
立体匹配类包括 StereoMatcherStereoBMStereoSGBM
标定靶检测包括 findChessboardCornersfindChessboardCornersSB 和圆点阵接口。

9.2 内部子系统与主要源码

  • modules/calib3d/src/calibration.cpp:针孔相机标定与优化。
  • modules/calib3d/src/fisheye.cpp:鱼眼模型。
  • modules/calib3d/src/solvepnp.cppp3p.cppap3p.cppsqpnp.cpp:PnP 算法族。
  • modules/calib3d/src/fundam.cpp:单应、基础矩阵和本质矩阵入口。
  • modules/calib3d/src/usac/:USAC 鲁棒估计框架。
  • modules/calib3d/src/stereo_geom.cppstereosgbm.cppstereobm.cpp:双目几何与匹配。
  • modules/calib3d/src/undistort.dispatch.cpp:去畸变映射。
  • modules/calib3d/src/triangulate.cpp:三角化。
  • modules/calib3d/src/chessboard.cpp:棋盘格检测。

9.3 输入输出约束

  • 世界点与图像点必须一一对应;单位可自定,但平移向量继承同一单位。
  • 相机矩阵通常为 3×3 浮点矩阵,畸变系数长度由模型和标志决定。
  • rvec 是 Rodrigues 旋转向量,不是欧拉角;可用 Rodrigues 转换。
  • solvePnP 不同方法对点数、共面性和初值有不同要求。
  • findEssentialMatrecoverPose 要求相机归一化关系一致。
  • StereoBMStereoSGBM 的视差通常为定点缩放值,解释前应查看输出类型和比例。
  • 三角化输出是齐次坐标,必须除以最后一维并检查数值稳定性。

9.4 执行特点、误区与阅读入口

  • RANSAC/USAC 的阈值处于输入坐标单位中;缩放图像后阈值也应调整。
  • 标定是非线性优化,初值、姿态覆盖、观测噪声和参数约束决定可观测性。
  • 误区:仅看整体重投影 RMS 判断标定质量;还应检查每视图误差和参数合理性。
  • 误区:混淆相机到世界与世界到相机变换,导致旋转和平移方向颠倒。
  • 误区:用单应矩阵解释有明显视差的非平面场景。
  • 推荐入口:modules/calib3d/include/opencv2/calib3d.hppcalibration.cppfundam.cpp

10. video:跨帧运动分析与跟踪

10.1 定位与关键 API

video 负责跨帧算法,不负责读取和写入媒体。
光流 API 包括 calcOpticalFlowPyrLKcalcOpticalFlowFarnebackreadOpticalFlow
抽象与实现包括 SparseOpticalFlowDenseOpticalFlowFarnebackOpticalFlowDISOpticalFlow
背景建模包括 BackgroundSubtractorMOG2BackgroundSubtractorKNN 及创建函数。
状态估计使用 KalmanFilter
目标跟踪包括 TrackerTrackerMILTrackerGOTURNTrackerDaSiamRPNTrackerNanoTrackerVit
区域跟踪还包括 meanShiftCamShift

10.2 内部子系统与主要源码

  • modules/video/src/lkpyramid.cpp:金字塔 Lucas–Kanade 稀疏光流。
  • modules/video/src/optflowgf.cppdis_flow.cpp:Farneback 与 DIS 稠密光流。
  • modules/video/src/bgfg_gaussmix2.cppbgfg_KNN.cpp:背景模型。
  • modules/video/src/kalman.cpp:卡尔曼滤波。
  • modules/video/src/camshift.cpp:MeanShift 与 CamShift。
  • modules/video/src/tracking/:统一 Tracker 及具体实现。
  • modules/video/src/optical_flow_io.cpp.flo 光流文件读写。

10.3 约束、执行与误区

  • LK 光流输入点通常是 Point2f,状态向量标识每个点是否成功。
  • 前后向一致性检查可剔除遮挡、越界和不稳定轨迹。
  • 稠密光流输出通常为双通道 CV_32F,分别表示 x、y 位移。
  • 背景减除器是有状态对象,学习率和历史长度会改变适应速度。
  • Kalman 状态、观测和控制矩阵的维度必须由调用方正确建模。
  • 深度跟踪器可能依赖外部模型文件,且预处理尺寸和模型结构固定。
  • 误区:把 videoio 的丢帧归因于光流;采集和分析应分别测量。
  • 推荐入口:modules/video/include/opencv2/video/tracking.hppbackground_segm.hpp

11. dnn:深度神经网络推理

11.1 定位与关键 API

dnn 导入训练好的网络并执行推理,不提供通用训练框架。
核心对象是 cv::dnn::NetLayerLayerParamsLayerFactory
模型导入入口包括 readNetreadNetFromONNXreadNetFromTensorflowreadNetFromDarknet
预处理包括 blobFromImageblobFromImagesImage2BlobParams
执行包括 setInputforwardforwardAsyncgetUnconnectedOutLayersNames
部署配置包括 setPreferableBackendsetPreferableTarget
后处理包括 NMSBoxesNMSBoxesBatchedsoftNMSBoxes
高层包装包括 ModelClassificationModelDetectionModelSegmentationModelKeypointsModel

11.2 内部子系统与主要源码

  • modules/dnn/src/net.cppnet_impl.cpp:公开门面、网络状态和执行计划。
  • modules/dnn/src/net_impl_fuse.cpp:层融合与图优化。
  • modules/dnn/src/net_impl_backend.cpp:后端初始化和节点映射。
  • modules/dnn/src/layers/:卷积、池化、激活、注意力等 CPU 层实现。
  • modules/dnn/src/onnx/tensorflow/darknet/:模型解析与图转换。
  • modules/dnn/src/ocl4dnn/opencl/:OpenCL 加速。
  • modules/dnn/src/cuda4dnn/cuda/:CUDA 后端。
  • modules/dnn/src/net_openvino.cppop_vkcom.cppop_webnn.cpp:可选后端桥接。
  • modules/dnn/src/nms.cpp:检测框抑制。

11.3 输入输出约束

  • blob 常为 NCHW,但实际输入名、维度、动态形状和数据类型由模型决定。
  • blobFromImage 的缩放、均值、通道交换和裁剪顺序必须匹配训练预处理。
  • 检测输出布局不是统一标准,高层 DetectionModel 也不能覆盖所有自定义模型。
  • Net 的输入缓冲和执行状态不应在无同步保护下被多个线程共享修改。
  • 动态形状、量化算子和控制流支持取决于导入器和目标后端。
  • forward 返回的数据只代表指定输出层;多输出网络应显式请求输出名称。

11.4 执行特点、误区与阅读入口

  • 可选后端包括 OpenCV CPU、OpenCL、CUDA、OpenVINO 等,实际集合由构建决定。
  • 后端不支持的层可能回退、拒绝执行或导致分图,必须通过日志和性能剖析确认。
  • FP16、INT8 能否生效取决于模型、设备、目标和层覆盖率。
  • 首次推理可能包含图初始化、权重转换和内核编译,不宜直接作为稳态延迟。
  • 误区:只改 swapRB 便认为预处理正确;还需核对 resize、letterbox、归一化和布局。
  • 误区:把 NMS 阈值与分类置信阈值混为一谈。
  • 推荐入口:modules/dnn/include/opencv2/dnn/dnn.hppnet_impl.cpp、对应导入器目录。

12. stitching:全景拼接流水线

12.1 定位与关键 API

stitching 将特征、几何估计、投影、曝光、接缝和融合组织为完整全景管线。
高层入口是 Stitcher::createestimateTransformcomposePanoramastitch
模式包括面向旋转相机的 PANORAMA 和面向扫描件的 SCANS
细节层公开 ImageFeaturesMatchesInfoCameraParams
匹配器包括 FeaturesMatcherBestOf2NearestMatcher
运动估计包括 HomographyBasedEstimatorAffineBasedEstimator 和多种 BundleAdjuster
投影、曝光、接缝、融合分别由 RotationWarperExposureCompensatorSeamFinderBlender 抽象。

12.2 内部子系统与主要源码

  • modules/stitching/src/stitcher.cpp:高层状态机和阶段编排。
  • modules/stitching/src/matchers.cpp:图像对匹配和置信度。
  • modules/stitching/src/motion_estimators.cpp:相机估计与光束法平差。
  • modules/stitching/src/warpers.cpp:平面、柱面、球面等投影。
  • modules/stitching/src/exposure_compensate.cpp:增益和分块曝光补偿。
  • modules/stitching/src/seam_finders.cpp:动态规划、图割等接缝。
  • modules/stitching/src/blenders.cpp:羽化和多频带融合。
  • modules/stitching/src/autocalib.cpp:波形校正与自动标定辅助。

12.3 约束、执行与误区

  • 输入图像需要足够重叠和可重复纹理;纯色、重复纹理和运动物体会降低可靠性。
  • 工作分辨率、接缝分辨率和合成分辨率是三套尺度,应保持坐标换算一致。
  • PANORAMA 主要假设相机绕光心旋转;明显平移和近景视差会破坏单应模型。
  • 多频带融合质量较高但内存和时间开销大。
  • CUDA/OpenCL 只覆盖部分投影或融合路径,不能假定整条流水线都在设备端。
  • 误区:增加所有图像总能改善结果;错误边会污染匹配图和相机估计。
  • 误区:只调整融合器掩盖几何错位;应先检查匹配内点与相机参数。
  • 推荐入口:modules/stitching/include/opencv2/stitching.hppstitcher.cpp,再深入 detail/

13. ml:传统机器学习

13.1 定位与关键 API

ml 提供基于 Mat 的传统监督与无监督学习,适合中小规模结构化特征。
统一基类是 StatModel,数据包装为 TrainData,超参数搜索辅助为 ParamGrid
算法包括 NormalBayesClassifierKNearestSVMEM
树模型包括 DTreesRTreesBoost
神经与线性模型包括 ANN_MLPLogisticRegressionSVMSGD
通用接口为 trainpredictsaveloadisTrained

13.2 内部子系统与主要源码

  • modules/ml/src/data.cpp:样本布局、训练/测试划分与变量类型。
  • modules/ml/src/svm.cppsvmsgd.cpp:核 SVM 与随机梯度版本。
  • modules/ml/src/tree.cpprtrees.cppboost.cpp:树模型族。
  • modules/ml/src/knearest.cppnbayes.cppem.cpp:经典统计模型。
  • modules/ml/src/ann_mlp.cpplr.cpp:多层感知机和逻辑回归。
  • modules/ml/src/inner_functions.cpp:共享数值辅助。

13.3 约束、执行与误区

  • 默认样本布局常为每行一个样本;必须用 ROW_SAMPLECOL_SAMPLE 明确表达。
  • 特征通常需转换为 CV_32F;类别标签和回归响应的类型、形状要匹配算法。
  • 类别变量必须通过 TrainData 的变量类型正确标记。
  • 缺失值、类别编码、归一化和特征缩放不会自动按业务语义处理。
  • 训练多在 CPU 完成,并非 UMat 或 GPU 训练框架。
  • 模型文件应与 OpenCV 版本和算法参数共同纳入部署验证。
  • 误区:在全量数据上调参后报告同一数据的准确率;必须保留独立验证集。
  • 推荐入口:modules/ml/include/opencv2/ml.hppdata.cpp 和目标算法实现文件。

14. gapi:图计算与流式执行

14.1 定位与关键 API

gapi 用声明式图描述计算,再将图编译到一个或多个执行后端。
图数据类型包括 GMatGScalarGArrayGOpaqueGFrame
GComputation 表示输入到输出的计算图,可通过 compileapply 执行。
GCompiled 是普通编译结果,GStreamingCompiled 面向持续数据源。
算子元信息由 GMetaArgGMatDesc 等描述。
自定义算子使用 G_API_OP,实现通过 CPU、Fluid、OpenCL 等 kernel package 提供。
编译参数可组合 kernel、网络推理参数、队列和流式策略。

14.2 内部子系统与主要源码

  • modules/gapi/src/api/:图节点、调用、数据对象和 GComputation 公共实现。
  • modules/gapi/src/compiler/:图模型构建、元信息传播、岛划分和编译 Pass。
  • modules/gapi/src/executor/:普通与流式执行器、队列和线程调度。
  • modules/gapi/src/backends/cpu/:基于 OpenCV CPU 函数的 kernel。
  • modules/gapi/src/backends/fluid/:面向缓存行和低内存占用的 Fluid 后端。
  • modules/gapi/src/backends/ocl/:OpenCL kernel。
  • modules/gapi/src/backends/streaming/:流式 kernel 支持。
  • modules/gapi/src/streaming/:媒体源、GStreamer、oneVPL 等接入。
  • modules/gapi/src/backends/ov/onnx/:推理后端桥接。

14.3 约束、执行与误区

  • 构图阶段操作的是符号对象,不会立即处理像素。
  • 编译需要输入元信息;尺寸、类型变化超出已编译描述时通常需要重新编译。
  • 每个图算子都必须在提供的 kernel package 中有可用实现。
  • 后端划分按“岛”执行,跨岛可能发生数据适配和同步。
  • Fluid 优势来自流水化和缓存局部性,不等价于一般 CPU kernel 的逐算子加速。
  • 流式模式需要管理启动、拉取、停止和背压,不是简单的循环 apply
  • 误区:认为任意现有 cv:: 函数会自动进入 G-API 图;必须有对应 G-API 操作与 kernel。
  • 推荐入口:modules/gapi/include/opencv2/gapi.hppsrc/api/gcomputation.cppsrc/compiler/

15. ts:OpenCV 自身测试基础设施

15.1 定位与关键 API

ts 是 OpenCV 模块测试和性能测试的公共支撑,不是业务算法库。
公开头聚合在 modules/ts/include/opencv2/ts.hpp
它提供测试基类、随机数据生成、矩阵比较、测试数据路径、标签和性能计时工具。
功能测试依赖 GoogleTest 风格基础设施,性能测试使用 OpenCV 的 perf 宏和运行器。

15.2 内部子系统与主要源码

  • modules/ts/src/ts.cppts_func.cpp:测试上下文与通用辅助。
  • modules/ts/src/ts_arrtest.cpp:数组算法测试基类和误差验证。
  • modules/ts/src/ts_gtest.cpp:测试框架集成。
  • modules/ts/src/ts_perf.cpp:性能测试运行与统计。
  • modules/ts/src/ts_tags.cpp:测试标签过滤。
  • modules/ts/src/ocl_test.cppcuda_test.cpp:设备测试辅助。

15.3 约束、误区与阅读入口

  • 测试数据根目录需要显式配置,不能依赖开发机的绝对路径。
  • 数值比较应根据算法、深度和后端选择绝对或相对误差。
  • 性能用例应预热并由框架控制迭代,避免把初始化成本混入稳态数据。
  • 误区:应用程序链接 ts 来获得通用工具;这些接口主要服务源码树内测试。
  • 推荐入口:目标模块 test/perf/modules/ts/include/opencv2/ts/ 对照阅读。

16. world:单库聚合目标

16.1 定位与实现方式

world 不是算法模块,而是把当前构建中启用的 OpenCV 模块聚合为单个 opencv_world 库。
它的价值是简化部署和链接参数,不改变 API 命名空间、模块语义或运行时后端。
modules/world/CMakeLists.txt 负责聚合逻辑。
modules/world/include/opencv2/world.hpp 提供聚合头入口。
modules/world/src/world_init.cpp 承担生成目标所需的初始化单元。

16.2 约束、误区与阅读入口

  • 单库只包含本次构建实际启用且允许聚合的模块。
  • 外部第三方动态库、插件、模型和系统媒体组件不会因 world 自动静态封装。
  • 使用单库可能增大链接和发布单元,也可能降低按模块裁剪的清晰度。
  • 误区:认为 opencv_world 提供额外算法或自动启用所有后端。
  • 推荐入口:modules/world/CMakeLists.txt,并结合顶层构建生成的模块清单核对。

17. objdetect:目标、图形码与标记检测

17.1 定位与关键 API

objdetect 汇集经典目标检测、图形码、ArUco/ChArUco 和部分 DNN 模型包装。
经典检测包括 CascadeClassifierHOGDescriptorgroupRectangles
图形码抽象为 GraphicalCodeDetector
二维码接口包括 QRCodeDetectorQRCodeDetectorArucoQRCodeEncoder
条码接口位于 cv::barcode::BarcodeDetector
标记接口包括 aruco::DictionaryArucoDetectorBoardGridBoard
混合标定板使用 CharucoBoardCharucoDetector
人脸 DNN 包装包括 FaceDetectorYNFaceRecognizerSF

17.2 内部子系统与主要源码

  • modules/objdetect/src/cascadedetect.cppcascadedetect_convert.cpp:级联检测和旧格式转换。
  • modules/objdetect/src/hog.cpp:HOG 特征与滑窗检测。
  • modules/objdetect/src/qrcode.cppqrcode_encoder.cpp:二维码检测、解码和编码。
  • modules/objdetect/src/graphical_code_detector.cpp:图形码公共门面。
  • modules/objdetect/src/barcode.cppbarcode_detector/barcode_decoder/:条码管线。
  • modules/objdetect/src/aruco/:字典、检测、板和 ChArUco。
  • modules/objdetect/src/face_detect.cppface_recognize.cpp:人脸模型包装。
  • modules/objdetect/src/opencl/:HOG 和级联检测的部分 OpenCL 内核。

17.3 约束、执行与误区

  • 级联分类器必须先成功 load;空分类器不会产生有效检测。
  • HOG 的窗口、块、步长和描述子维度必须与检测器权重匹配。
  • 二维码和条码检测可接受常见灰度或 BGR 图,但清晰度、静区和尺度决定解码率。
  • ArUco 字典、标记边长和坐标系定义必须在生成、检测和位姿阶段一致。
  • FaceDetectorYNFaceRecognizerSF 依赖外部模型,输入尺寸与归一化由包装接口约束。
  • 检测结果坐标位于输入图像坐标系,预缩放后需正确映射回原图。
  • 误区:把人脸相似度阈值跨模型、跨度量直接复用。
  • 推荐入口:modules/objdetect/include/opencv2/objdetect.hpp 和对应子头,再查同名源码。

18. photo:计算摄影与图像修复

18.1 定位与关键 API

photo 提供去噪、修复、HDR、曝光融合、无缝克隆和风格化处理。
去噪包括 fastNlMeansDenoisingfastNlMeansDenoisingColored、多帧版本和 denoise_TVL1
修复使用 inpaint,算法标志包括 Telea 与 Navier–Stokes 路径。
无缝克隆包括 seamlessClonecolorChangeilluminationChangetextureFlattening
HDR 对齐使用 AlignMTB
相机响应标定使用 CalibrateDebevecCalibrateRobertson
HDR 合并与曝光融合使用 MergeDebevecMergeRobertsonMergeMertens
色调映射包括 TonemapTonemapDragoTonemapReinhardTonemapMantiuk
非真实感渲染包括 edgePreservingFilterdetailEnhancepencilSketchstylization

18.2 内部子系统与主要源码

  • modules/photo/src/denoising.cppdenoise_tvl1.cpp:单帧、多帧去噪。
  • modules/photo/src/inpaint.cpp:图像修复。
  • modules/photo/src/seamless_cloning.cppseamless_cloning_impl.cpp:泊松融合。
  • modules/photo/src/align.cppcalibrate.cppmerge.cpp:HDR 管线。
  • modules/photo/src/tonemap.cpp:色调映射。
  • modules/photo/src/npr.cpp:风格化与细节增强。
  • modules/photo/src/opencl/nlmeans.clcuda/nlm.cu:部分去噪加速。

18.3 约束、执行与误区

  • NLM 参数以像素噪声与搜索窗口为尺度,窗口增大将显著提高计算量。
  • 多帧去噪要求相邻帧已大致对齐,并正确指定目标帧索引和时间窗口。
  • inpaint 掩码应为 8 位单通道,非零区域表示待修复像素。
  • HDR 辐照度合并通常接收同尺寸曝光序列和对应曝光时间。
  • MergeMertens 输出融合图而非物理辐照度图,不要求曝光时间。
  • 色调映射把 HDR 映射到显示范围,输出仍应按目标显示/编码格式转换。
  • 误区:把无缝克隆当通用几何对齐;源图、掩码和目标位置必须先合理配准。
  • 推荐入口:modules/photo/include/opencv2/photo.hpp,按任务进入 denoising.cppmerge.cpp 等。

19. 跨模块典型调用链

19.1 静态图像分析

  1. imgcodecs::imread 解码文件,失败时拒绝继续。
  2. core 检查尺寸、类型、连续性和数值范围。
  3. imgproc::cvtColorresize、滤波或阈值完成预处理。
  4. features2dobjdetectdnnml 执行任务算法。
  5. imgproc 绘制结果,imgcodecs::imwrite 编码输出。
  6. 调试时可用 highgui 展示,但生产计算不应依赖窗口事件循环。

19.2 相机标定与位姿

  1. videoio::VideoCapture 采集帧并记录设备、分辨率和时间信息。
  2. imgproc 转灰度,必要时做适度增强。
  3. calib3d 检测标定靶,cornerSubPix 提升角点精度。
  4. calibrateCamera 或鱼眼接口估计内参与畸变。
  5. initUndistortRectifyMap 生成固定映射,imgproc::remap 在每帧复用。
  6. solvePnP 从三维点和二维观测估计后续位姿。

19.3 特征配准与全景拼接

  1. imgcodecsvideoio 提供图像。
  2. imgproc 统一尺度和颜色。
  3. features2d 检测关键点并生成描述子。
  4. BFMatcherFlannBasedMatcher 产生候选匹配。
  5. calib3d::findHomography 配合 RANSAC/USAC 剔除外点。
  6. 简单任务可用 warpPerspective;完整全景交给 stitching 的相机估计、接缝和融合阶段。

19.4 视频检测与跟踪

  1. videoio 解码或采集,独立线程负责限长队列和重连。
  2. imgproc 完成颜色、尺寸和归一化前处理。
  3. dnnobjdetect 周期性给出检测框。
  4. video 的光流、Kalman 或 Tracker 在检测间隔内更新状态。
  5. core 管理时间戳和状态矩阵,业务层负责轨迹关联与生命周期。
  6. videoio::VideoWriter 写出时明确编码器、FPS、帧尺寸和颜色约定。

19.5 HDR 与计算摄影

  1. imgcodecs 以保持原位深的标志读取曝光序列。
  2. photo::AlignMTB 对齐存在轻微相机移动的图像。
  3. CalibrateCRF 估计响应曲线,MergeDebevecMergeRobertson 合成 HDR。
  4. 或使用 MergeMertens 直接进行曝光融合。
  5. Tonemap 将 HDR 映射到可显示范围。
  6. core 做范围检查和类型转换,imgcodecs 按目标格式编码。

19.6 G-API 流式管线

  1. GMatGFrame 等符号数据声明预处理和推理图。
  2. 为输入提供准确元信息和流式数据源。
  3. 组合 CPU、Fluid、OpenCL 或推理 kernel package。
  4. 编译器完成元信息传播、岛划分和执行计划生成。
  5. GStreamingCompiled 管理启动、拉取和停止。
  6. 用端到端吞吐和延迟验证跨后端复制是否抵消融合收益。

20. 二次开发指南

20.1 先选择扩展层级

  • 仅组合公开 API:最稳定,优先放在应用或独立库中。
  • 实现 Algorithm 派生类:适合需要统一配置、保存和工厂语义的算法。
  • 为 G-API 增加操作与 kernel:适合声明式流水线和多后端部署。
  • 扩展 videoio/highgui 后端:需要遵循内部后端接口与插件 ABI,维护成本较高。
  • 修改模块内部实现:只在确需进入 OpenCV 主源码时采用,并准备跨平台测试。
  • 新增 HAL/SIMD 路径:必须保留标量基线,并证明数值一致性和真实性能收益。

20.2 API 与数据边界

  • 公开接口优先使用 InputArray/OutputArray,内部尽早解析并验证真实类型。
  • 对尺寸、通道、深度、连续性、允许原地操作与空输入给出明确契约。
  • 不缓存短生命周期 Mat 的裸 data 指针。
  • 对 ROI、非连续矩阵和自定义步长编写专门测试。
  • 算法参数应有可解释默认值,并检查非法组合。
  • 序列化模型或配置时记录版本、预处理约定和坐标系。

20.3 后端与性能

  • 先建立正确的 CPU 基线,再增加 SIMD、OpenCL、CUDA 或第三方后端。
  • 把上传、下载、颜色转换和布局变换计入端到端性能。
  • 复用模型、编译图、索引、映射表和输出缓冲。
  • 避免在逐帧热路径中反复创建 NetStitcher、FLANN 索引或 G-API 编译结果。
  • 多线程时区分对象只读共享、内部可变状态和后端上下文约束。
  • 使用模块 perf/ 风格覆盖典型尺寸,也测试小输入的调度开销。

20.4 测试与诊断

  • 功能测试至少覆盖空输入、最小尺寸、奇数尺寸、ROI、不同深度和多通道。
  • 数值算法同时检查绝对误差、相对误差和几何不变量。
  • 鲁棒估计算法固定随机种子后测试,也保留统计性压力测试。
  • 后端一致性测试不能要求所有浮点位完全相同,应按误差模型设阈值。
  • 通过 getBuildInformation 记录构建能力,通过 videoio registry 或 DNN 查询确认实际后端。
  • 遇到性能回退时分别测量初始化、首帧、稳态和数据传输。

20.5 源码提交前检查

  1. 公共声明是否只放在模块 include/opencv2/ 下。
  2. 新实现是否被 CMakeLists.txt 和条件编译正确纳入。
  3. 不可用可选依赖时是否仍能构建并给出明确行为。
  4. C++ API、Python/Java 绑定注解和文档是否一致。
  5. 新增代码是否覆盖标量基线、优化路径和异常路径。
  6. 是否在目标模块 test/perf/ 增加对应案例。
  7. 是否避免把机器路径、测试资产位置或外部模型硬编码进源码。

21. 模块选型与阅读路线总结

  • 基础矩阵和运行时问题:从 core 开始。
  • 静态图像读写与处理:imgcodecs + imgproc + core
  • 相机和视频分析:videoio + imgproc + video
  • 局部特征与几何:features2d + flann + calib3d
  • 深度推理:dnn,并按输入来源搭配 imgcodecsvideoio
  • 全景:优先使用 stitching 高层接口,诊断时逐层进入 detail 组件。
  • 传统表格特征学习:使用 ml,把预处理和验证集策略放在模块之外。
  • 声明式或流式异构图:使用 gapi,先核对 kernel 与后端覆盖。
  • 图形码、标记和经典检测:使用 objdetect
  • HDR、去噪、修复和融合:使用 photo
  • OpenCV 自身测试扩展:使用 ts;应用代码不应依赖它。
  • 需要简化链接时选择 world,但仍按原模块理解 API、依赖和运行时行为。

阅读任何模块时,公开头文件回答“允许怎样使用”,统一入口源码回答“如何分发”,具体算法文件回答“怎样计算”,测试与性能目录回答“边界和代价是什么”。

04 OpenCV 4.13.0 算法流水线

04 OpenCV 4.13.0 算法流水线

本章面向需要把“单个 API 示例”组装成可验证视觉系统的开发者。内容以 OpenCV 4.13.0 的公开 API 和源码头文件为准,统一按“输入 → 处理 → 输出 → 失败诊断 → 参数调整 → 验证”描述。示例默认使用 Python 接口 cv2;C++ 中对应类型通常为 cv::Matcv::Point2fcv::KeyPoint 等。

本章只讨论算法流水线。模块边界、构建方式、HAL 优化和完整源码目录分别由其他章节负责。

4.1 流水线设计与输入契约

采集或解码"输入有效?"记录并拒绝处理颜色/位深/尺寸归一化主算法几何或语义后处理定量验证结果与中间产物

4.1.1 类型、范围与坐标

数据 常见类型 数值范围 典型用途
彩色图 uint8, H×W×3,BGR [0,255] 显示、传统视觉
灰度图 uint8, H×W [0,255] 阈值、边缘、角点
浮点图 float32, H×WH×W×C 常见 [0,1],也可无界 卷积、梯度、DNN
二值掩膜 uint8, H×W 推荐 {0,255} 形态学、轮廓、逻辑运算
标签图 int32, H×W 0...N,特殊算法可有负值 连通域、Watershed
点集 float32/float64, N×2N×1×2 像素坐标 几何估计

OpenCV 图像坐标原点在左上角,x 向右、y 向下;数组索引则写作 image[y, x]。裁剪 ROI 后得到的坐标相对 ROI 原点,回写原图必须加偏移。几何估计宜使用浮点坐标,标签和类别掩膜的缩放必须使用 INTER_NEAREST

最小输入守卫:

1
2
3
4
5
6
7
8
import cv2 as cv
import numpy as np

image = cv.imread("input.png", cv.IMREAD_COLOR)
if image is None or image.size == 0:
raise ValueError("图像读取失败或为空")
if image.dtype != np.uint8 or image.ndim != 3 or image.shape[2] != 3:
raise TypeError(f"期望 uint8 BGR,实际为 {image.dtype}, {image.shape}")

4.1.2 可复现验证

每一级至少记录输入类型、关键参数、有效像素比例、候选数、内点率、误差分位数及耗时。调参时先固定数据、随机种子、尺寸和指标,再确认颜色、位深、范围与坐标映射;从前往后一次只调一层,先提高召回率,最后优化速度。不要只保存最终叠加图,中间掩膜、边缘、内点和重投影结果更能定位失败阶段。

4.2 图像预处理

BGR/灰度原图裁剪 ROIcvtColorresizeconvertTo/normalize连续且语义明确的输入

4.2.1 API、参数和输入输出

  • cv.cvtColor(src, code)COLOR_BGR2GRAYCOLOR_BGR2HSVCOLOR_BGR2Lab 等;输出通道数由转换码决定。
  • cv.resize(src, dsize, fx, fy, interpolation):缩小优先 INTER_AREA,普通放大优先 INTER_LINEAR,离散标签使用 INTER_NEAREST
  • cv.normalize(src, dst, alpha, beta, norm_type):可做 NORM_MINMAX 或范数归一化,不等同于神经网络的均值方差标准化。
  • cv.copyMakeBorder:补边方式包括 BORDER_CONSTANTREPLICATEREFLECT_101
  • cv.remap(src, map1, map2, interpolation):输入映射表常为 CV_32FC1/2 或转换后的定点格式,输出尺寸由映射表决定。

保持宽高比缩放并补边时,设原尺寸为 (W,H)、目标尺寸为 (W_t,H_t)

[
s=\min(W_t/W,\ H_t/H),\quad W’=sW,\quad H’=sH
]

左右和上下总补边分别是 W_t-W'H_t-H'。后续坐标映射必须执行 x=(x_t-p_x)/sy=(y_t-p_y)/s

1
2
3
4
5
6
7
8
9
10
11
def letterbox(bgr, size=(640, 640), value=(114, 114, 114)):
tw, th = size
h, w = bgr.shape[:2]
scale = min(tw / w, th / h)
nw, nh = round(w * scale), round(h * scale)
resized = cv.resize(bgr, (nw, nh), interpolation=cv.INTER_LINEAR)
left, top = (tw - nw) // 2, (th - nh) // 2
right, bottom = tw - nw - left, th - nh - top
out = cv.copyMakeBorder(resized, top, bottom, left, right,
cv.BORDER_CONSTANT, value=value)
return out, scale, (left, top)

4.2.2 失败、调参和验证

  • 失败原因:把 RGB 模型输入当 BGR;整数除法导致归一化全零;宽高顺序写反;ROI 越界;重复压缩造成细节丢失。
  • 调参顺序:先定颜色空间和范围,再定目标尺寸及插值,最后选择补边和归一化。
  • 验证方法:检查通道均值、直方图、角点坐标回映射误差;对掩膜确认缩放后类别集合没有新增值。

4.3 滤波、增强与二值化

灰度或彩色图噪声模型判断Gaussian/Median/BilateralCLAHE/直方图均衡固定/Otsu/自适应阈值uint8 二值掩膜

4.3.1 滤波与增强

  • GaussianBlur(src, ksize, sigmaX, sigmaY=0):核尺寸通常为正奇数;适合近似高斯噪声。
  • medianBlur(src, ksize)ksize 为大于 1 的奇数;对椒盐噪声稳健。
  • bilateralFilter(src, d, sigmaColor, sigmaSpace):同时按空间距离和颜色差加权,保边但较慢。
  • equalizeHist(src):只接受 8 位单通道图;彩色图宜仅均衡亮度通道。
  • createCLAHE(clipLimit, tileGridSize):限制局部对比度,降低全局均衡放大噪声的风险。

高斯滤波可写为:

[
G(x,y)=\frac{1}{2\pi\sigma^2}\exp\left(-\frac{x^2+y^2}{2\sigma^2}\right),\quad I’=G*I
]

双边滤波的权重同时包含空间项与强度项:

[
w(p,q)\propto \exp(-|p-q|^2/2\sigma_s^2)\exp(-|I_p-I_q|^2/2\sigma_r^2)
]

4.3.2 二值化

  • threshold(src, thresh, maxval, type):输入通常为单通道;返回实际阈值和输出图。
  • THRESH_OTSU 自动寻找类间方差最大的阈值,应与 THRESH_BINARY 或反相模式组合。
  • adaptiveThreshold 要求 8 位单通道输入;blockSize 必须为大于 1 的奇数,C 从局部均值或高斯加权均值中扣除。
  • 目标比背景暗时,优先考虑 THRESH_BINARY_INV,避免后续把背景当作前景。

Otsu 最大化类间方差:

[
\sigma_b^2(t)=\omega_0(t)\omega_1(t)\left[\mu_0(t)-\mu_1(t)\right]^2
]

1
2
3
4
5
6
7
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
gray = cv.GaussianBlur(gray, (5, 5), 0)
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
enhanced = clahe.apply(gray)
otsu_t, mask = cv.threshold(
enhanced, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU
)

4.3.3 失败、调参和验证

  • 失败原因:光照梯度破坏全局阈值双峰假设;核过大吞掉细线;CLAHE 放大纹理和噪声;前景极少时 Otsu 偏向背景。
  • 调参顺序:先决定灰度/亮度通道和前景极性;再按噪声选滤波器;随后调增强;最后调阈值、blockSizeC
  • 验证方法:画灰度直方图;统计前景比例;在标注集上计算 Precision、Recall、IoU;用不同曝光和噪声级别做扰动测试。

4.4 形态学处理

白点黑洞收缩/分离扩张/连接二值图/灰度图getStructuringElement"缺陷类型"OpeningClosingErodeDilate清理后掩膜

结构元素可由 getStructuringElement(MORPH_RECT/MORPH_ELLIPSE/MORPH_CROSS, ksize) 构造。erodedilatemorphologyEx 接受灰度或多通道图,但语义最清晰的输入通常是 {0,255} 二值图;输出尺寸和类型默认不变。

集合意义下,腐蚀与膨胀为:

[
A\ominus B={z\mid B_z\subseteq A},\qquad
A\oplus B={z\mid (\hat B)_z\cap A\neq\varnothing}
]

开运算是 (A⊖B)⊕B,闭运算是 (A⊕B)⊖BMORPH_GRADIENT 近似膨胀减腐蚀,MORPH_TOPHAT 提取比结构元素小的亮结构,MORPH_BLACKHAT 提取暗结构。

1
2
3
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
opened = cv.morphologyEx(mask, cv.MORPH_OPEN, kernel, iterations=1)
clean = cv.morphologyEx(opened, cv.MORPH_CLOSE, kernel, iterations=2)
  • 失败原因:结构元素大于目标最窄部分;迭代过多合并相邻目标;前景极性颠倒;边界补值引入伪结构。
  • 调参顺序:先确认白色代表前景,再按缺陷方向选操作,随后选形状,再从小核、单次迭代开始。
  • 验证方法:比较连通域数量、面积分布、孔洞数和细线保留率;用异或图显示处理前后改变的像素。

4.5 Canny 与梯度

uint8 灰度图平滑Sobel/Scharr 梯度幅值与方向非极大值抑制双阈值与滞后连接单像素边缘

4.5.1 梯度 API 与原理

Sobel(src, ddepth, dx, dy, ksize, scale, delta) 输出导数图;对 8 位输入常用 CV_16SCV_32F,不能直接用 CV_8U 保存带符号梯度。Scharr 使用固定高精度 3×3 核,适合小核一阶导。magnitudephase 可由 Gx/Gy 得到幅值与方向。

[
G=\sqrt{G_x^2+G_y^2},\qquad \theta=\operatorname{atan2}(G_y,G_x)
]

Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False) 接受 8 位图;低阈值以下丢弃,高阈值以上保留,中间像素仅在连接强边缘时保留。L2gradient=False 使用 |Gx|+|Gy| 近似幅值,设为 True 使用欧氏幅值。

1
2
3
4
5
6
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
blur = cv.GaussianBlur(gray, (5, 5), 1.2)
gx = cv.Scharr(blur, cv.CV_32F, 1, 0)
gy = cv.Scharr(blur, cv.CV_32F, 0, 1)
mag = cv.magnitude(gx, gy)
edges = cv.Canny(blur, 50, 150, apertureSize=3, L2gradient=True)

4.5.2 失败、调参和验证

  • 失败原因:低阈值太低导致纹理泛滥;高阈值太高造成断边;平滑过强令弱边缘消失;图像动态范围变化使固定阈值失效。
  • 调参顺序:先控制输入尺度和降噪,再看梯度幅值分布,先调高阈值定位强边,再调低阈值连接,最后考虑形态学闭合。
  • 验证方法:边缘像素比例、与标注边缘的容差匹配 F1、轮廓闭合率;同时检查 GxGy,避免只看最终 Canny 图。

4.6 轮廓与形状分析

单通道二值图findContours层级/面积/周长过滤approxPolyDP/convexHull矩/外接框/圆/椭圆形状与几何量

4.6.1 API 和类型

  • findContours(image, mode, method):输入为 8 位单通道二值图;RETR_EXTERNAL 仅取外轮廓,RETR_TREE 建立完整嵌套层级。
  • CHAIN_APPROX_SIMPLE 压缩水平、垂直和斜线共线点;需要全部边界点时用 CHAIN_APPROX_NONE
  • contourArea(contour, oriented=False) 返回面积;arcLength(contour, closed) 返回周长。
  • approxPolyDP(curve, epsilon, closed) 使用 Douglas–Peucker 近似;常设 epsilon=k×周长
  • boundingRect 返回轴对齐整数框;minAreaRect 返回旋转矩形;fitEllipse 至少需要 5 个点。
  • moments 给出空间矩;当 m00 != 0 时质心为 (m10/m00, m01/m00)

圆度常定义为:

[
C=\frac{4\pi A}{P^2}
]

理想圆接近 1;像素化和轮廓噪声会使其下降。矩形填充率可取 A/(w·h),凸度可取 A/A_hull

1
2
3
4
5
6
7
8
9
10
11
contours, hierarchy = cv.findContours(
mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE
)
shapes = []
for cnt in contours:
area = cv.contourArea(cnt)
if area < 200:
continue
perimeter = cv.arcLength(cnt, True)
polygon = cv.approxPolyDP(cnt, 0.02 * perimeter, True)
shapes.append((cnt, polygon, area))

4.6.2 失败、调参和验证

  • 失败原因:轮廓断裂;噪声产生大量小轮廓;ROI 偏移未还原;用像素面积固定阈值处理多分辨率数据;忽略层级导致孔洞误计。
  • 调参顺序:先改善掩膜闭合性,再选检索模式,然后按相对面积过滤,最后调近似误差和形状指标。
  • 验证方法:把轮廓、顶点编号和层级叠加到原图;检查面积守恒;对旋转、缩放样本验证归一化指标稳定性。

4.7 几何变换与文档扫描

文档图像灰度/边缘/形态学四边形候选四角点稳定排序getPerspectiveTransformwarpPerspective光照校正/二值化正视文档

4.7.1 变换模型

仿射变换用 2×3 矩阵,保持平行关系;透视变换用单应矩阵:

[
s\begin{bmatrix}x’\y’\1\end{bmatrix}
=H\begin{bmatrix}x\y\1\end{bmatrix},\quad H\in\mathbb{R}^{3\times3}
]

getAffineTransform 需要三对点,getPerspectiveTransform 需要四对对应点。warpAffine/warpPerspectivedsize 是输出 (width,height)perspectiveTransform 用于变换点集,不用于重采样整幅图。remap 适合相机去畸变或任意稠密映射。

四点排序不能仅在所有视角下机械依赖坐标和差;更稳妥的做法是先取凸包、验证四边形非自交,再按质心极角排序并统一起点和方向。

1
2
3
4
5
6
7
8
src = np.array([[120, 80], [920, 110], [890, 680], [90, 650]],
dtype=np.float32)
dst = np.array([[0, 0], [799, 0], [799, 599], [0, 599]],
dtype=np.float32)
H = cv.getPerspectiveTransform(src, dst)
scan = cv.warpPerspective(image, H, (800, 600),
flags=cv.INTER_LINEAR,
borderMode=cv.BORDER_REPLICATE)

4.7.2 失败、调参和验证

  • 失败原因:四角顺序不一致导致翻转;候选不是凸四边形;文档边缘出画;镜头畸变未校正;纸张弯曲却使用平面单应。
  • 调参顺序:先去畸变,再提高边缘召回,按面积/凸性/角度筛四边形,最后确定输出比例与插值。
  • 验证方法:将目标四角通过逆单应投回原图;计算边线直线度、相邻边夹角、文字行水平度和正反向变换误差。

4.8 特征匹配与几何验证

图像 AdetectAndCompute图像 BdetectAndComputeKNN 匹配Lowe ratio/互检RANSAC/USACH/F/E 与内点掩膜重投影或极线验证

4.8.1 描述子与匹配器

SIFT_create 生成 CV_32F 浮点描述子,常用 L2 距离;ORB_create 生成 CV_8U 二进制描述子,使用 NORM_HAMMINGBFMatcher.knnMatch(k=2) 可做比率测试;crossCheck=True 只适用于一一最近邻匹配,不与 KNN 比率测试同时使用。

Lowe 比率判据为:

[
d_1 < r d_2
]

其中 d1,d2 是最近与次近距离,r 常从 0.7~0.8 起试。它只衡量描述子歧义,不能代替几何验证。

  • 平面场景或纯旋转:findHomography(..., RANSAC/USAC_MAGSAC, ransacReprojThreshold)
  • 未标定一般双视图:findFundamentalMat,满足 x_2^T F x_1=0
  • 已知相机内参:findEssentialMatrecoverPose,满足 x_2^T E x_1=0
1
2
3
4
5
6
7
8
9
10
11
12
13
gray1 = cv.cvtColor(image1, cv.COLOR_BGR2GRAY)
gray2 = cv.cvtColor(image2, cv.COLOR_BGR2GRAY)
orb = cv.ORB_create(nfeatures=2000)
kp1, des1 = orb.detectAndCompute(gray1, None)
kp2, des2 = orb.detectAndCompute(gray2, None)
if des1 is None or des2 is None:
raise RuntimeError("描述子为空")
knn = cv.BFMatcher(cv.NORM_HAMMING).knnMatch(des1, des2, k=2)
good = [m for pair in knn if len(pair) == 2
for m, n in [pair] if m.distance < 0.75 * n.distance]
pts1 = np.float32([kp1[m.queryIdx].pt for m in good])
pts2 = np.float32([kp2[m.trainIdx].pt for m in good])
H, inliers = cv.findHomography(pts1, pts2, cv.USAC_MAGSAC, 3.0)

4.8.2 失败、调参和验证

  • 失败原因:纹理重复;关键点过少或集中在小区域;运动模糊;误用距离范数;动态物体主导;平面模型用于强视差场景。
  • 调参顺序:先确认描述子类型与范数,再增加特征覆盖;随后调比率阈值;最后按图像噪声调 RANSAC 阈值和置信度。
  • 验证方法:报告原始匹配数、筛后匹配数、内点数和内点率;画内点空间分布;计算对称传输误差或极线距离的中位数和 95 分位数。

4.9 相机标定、PnP 与双目

4.9.1 单目标定

多姿态标定图棋盘/圆点/ChArUco 检测亚像素优化calibrateCamera逐帧重投影误差K、D、图像尺寸

针孔模型为:

[
s\begin{bmatrix}u\v\1\end{bmatrix}
=K[R|t]\begin{bmatrix}X\Y\Z\1\end{bmatrix},\quad
K=\begin{bmatrix}f_x&0&c_x\0&f_y&c_y\0&0&1\end{bmatrix}
]

findChessboardCornerspatternSize 是每行、每列的内角点数,不是方格数。cornerSubPix 输入灰度图和初始角点。calibrateCamera 输入每帧 N×3 物点与对应 N×2 像点,输出 RMS、内参、畸变、每帧外参。鱼眼模型应使用 cv.fisheye API,不能混用普通畸变系数语义。

1
2
3
4
5
6
7
8
9
ok, corners = cv.findChessboardCorners(gray, (9, 6))
if ok:
term = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_COUNT, 30, 1e-3)
corners = cv.cornerSubPix(gray, corners, (11, 11), (-1, -1), term)
image_points.append(corners)
object_points.append(board_points.copy())
rms, K, dist, rvecs, tvecs = cv.calibrateCamera(
object_points, image_points, gray.shape[::-1], None, None
)

失败原因包括姿态单一、标定板仅居中、覆盖深度不足、运动模糊、打印比例不准和运行分辨率变化。调参先改善采集覆盖,再剔除检测错误帧,最后谨慎固定高阶畸变参数。验证时必须用 projectPoints 计算逐帧误差,而不只看总体 RMS,并检查 fx/fy、主点及畸变曲线是否合理。

4.9.2 PnP 位姿

N 个 3D 物点solvePnP/Ransac对应 2D 像点 + K,Drvec,tvecprojectPoints重投影误差/坐标轴

solvePnP 的物点和像点必须一一对应。通用情况可从 SOLVEPNP_ITERATIVE 开始;平面方形标记可考虑 SOLVEPNP_IPPE_SQUARE,其四个物点有规定顺序;存在离群点时使用 solvePnPRansac,再以内点调用 solvePnPRefineLM

失败原因:单位不一致;点顺序错误;点近共线;平面解歧义;错误内参;把相机到物体变换与物体到相机变换混淆。调参先核对坐标系和单位,再选求解器,再调 RANSAC 重投影阈值,最后细化。验证应检查正深度、重投影误差以及时序位姿连续性。

4.9.3 双目标定与深度

同步左右图stereoCalibratestereoRectifyinitUndistortRectifyMap/remapStereoBM/SGBMdisparityreprojectImageTo3D

校正后对应点应位于同一水平扫描线。若焦距为 f、基线为 B、视差为 d,则:

[
Z=\frac{fB}{d}
]

StereoSGBM_createnumDisparities 必须为 16 的倍数,blockSize 为正奇数;常用平滑罚项起点为 P1=8·C·b^2P2=32·C·b^2。输出视差通常带 4 位小数定标,转浮点时除以 16。

失败原因:左右不同步、曝光差、垂直视差、弱纹理、重复纹理和遮挡。调参先验证校正,再定最小/最大视差范围,然后调窗口与 P1/P2,最后做左右一致性和 speckle 清理。验证用极线纵向误差、有效视差比例和已知距离平面的深度误差。

4.10 光流、背景建模与跟踪

4.10.1 光流

前一灰度帧LK/Farneback当前灰度帧前帧特征点位移/稠密 flow状态过滤与重检测

亮度恒常和小运动假设给出光流约束:

[
I_xu+I_yv+I_t=0
]

Lucas–Kanade 在局部窗口内联合求解,calcOpticalFlowPyrLK 输入前后帧及 N×1×2 float32 点,输出新点、status 和误差。winSize 控制局部窗口,maxLevel 控制金字塔层数。calcOpticalFlowFarneback 输出 H×W×2 float32 稠密流。

1
2
3
4
5
6
7
8
p0 = cv.goodFeaturesToTrack(prev_gray, 500, 0.01, 8)
p1, status, err = cv.calcOpticalFlowPyrLK(
prev_gray, gray, p0, None,
winSize=(21, 21), maxLevel=3,
criteria=(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 30, 0.01)
)
good0 = p0[status.ravel() == 1]
good1 = p1[status.ravel() == 1]

失败原因:快速运动超出金字塔搜索;遮挡;无纹理区域;曝光突变;点漂移。调参先改善帧间隔和角点质量,再增大金字塔层级,随后调窗口,最后加前后向一致性并周期性重检测。验证可将点正向追踪后反向追踪,统计往返误差和有效点寿命。

4.10.2 背景建模

视频帧MOG2/KNN apply前景掩膜去阴影/形态学连通域/检测框

createBackgroundSubtractorMOG2(history=500, varThreshold=16, detectShadows=True) 适合较稳定相机;阴影通常标为 127,前景为 255,不能直接把所有非零值视为目标。learningRate=0 冻结模型,负值让算法自动选择,较大值适应更快但会吞掉慢速目标。

失败原因:相机抖动、周期背景、自动曝光、目标长时间静止。调参先固定相机和曝光,再设置学习率与历史长度,然后调判定阈值,最后清理阴影和小区域。验证使用前景 IoU、误警面积、目标进入/离开后的适应时间。

4.10.3 状态跟踪

Kalman Filter 只估计状态,不负责目标检测或多目标关联。线性模型为:

[
x_k=Ax_{k-1}+Bu_k+w_k,\qquad z_k=Hx_k+v_k
]

cv.KalmanFilter(dynamParams, measureParams)transitionMatrixmeasurementMatrix、过程噪声 Q、测量噪声 R 必须与状态定义一致。失败通常来自时间步长错误、噪声协方差不合理和关联错配。先验证检测,再验证关联门限,随后调 R,最后调 Q;以轨迹 RMSE、ID 切换、丢失恢复时间验证。

4.11 图像分割

连通区域接触目标交互抠图种子扩张图像/二值先验"任务"connectedComponentsWithStatsdistanceTransform + watershedgrabCutfloodFill标签/统计量

4.11.1 连通域与 Watershed

connectedComponentsWithStats 接受 8 位单通道图,返回 int32 标签、包围框/面积统计和质心。connectivity=4 不连接对角像素,8 会连接。

Watershed 把梯度图看作地形,从 marker 指定的种子扩张。watershed(image, markers) 的图像是 8 位三通道,marker 是 int32 单通道;处理后分水岭边界标为 -1。未知区域必须为 0,已知前景实例使用不同正整数标签。

1
2
3
4
5
6
7
8
9
dist = cv.distanceTransform(mask, cv.DIST_L2, 5)
_, sure_fg = cv.threshold(dist, 0.45 * dist.max(), 255, 0)
sure_fg = sure_fg.astype(np.uint8)
sure_bg = cv.dilate(mask, np.ones((3, 3), np.uint8), iterations=3)
unknown = cv.subtract(sure_bg, sure_fg)
count, markers = cv.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
markers = cv.watershed(image.copy(), markers.astype(np.int32))

4.11.2 GrabCut、Flood Fill 与聚类

grabCut 输入 BGR 图、uint8 掩膜、矩形、背景/前景模型和迭代数;掩膜值是 GC_BGD/FGD/PR_BGD/PR_FGD。矩形初始化要求目标大体位于框内,精细边界应再用掩膜初始化。floodFill 从种子按颜色差扩张,需谨慎选择 loDiff/upDiff。颜色聚类可把像素转为 float32 N×C 后调用 kmeans,但空间不连续且类别编号无语义。

  • 失败原因:marker 粘连或缺失导致 Watershed 欠分/过分;GrabCut 框包含太多背景或目标触边;聚类只看颜色忽略空间。
  • 调参顺序:先确认任务线索,再优化前景/背景种子;Watershed 调距离阈值,GrabCut 调初始化和迭代,最后做区域过滤。
  • 验证方法:IoU、Dice、边界 F1、实例计数误差;将每个标签随机着色,检查标签泄漏和碎片。

4.12 图像拼接

有重叠的多图特征与成对匹配相机/单应估计Bundle Adjustment投影与曝光补偿接缝搜索羽化/多频段融合全景图

cv.Stitcher.create(mode) 提供完整封装:PANORAMA 假设相机旋转为主,SCANS 更适合仿射扫描件。stitch(images) 返回状态码和结果,不应只捕获异常。状态包括成功、需要更多图像、单应估计失败和相机参数调整失败。

高级流水线位于 cv::detail:特征寻找、最佳匹配图、运动估计、Bundle Adjustment、球面/柱面 warper、曝光补偿、接缝寻找及 blender 可独立替换。多频段融合减少低频曝光缝,羽化融合开销较小但不能修复错位。

1
2
3
4
stitcher = cv.Stitcher.create(cv.Stitcher_PANORAMA)
status, panorama = stitcher.stitch(images)
if status != cv.Stitcher_OK:
raise RuntimeError(f"拼接失败,状态码={status}")
  • 失败原因:重叠不足;纹理单一;视差显著;滚动快门;移动物体;输入顺序或尺度跨度过大。
  • 调参顺序:先检查相邻图重叠和匹配内点,再选 PANORAMA/SCANS;随后调匹配置信度与投影模型,最后才调曝光、接缝和融合。
  • 验证方法:匹配图连通性、边缘重影宽度、接缝两侧亮度差、直线弯曲程度和有效画布比例;不要仅凭“能输出图”判定成功。

4.13 DNN 推理

readNet/ONNXNet原图resize/letterboxblobFromImagesetInputforward按模型解码阈值/NMS坐标回映射

4.13.1 输入、执行和输出

readNet/readNetFromONNX 返回 cv.dnn.NetblobFromImage(image, scalefactor, size, mean, swapRB, crop, ddepth) 通常输出 NCHW 四维 blob。实际预处理由模型训练配置决定,OpenCV 不会自动推断 letterbox、均值、标准差或输出布局。

常见标准化为:

[
x’=(x-\mu)\cdot s
]

注意 blobFromImage 的顺序是先减 mean 再乘 scalefactorswapRB=True 会交换红蓝通道。若模型要求逐通道标准差,通常需自行构造浮点输入。

1
2
3
4
5
6
7
8
net = cv.dnn.readNetFromONNX("model.onnx")
inp, scale, (pad_x, pad_y) = letterbox(image, (640, 640))
blob = cv.dnn.blobFromImage(
inp, scalefactor=1.0 / 255.0, size=(640, 640),
mean=(0, 0, 0), swapRB=True, crop=False
)
net.setInput(blob)
outputs = net.forward(net.getUnconnectedOutLayersNames())

setPreferableBackendsetPreferableTarget 只表达偏好;部署前应通过构建信息、运行日志和基准确认实际后端。动态形状、量化模型和自定义算子必须做兼容性测试。

4.13.2 后处理、失败与验证

检测后处理通常先按置信度筛选,再调用 NMSBoxes(bboxes, scores, score_threshold, nms_threshold)。IoU 为:

[
\operatorname{IoU}(A,B)=\frac{|A\cap B|}{|A\cup B|}
]

失败原因:BGR/RGB 错;拉伸与 letterbox 混用;输出维度按错误模型版本解释;置信度定义错误;坐标忘记减 padding;类别索引偏移;NMS 跨类别误抑制。

调参顺序:先用已知输入对齐训练框架的预处理和原始张量,再实现解码与坐标回映射,随后调置信度和 NMS,最后选择后端和批量。验证应比较参考框架逐层或最终输出、固定样本数值误差、mAP/IoU,以及预热后的端到端延迟和峰值内存。

4.14 模板、霍夫与 ArUco

4.14.1 模板匹配

搜索图matchTemplate模板响应图minMaxLoc/局部峰值阈值与 NMS

matchTemplate(image, templ, method, mask) 输出尺寸为 (W-w+1, H-h+1) 的浮点响应图。TM_SQDIFF 系列越小越好,相关系数系列越大越好。归一化相关系数可理解为对均值和能量归一化后的相似度。

1
2
3
4
response = cv.matchTemplate(gray, templ, cv.TM_CCOEFF_NORMED)
_, score, _, location = cv.minMaxLoc(response)
if score >= 0.85:
x, y = location

失败原因是尺度、旋转、透视和光照差异,以及低纹理模板。先固定尺度搜索,再设置分数阈值和峰值抑制,最后才扩展图像金字塔或角度搜索。用正负样本分数分布、定位误差和重复检测率验证。

4.14.2 霍夫直线与圆

灰度图CannyHoughLinesP/HoughCircles长度/角度/半径筛选几何对象

直线法式为:

[
\rho=x\cos\theta+y\sin\theta
]

HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap) 输入 8 位二值边缘图,输出线段端点。HoughCircles 常用 HOUGH_GRADIENTdp 是累加器与图像分辨率反比,minDist 抑制相邻圆,param1 通常是内部 Canny 高阈值,param2 是圆心累加阈值。

失败原因:边缘太碎、纹理伪线、maxLineGap 连接无关边、半径范围过宽。调参先稳定边缘,再限定 ROI 和角度/半径范围,随后调投票阈值,最后调线长或圆间距。验证用端点到标注线距离、角度误差、圆心误差和半径误差。

4.14.3 ArUco 与 ChArUco

去畸变或原始图ArucoDetector.detectMarkers角点 + IDs + rejected板级匹配/角点细化solvePnPprojectPoints/drawFrameAxes

OpenCV 4.13.0 使用 cv.aruco.ArucoDetector(dictionary, detectorParams) 检测标记,输出每个标记的四角、ID 和拒绝候选。字典必须与打印标记一致。姿态估计可将已知标记或 Board 的三维角点与检测二维角点交给 solvePnP;单个方形标记适合 IPPE 方形模型。

1
2
3
4
5
6
dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250)
params = cv.aruco.DetectorParameters()
detector = cv.aruco.ArucoDetector(dictionary, params)
corners, ids, rejected = detector.detectMarkers(image)
if ids is not None:
cv.aruco.drawDetectedMarkers(image, corners, ids)

失败原因:字典错误;打印边框不足;标记像素过少;反光、模糊或遮挡;角点顺序与三维点不一致;未考虑镜头畸变。调参先保证打印质量和像素尺寸,再选角点细化方式,随后调整自适应阈值窗口和候选周长范围,最后估计位姿。验证 marker 检出率、ID 混淆、角点重投影误差、姿态抖动和不同距离下的稳定性。

4.15 验收与源码核验

验收至少覆盖:输入类型契约;中间结果留存;独立验证集阈值;重投影、极线或逆变换误差;空图与无候选分支;噪声、模糊、曝光、尺度、旋转、遮挡扰动;视频延迟和丢帧;DNN 与参考框架数值对齐。

本章 API 与主要参数已按仓库内 opencv-4.13.0/modules/ 下的 imgprocfeatures2dcalib3dvideostitchingdnnobjdetect 公开头文件核验,其中 ArUco 类声明位于 objdetect/include/opencv2/objdetect/aruco_detector.hpp。版本升级时仍须复查函数重载、枚举、默认参数、模型导入兼容性和 Python 绑定。

源码/API 核验不能替代任务数据上的定量验证;只有指标、失败样本和中间产物都可复现,流水线才算完成。

OpenCV 4.13.0 HAL 与性能优化

OpenCV 4.13.0 HAL 与性能优化

本文面向需要解释、选择或扩展 OpenCV 加速路径的开发者。内容依据 OpenCV 4.13.0 源码树中的 HAL、CPU 分发、并行、OpenCL 和 DNN 实现核验。文中的路径均相对于 OpenCV 源码根目录。

1. 先建立正确的性能模型

一次公开 API 调用可能依次经过:

1
2
3
4
5
6
7
公开 API
-> 参数检查与输出分配
-> OpenCL / 专用后端尝试
-> HAL 替换原语
-> CPU dispatch 或通用实现
-> parallel_for_ 分块
-> SIMD、标量与尾部处理

这不是所有函数都严格遵循的固定层级。不同模块会按算法、数据类型、尺寸和构建能力选择其中一部分。因此,“启用了某个库”不等于“每次调用都进入该库”。性能判断必须同时核对构建结果、运行时选择和实际输入。
HAL、SIMD、线程和异构设备解决的问题不同:

  • HAL 替换一组约定好的底层原语;
  • CPU dispatch 在同一二进制中选择不同指令集版本;
  • 通用 intrinsics 帮助源码以统一方式表达 SIMD;
  • parallel_for_ 把独立区间分给多个 CPU 线程;
  • T-API 通过 UMat 尝试 OpenCL;
  • DNN 后端把网络或网络片段交给专用执行引擎。

2. HAL 的两层含义

OpenCV 源码中的 HAL 至少有两层含义,阅读时不能混为一谈。

2.1 模块内的硬件抽象接口

主要入口包括:

1
2
3
4
5
6
modules/core/include/opencv2/core/hal/interface.h
modules/core/include/opencv2/core/hal/hal.hpp
modules/core/include/opencv2/core/hal/intrin.hpp
modules/core/include/opencv2/core/hal/intrin_*.hpp
modules/imgproc/include/opencv2/imgproc/hal/hal.hpp
modules/features2d/include/opencv2/features2d/hal/

interface.h 定义低层 C 风格接口、类型和返回码。接口返回值的三个基本约定是:

  • CV_HAL_ERROR_OK:实现已完成操作;
  • CV_HAL_ERROR_NOT_IMPLEMENTED:该输入或操作不支持,应由上层回退;
  • CV_HAL_ERROR_UNKNOWN:实现发生无法恢复的错误。
    各模块的 src/hal_replacement.hpp 提供默认替换入口。自定义头通过宏重新绑定 cv_hal_* 名称。例如实现头可先 #undef cv_hal_xxx,再将它定义为供应商函数。这是一种编译期替换机制,不是运行时插件虚函数表。
    intrin.hpp 及架构专用头属于另一类抽象。它们把向量寄存器、加载、存储、算术和归约包装成统一 API。算法可由同一份模板生成 baseline 或多个 dispatch 版本。intrinsics 不是外置 HAL,但两者可以在同一调用链中同时存在。

2.2 源码根目录中的 HAL 子工程

源码根目录 hal/ 保存树内可选实现:

1
2
3
4
5
6
7
hal/carotene/
hal/fastcv/
hal/kleidicv/
hal/ndsrvp/
hal/riscv-rvv/
hal/ipp/
hal/openvx/

这些目录各自构建静态辅助库或接入外部项目。根 CMakeLists.txt 决定其顺序、头文件注入和链接库收集。目录存在并不表示当前平台一定构建或使用它。

3. HAL 注册链与优先级

3.1 CMake 阶段的完整链路

根构建脚本中的关键流程是:

  1. 平台与依赖探测生成 HAVE_*
  2. 用户选项和探测结果修改 OpenCV_HAL 列表;
  3. foreach(hal ${OpenCV_HAL}) 按列表顺序处理实现;
  4. 树内实现通过 add_subdirectory(hal/...) 构建;
  5. 未识别名称通过 find_package(<name> NO_MODULE QUIET) 查找;
  6. ocv_hal_register() 收集库、头和 include 目录;
  7. custom_hal.hpp.in 被配置成构建目录中的 custom_hal.hpp
  8. 收集到的库进入 OpenCV 模块链接关系。
    ocv_hal_register() 实际做三件事:
  • 将实现库追加到 OPENCV_HAL_LINKER_LIBS
  • 将实现头变成生成头中的 #include
  • 将实现 include 目录加入构建。
    根脚本默认把 OpenCV_HAL 设为字符串 OpenCV_HAL。这个名称会走 find_package(OpenCV_HAL NO_MODULE QUIET)。因此 OpenCV_HAL_DIR 可指向一个含 OpenCV_HALConfig.cmake 的外置实现构建目录。

3.2 顺序为什么重要

IPP、OpenVX、FastCV、KleidiCV、Carotene、NDSRVP 和 RVV 会按条件前插到列表。每个注册头都可能重定义同一个 cv_hal_* 宏。生成的 custom_hal.hpp 按注册顺序包含这些头。后包含且确实重定义某接口的头,可能覆盖先前绑定。没有覆盖的接口继续由前一实现或默认实现提供。
不要仅根据“某库排在列表中”推断最终处理者。应检查生成的 custom_hal.hpp、具体实现头和目标链接命令。

3.3 从公开 API 到回退

典型路径可以概括为:

1
2
3
4
5
cv::算法
-> cv_hal_xxx(...)
-> 返回 OK:结束
-> 返回 NOT_IMPLEMENTED:执行 OpenCV 内部实现
-> 返回 UNKNOWN:按调用点的错误策略处理

是否允许回退由具体调用点决定。实现必须遵守接口的步长、尺寸、原地操作、边界和数值约定。“不支持此组合”应返回 NOT_IMPLEMENTED,不能悄悄产生近似错误结果。

4. 编写和接入自定义 HAL

源码自带两个教学实现:

1
2
samples/hal/c_hal/
samples/hal/slow_hal/

c_hal 的函数返回错误,用于验证错误处理和回退。slow_hal 替换按位运算,用可观察的慢实现证明绑定已生效。两者都会生成 OpenCV_HALConfig.cmake

4.1 最小接入流程

先单独构建自定义 HAL:

1
2
3
4
cmake -S /path/to/opencv/samples/hal/slow_hal \
-B /path/to/build-hal \
-D CMAKE_BUILD_TYPE=Release
cmake --build /path/to/build-hal -j

再配置 OpenCV:

1
2
3
4
5
cmake -S /path/to/opencv \
-B /path/to/build-opencv \
-D CMAKE_BUILD_TYPE=Release \
-D OpenCV_HAL_DIR=/path/to/build-hal
cmake --build /path/to/build-opencv -j

外置包至少需要导出:

1
2
3
4
5
set(OpenCV_HAL_FOUND TRUE)
set(OpenCV_HAL_VERSION 0.1.0)
set(OpenCV_HAL_LIBRARIES /path/to/libcustom_hal.a)
set(OpenCV_HAL_HEADERS custom_hal_impl.hpp)
set(OpenCV_HAL_INCLUDE_DIRS /path/to/include)

生产实现应使用可重定位的导出目标或安装路径。上面的绝对占位仅说明变量语义。

4.2 实现检查清单

  • 函数签名必须与当前 4.13.0 接口完全一致;
  • 只重定义真正实现的接口;
  • 对不支持的深度、通道或边界模式返回 NOT_IMPLEMENTED
  • 正确处理非连续矩阵和字节步长;
  • 明确是否支持源、目的区域重叠;
  • 避免越过每行有效宽度;
  • 保证多线程并发调用安全;
  • 不把进程级可变状态放进无保护全局变量;
  • 静态库用于共享 OpenCV 时通常需要位置无关代码;
  • 用正确性测试覆盖空尺寸、奇数尺寸和尾部元素;
  • 用性能测试证明收益大于分派与转换成本;
  • 将支持矩阵、版本和供应商运行库要求写入发布说明。

4.3 如何确认自定义 HAL 生效

检查以下证据链:

  1. CMake 配置日志找到了自定义包;
  2. 生成的 custom_hal.hpp 包含自定义头;
  3. 目标链接命令含自定义 HAL 库;
  4. 针对被替换接口的测试通过;
  5. 通过日志、计数器或调试器确认函数被调用;
  6. 关闭自定义 HAL 后基准结果按预期变化。
    不要只靠符号出现在静态库中判断生效。链接器可能丢弃未引用对象,宏绑定也可能已被后续头覆盖。

5. 树内 HAL 实现

5.1 Carotene

选项是 WITH_CAROTENE。根 CMake 仅在 ARM/AArch64 的适用平台显示该选项。真正注册前还要求 CPU_BASELINE_FINAL 包含 NEON。接线头是 hal/carotene/hal/tegra_hal.hpp
Carotene 覆盖多种 core 与 imgproc 原语。其对象库会按 WITH_NEON 添加定义,并包含针对内联增长的编译参数。适合已有 NEON baseline 的 ARM 构建。它不是所有 ARM 算法的统一开关,也不等价于 CPU dispatch 中的 NEON。

5.2 Qualcomm FastCV

选项是 WITH_FASTCV,默认关闭。可见平台为 ARM/AArch64 上的 Android 或适用 Unix。依赖探测成功后形成 HAVE_FASTCV。实现位于 hal/fastcv/src/,注册头覆盖 core 和 imgproc 的部分接口。
hal/fastcv/CMakeLists.txt 将外部 FASTCV_LIBRARY 链接到 fastcv_hal。选项打开但库或头未找到时,HAL 不可用。发布时必须同时考虑 FastCV 二进制、许可、目标 ABI 和运行时装载路径。

5.3 Arm KleidiCV

选项是 WITH_KLEIDICV。源码将其限制到 AArch64 的 Android 或 Unix 环境。依赖可用时,OpenCV包含 KleidiCV 自带的 adapters/opencv/CMakeLists.txt。适配器负责生成 kleidicv_hal 和对应注册信息。
构建中还提供 KLEIDICV_ENABLE_SME2,默认关闭。源码注释指出它与部分 Android NDK Clang 版本不兼容。启用 SME2 前要同时验证编译器、运行设备和部署基线。

5.4 Andes NDSRVP

选项是 WITH_NDSRVP,仅在 RISC-V 平台可见。注册还要求 C 与 C++ flags 都包含 -mext-dsp。同时要求 baseline 不含 RVV。这体现了 NDSRVP 与 RVV HAL 的选择关系。
实现覆盖部分 core、imgproc 和 features2d 接口。构建生成 ndsrvp_hal 静态库。应使用 Andes 对应工具链验证编译选项,不能在普通 RISC-V 工具链上只强开选项。

5.5 RISC-V RVV HAL

选项是 WITH_HAL_RVV,仅在 RISC-V 平台可见。注册要求 CPU_BASELINE_FINALRVV。构建目标为 rvv_hal。入口头 rvv_hal.hpp 汇集 core、imgproc 和 features2d 替换。
源码覆盖矩阵分解、数学、颜色转换、滤波、几何变换、直方图和 FAST 等多类原语。具体接口仍可能因数据类型或参数而回退。RVV HAL 与通用 intrinsics 中的 RVV dispatch 是不同机制。

5.6 Intel IPP

选项是 WITH_IPP。根 CMake 在 x86/x86_64 且适用平台提供该选项,并以 HAVE_IPP 验证探测结果。注册目标 ipphal 覆盖 mean、min/max、norm、极坐标转换、变换、warp 和 sum 等接口。
OpenCV 其他位置仍保留 IPP 集成。hal/ipp/CMakeLists.txt 的注释明确指出 HAL 尚未成为唯一 IPP 来源。因此分析 IPP 命中时要同时看 HAL 和模块内部 IPP 路径。WITH_IPP_CALLS_ENFORCED 更适合验证和开发,不应在不了解回退影响时用于通用发布。

5.7 OpenVX

选项是 WITH_OPENVX,默认关闭。cmake/FindOpenVX.cmake 探测实现并形成 HAVE_OPENVX。只有探测成功才进入 hal/openvx/hal/。源码还包含 ivx.hpp 等 C++ 包装。
OpenVX HAL 只覆盖它实现的原语。性能受图构建、数据导入导出、供应商实现和目标设备影响。不能把 WITH_OPENVX=ON 理解为整个 OpenCV 流水线自动转换为 OpenVX 图。

5.8 选择摘要

平台或依赖 首先评估 关键验证
x86/x86_64 CPU dispatch、IPP HAVE_IPP、实际命中、线程数
通用 ARM/AArch64 NEON、Carotene、KleidiCV baseline、编译器、覆盖接口
Qualcomm ARM FastCV 外部库、许可、ABI、回退
Andes RISC-V DSP NDSRVP -mext-dsp 且 baseline 非 RVV
RISC-V Vector RVV HAL CPU_BASELINE_FINAL 含 RVV
OpenVX 设备 OpenVX HAL 实现版本、传输和图开销

6. CPU baseline 与 runtime dispatch

6.1 两类构建结果

CPU_BASELINE 指定库运行所需的最低优化能力。baseline 指令可以出现在通用代码路径中。把 AVX2 设为 baseline 意味着不支持 AVX2 的机器不应运行该二进制。
CPU_DISPATCH 指定额外编译的优化版本。运行时检测 CPU 后选择可用的最高合适版本。不满足这些额外能力的机器仍可走 baseline。
高级约束还有:

  • CPU_BASELINE_REQUIRE:必须成功启用的 baseline;
  • CPU_BASELINE_DISABLE:禁止的 baseline;
  • CPU_DISPATCH_REQUIRE:必须成功生成的 dispatch。
    最终结果记录在:
  • CPU_BASELINE_FINAL
  • CPU_DISPATCH_FINAL
  • CMake Summary 的 CPU/HW features 段。

6.2 源码组织

热点实现常使用:

1
2
3
name.dispatch.cpp
name.simd.hpp
name.avx2.cpp

CV_CPU_DISPATCH 宏按运行时能力调用命名空间中的版本。dispatch 链最终落到 BASELINE。不是每个算法、深度和尺寸都有每种指令集实现。

6.3 构建与运行时控制

构建时 CV_DISABLE_OPTIMIZATION=ON 会关闭多类优化,适合建立调试对照。运行时 cv::setUseOptimized(false) 关闭受该全局标志控制的优化分支。它必须在没有其他 OpenCV 调用并发执行的顶层安全位置调用。
环境变量 OPENCV_CPU_DISABLE 可禁用以逗号或分号分隔的 dispatch 特性。它适合定位某个指令集实现,不适合作为长期性能配置的替代品。

1
OPENCV_CPU_DISABLE=AVX2,AVX512-SKX /path/to/app

cv::getCPUFeaturesLine() 的标记含义为:

  • 无标记:baseline;
  • 前缀 *:dispatch 中编译的特性;
  • 后缀 ?:已编译但当前硬件不可用。

7. parallel_for_ 与线程后端

cv::parallel_for_ 接受一个 Range 和并行循环体。它把区间划分为多个 stripe,再交给并行后端。构建可能使用 TBB、OpenMP、平台后端、插件或内置实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Body final : public cv::ParallelLoopBody {
public:
Body(const cv::Mat& src, cv::Mat& dst) : src_(src), dst_(dst) {}

void operator()(const cv::Range& range) const override {
for (int y = range.start; y < range.end; ++y)
src_.row(y).copyTo(dst_.row(y));
}

private:
const cv::Mat& src_;
cv::Mat& dst_;
};

cv::parallel_for_(cv::Range(0, src.rows), Body(src, dst));

循环体应满足:

  • 每个 stripe 写入互不重叠的输出;
  • 只读共享输入;
  • 共享统计量使用归约或同步;
  • 不依赖 stripe 的执行顺序;
  • 粒度足够大,能覆盖调度开销;
  • 异常和对象生命周期符合调用线程语义。
    常用控制 API:
1
2
3
cv::setNumThreads(1);
int configured = cv::getNumThreads();
int cpus = cv::getNumberOfCPUs();

setNumThreads(1) 可用于串行对照。传负数恢复系统默认。该函数不是线程安全的,不能在并行区或并发调用中修改。getNumThreads() 的精确语义取决于 TBB、OpenMP 等后端。
上层线程池与 OpenCV 内部线程并行叠加会过度订阅。批量处理时常见策略是“外层并行、库内单线程”或反之。应分别测量,不能凭核心数直接决定。

8. OpenCL Transparent API

T-API 使用 cv::UMat 表达可由 OpenCL 管理的数据。支持 OpenCL 的函数会尝试设备实现,不支持时可走 CPU 路径。

1
2
3
4
5
cv::UMat src, gray, blurred;
cv::imread("input.jpg", cv::IMREAD_COLOR).copyTo(src);
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 1.2);
cv::ocl::finish();

诊断 API:

1
2
3
4
5
std::cout << cv::ocl::haveOpenCL() << '\n';
std::cout << cv::ocl::useOpenCL() << '\n';
cv::ocl::setUseOpenCL(true);
const cv::ocl::Device& dev = cv::ocl::Device::getDefault();
std::cout << dev.name() << '\n';

环境变量 OPENCV_OPENCL_DEVICE 可选择设备或设为 disabled。设备选择应在 OpenCL 上下文首次初始化前完成。
性能陷阱包括:

  • 小算子启动成本高于计算收益;
  • MatUMat 频繁互转造成上传和下载;
  • getMat() 可能触发同步;
  • 只计异步提交而没有 cv::ocl::finish() 会低估时间;
  • 某一步回退到 CPU 可能打断整条设备流水线;
  • 首次编译 kernel 与缓存建立不代表稳定态。
    最佳实践是让尽可能长的支持链保持 UMat。端到端基准必须包含必要的输入传输、最终同步和输出取回。

9. DNN 后端与目标

OpenCV 4.13.0 的公开枚举包含:

  • 后端:Default、Halide、OpenVINO、OpenCV、VkCom、CUDA、WebNN、TIM-VX、CANN;
  • 目标:CPU、OpenCL、OpenCL FP16、Myriad、Vulkan、FPGA、CUDA、CUDA FP16、HDDL、NPU、ARM CPU FP16。
    枚举存在不代表当前构建可用。应查询实际组合:
1
2
3
4
for (const auto& item : cv::dnn::getAvailableBackends())
std::cout << item.first << " -> " << item.second << '\n';

auto targets = cv::dnn::getAvailableTargets(cv::dnn::DNN_BACKEND_OPENCV);

显式选择示例:

1
2
3
cv::dnn::Net net = cv::dnn::readNet("/path/to/model.onnx");
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

CUDA 后端通常要求构建探测到 CUDA,并按能力使用 cuDNN、cuBLAS 等。OpenVINO、TIM-VX、CANN 等也各有构建和运行时依赖。不支持的层可能回退、重新分区或直接报错,取决于后端。
DNN 性能测量应分离:

  • 模型读取与解析;
  • 首次网络初始化;
  • 首次推理和 kernel 编译;
  • 稳定态推理;
  • blob 预处理;
  • 输出复制与后处理。
    Net::getPerfProfile() 可返回层级时间,但支持范围与后端有关。最终仍要以应用端到端延迟和吞吐为准。

10. 内存、数据布局与缓存

许多“计算优化”最终受内存带宽限制。优先检查:

  • 是否在循环中反复创建同尺寸输出;
  • 是否存在无意的 clone()copyTo() 或类型转换;
  • ROI 是否导致非连续步长;
  • 通道转换能否前移、合并或取消;
  • 数据类型是否超出精度需求;
  • 大图处理是否有更好的 tile;
  • 多线程是否争用同一缓存行;
  • NUMA 机器上的分配与执行是否跨节点。
    cv::Mat 是引用计数的浅拷贝头。赋值通常不复制像素,clone() 才执行深拷贝。ROI 可能不连续,底层代码必须尊重 step。可用 isContinuous() 判断能否把多行合并为一个线性区间。
    OpenCV 提供 fastMalloc()fastFree()。需要特殊分配策略时可研究 MatAllocator,但这是高级扩展点。自定义 allocator 必须处理生命周期、对齐、map/unmap 和异常路径。一般应用先复用 Mat::create() 管理的缓冲区即可。
    减少峰值内存的常用方法:
  • 原地操作仅在 API 明确支持时使用;
  • 将中间缓冲区放到循环外复用;
  • 流式读取视频,不缓存全部帧;
  • 控制 DNN batch 与输入分辨率;
  • 对超大图采用分块并处理 halo;
  • 避免同时保留 MatUMat 和设备副本。

11. 可复现 benchmark 方法

11.1 基准骨架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cv::TickMeter tm;
cv::Mat dst;

for (int i = 0; i < 10; ++i)
cv::GaussianBlur(src, dst, cv::Size(5, 5), 1.2);

std::vector<double> samples;
for (int i = 0; i < 100; ++i) {
tm.reset();
tm.start();
cv::GaussianBlur(src, dst, cv::Size(5, 5), 1.2);
tm.stop();
samples.push_back(tm.getTimeMilli());
}

GPU 或 OpenCL 路径要在计时区间末尾同步。异步设备后端也要使用其对应同步机制。不要使用 getCPUTickCount() 直接换算耗时;源码文档建议一般计时使用 getTickCount()

11.2 必须固定和记录

  • OpenCV 完整版本与源码修订;
  • Release、Debug 或 RelWithDebInfo;
  • 编译器、标准库和关键编译参数;
  • baseline、dispatch 与 HAL 列表;
  • 第三方加速库和驱动版本;
  • CPU 型号、频率策略、NUMA 与亲和性;
  • GPU/NPU 型号、功耗模式与温度;
  • 输入尺寸、类型、通道、步长和内容分布;
  • 线程数、并行后端和上层并发;
  • 预热次数、样本数和同步位置;
  • 中位数、分位数与离群值规则;
  • 优化前后的输出误差阈值;
  • 是否包含 I/O、传输、预处理和后处理。

11.3 OpenCV 自带 perf

启用 BUILD_PERF_TESTS=ON 后可构建 opencv_perf_<module>。使用 GoogleTest 风格过滤器缩小测试范围:

1
2
/path/to/build/bin/opencv_perf_core \
--gtest_filter='*bitwise_and*'

先运行 --help 查看当前二进制支持的 perf 参数。不同构建和版本的参数集合可能变化。不要把单个微基准直接外推为完整业务收益。

12. 诊断 API 与环境变量

最小诊断程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <iostream>

int main() {
cv::utils::logging::setLogLevel(
cv::utils::logging::LOG_LEVEL_INFO);
std::cout << cv::getVersionString() << '\n';
std::cout << cv::getBuildInformation() << '\n';
std::cout << cv::getCPUFeaturesLine() << '\n';
std::cout << "optimized=" << cv::useOptimized() << '\n';
std::cout << "threads=" << cv::getNumThreads() << '\n';
std::cout << "cpus=" << cv::getNumberOfCPUs() << '\n';
std::cout << "opencl=" << cv::ocl::haveOpenCL() << '\n';
}

常用环境变量:

1
2
3
4
OPENCV_LOG_LEVEL=DEBUG /path/to/app
OPENCV_CPU_DISABLE=AVX2 /path/to/app
OPENCV_FOR_THREADS_NUM=1 /path/to/app
OPENCV_OPENCL_DEVICE=disabled /path/to/app

诊断顺序建议:

  1. 打印 getBuildInformation()
  2. 核对目标模块和第三方依赖确实为 YES;
  3. 打印 CPU features 和线程数;
  4. 开启日志观察后端选择;
  5. 逐个关闭线程、dispatch、OpenCL 或专用后端;
  6. 保持相同输入比较结果和时间;
  7. 用调试器或 profiler 获取最终证据。

13. 平台决策树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
先确认热点是否在 OpenCV 内
|
+-- 否 -> 优化 I/O、业务逻辑或数据搬运
|
+-- 是
|
+-- x86/x86_64
| -> Release + 合理 baseline/dispatch
| -> 检查 IPP、线程和内存带宽
|
+-- ARM/AArch64
| -> 检查 NEON baseline/dispatch
| -> 评估 Carotene / KleidiCV
| -> Qualcomm 设备再评估 FastCV
|
+-- RISC-V
| -> RVV baseline 可用:评估 RVV HAL
| -> Andes DSP 工具链:评估 NDSRVP
|
+-- 有 OpenCL
| -> 流水线可长期保留 UMat:测 T-API
| -> 频繁传输或小算子:优先 CPU
|
+-- DNN
-> 查询可用 backend/target
-> 按模型覆盖率、精度、延迟选择

14. 优化实施顺序

  1. 建立正确性基线和误差标准;
  2. 用 profiler 找到真实热点;
  3. 先减少输入量、重复计算和数据搬运;
  4. 确保使用 Release 构建;
  5. 核验已有 SIMD、HAL、IPP 和线程路径;
  6. 调整线程层级和任务粒度;
  7. 评估保持设备驻留的 OpenCL 或 DNN 后端;
  8. 仅对稳定且高占比的底层原语开发自定义 HAL;
  9. 用同一套正确性与性能测试验收;
  10. 在目标设备和热稳态条件下重新测量。
    最终选择应以目标平台的可重复端到端数据为依据。任何加速路径都必须保留可诊断的回退方案,并验证回退结果正确。

OpenCV 4.13.0 配置、构建与使用指南

OpenCV 4.13.0 配置、构建与使用指南

本文给出从 Linux 源码构建到 C++/Python 使用、测试、调试和部署的完整流程。内容依据 OpenCV 4.13.0 的根 CMakeLists.txt、模块配置和公开头文件核验。所有命令使用 /path/to 占位,不依赖本文之外的说明。

1. 构建前的版本与目录约定

建议准备三个彼此分离的目录:

1
2
3
/path/to/opencv-4.13.0/       # 只读源码
/path/to/build-opencv/ # CMake 缓存和编译产物
/path/to/install-opencv/ # 安装结果

源码外构建便于:

  • 同时维护 Debug、Release、静态和交叉构建;删除构建目录后干净重配;
  • 避免生成文件污染源码;明确部署内容来自哪个安装前缀。
    记录源码标签、提交、编译器和 CMake 版本。若使用 opencv_contrib,主仓库与 contrib 应来自相同版本标签。不要把不同小版本的头文件、库和 Python 扩展混在一起。

2. Linux 构建环境

2.1 基础工具

最低实用工具集包括:

  • 支持 C++11 及项目要求的 GCC 或 Clang;CMake;
  • Ninja 或 Make;pkg-config;
  • Python 3 和开发文件;Git、下载工具与证书包;
  • 目标功能对应的开发包。
    Debian/Ubuntu 类系统的常见准备命令:
1
2
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build pkg-config python3 python3-dev python3-numpy libjpeg-dev libpng-dev libtiff-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libgtk-3-dev libtbb-dev

这只是常见组合,不是强制清单。服务器可省略 GTK。不用视频时可省略 FFmpeg。发行版包名和版本可能不同,应以 CMake Summary 的探测结果为准。

2.2 首次 Release 构建

1
2
3
4
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-opencv -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-opencv

cmake --build /path/to/build-opencv -j
cmake --install /path/to/build-opencv

单配置生成器使用 CMAKE_BUILD_TYPE。Visual Studio、Xcode 等多配置生成器通常在构建和安装时用 --config Release。不要假设环境变量中的编译器会覆盖已有 CMake 缓存。切换编译器、架构或静态/动态策略时应使用新的构建目录。

2.3 配置结果验收

配置末尾的 Summary 至少检查:

  • OpenCV version;C/C++ compiler;
  • CPU/HW baseline 与 dispatched code;To be built / Disabled / Unavailable modules;
  • GUI 与 Video I/O;Media I/O;
  • Parallel framework;OpenCL、IPP、Eigen 等;
  • Python 3 interpreter、libraries、numpy 和 install path;Install to。
    WITH_X=ON 表示请求能力。HAVE_X 或 Summary 中的 YES 才表示探测成功。某个模块未进入 “To be built” 时,安装后不会凭空可用。

3. CMake 选项语义

3.1 模块选择

选项 语义
BUILD_LIST 构建列出的模块及其必要依赖,接受逗号、空格、冒号等分隔
BUILD_opencv_<name> 单独控制某模块
OPENCV_EXTRA_MODULES_PATH 一个或多个额外模块目录,通常指向 contrib 的 modules
BUILD_opencv_world 构建聚合库 opencv_world
BUILD_SHARED_LIBS ON 生成共享库,OFF 生成静态库
BUILD_TESTS 构建正确性和回归测试
BUILD_PERF_TESTS 构建性能测试
BUILD_EXAMPLES 构建示例
BUILD_LIST=core,imgproc 会自动加入必要依赖。它不会加入“业务上可能需要”的可选模块。例如 imread 需要 imgcodecs,窗口需要 highgui,摄像头需要 videoio
BUILD_opencv_world=ON 方便简单链接。它不减少内部模块依赖,也不保证第三方静态依赖自动适合所有消费方式。需要最小部署、插件隔离或清晰依赖时,按组件链接通常更稳妥。

3.2 第三方能力

选项 主要作用
WITH_IPP x86/x86_64 上的 Intel IPP 优化
WITH_OPENCL OpenCL 与 Transparent API
WITH_TBB TBB 并行后端
WITH_OPENMP OpenMP 并行支持
WITH_FFMPEG FFmpeg 视频 I/O
WITH_GSTREAMER GStreamer 视频 I/O
WITH_GTK / WITH_QT / WITH_WAYLAND Linux GUI 后端
WITH_CUDA CUDA runtime 与相关能力
WITH_CUDNN DNN CUDA 路径使用 cuDNN
WITH_OPENVINO OpenVINO DNN 后端
OPENCV_ENABLE_NONFREE 启用受额外许可约束的算法,默认关闭
选项默认值受平台条件影响。OpenCV 4.13.0 根配置对 WITH_CUDAWITH_OPENVXWITH_FASTCV 等默认关闭。打开选项后仍需匹配开发头、库、工具链和版本。

3.3 CPU 与构建质量

选项 语义
CPU_BASELINE 运行二进制所要求的最低 CPU 指令集
CPU_DISPATCH 额外编译并在运行时选择的指令集
CV_DISABLE_OPTIMIZATION 关闭多类优化,主要用于诊断
ENABLE_LTO 请求链接时优化
ENABLE_FAST_MATH 允许影响严格浮点语义的优化
CMAKE_BUILD_TYPE 单配置生成器的 Release/Debug/RelWithDebInfo
提高 baseline 会牺牲旧 CPU 兼容性。通用发布包更适合保守 baseline 加 runtime dispatch。ENABLE_FAST_MATH 可能改变 NaN、舍入和可重复性,不应只因“更快”而默认打开。

3.4 Python 相关

常用变量包括:

1
2
3
4
5
6
BUILD_opencv_python3
PYTHON3_EXECUTABLE
PYTHON3_INCLUDE_DIR
PYTHON3_LIBRARY
PYTHON3_NUMPY_INCLUDE_DIRS
PYTHON3_PACKAGES_PATH

优先指定目标虚拟环境中的 PYTHON3_EXECUTABLE。其余变量只有在自动探测错误时再显式设置。配置 Summary 必须显示预期解释器、NumPy 和安装路径。

3.5 缓存与重配置

查看缓存:

1
2
cmake -L -N /path/to/build-opencv
cmake -LAH -N /path/to/build-opencv

更改单个普通选项可重新运行 cmake -S ... -B ...。更改编译器、sysroot、生成器、目标架构或主要依赖版本时新建构建目录。不要手工编辑 CMakeCache.txt 作为常规配置方式。

4. 常见构建配方

4.1 最小图像处理

1
2
3
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-min -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-min -D BUILD_LIST=core,imgproc,imgcodecs -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D WITH_FFMPEG=OFF -D WITH_GSTREAMER=OFF -D WITH_GTK=OFF
cmake --build /path/to/build-min -j
cmake --install /path/to/build-min

此配方适合无 GUI 的离线图像处理。PNG/JPEG 等能力仍取决于 Media I/O 探测。

4.2 完整桌面构建

1
2
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-full -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-full -D WITH_GTK=ON -D WITH_FFMPEG=ON -D WITH_GSTREAMER=ON -D WITH_TBB=ON -D WITH_OPENCL=ON -D BUILD_EXAMPLES=ON -D BUILD_TESTS=ON -D BUILD_PERF_TESTS=ON
cmake --build /path/to/build-full -j

“完整”不是开启所有实验后端。只启用目标机器安装、测试和部署得了的能力。

4.3 contrib 构建

1
2
3
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-contrib -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-contrib -D OPENCV_EXTRA_MODULES_PATH=/path/to/opencv_contrib-4.13.0/modules
cmake --build /path/to/build-contrib -j
cmake --install /path/to/build-contrib

变量应指向 modules 目录,不是 contrib 仓库根目录。若只需少数模块,可同时使用:

1
-D BUILD_LIST=core,imgproc,imgcodecs,features2d,xfeatures2d

启用 OPENCV_ENABLE_NONFREE=ON 前先审查算法和部署地区的许可要求。

4.4 静态构建

1
2
3
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-static -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-static -D BUILD_SHARED_LIBS=OFF -D BUILD_LIST=core,imgproc,imgcodecs -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF
cmake --build /path/to/build-static -j
cmake --install /path/to/build-static

静态 OpenCV 不等于最终应用完全静态。编解码器、线程库、系统库和 C++ 运行库仍可能需要显式链接。优先使用安装导出的 CMake 配置传播依赖,不要手写一串 .a

4.5 Debug 和 RelWithDebInfo

1
2
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-debug -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -D CMAKE_INSTALL_PREFIX=/path/to/install-debug -D BUILD_TESTS=ON
cmake --build /path/to/build-debug -j

Debug 最便于断言和逐步调试,但性能不能代表发布构建。RelWithDebInfo 常用于接近 Release 的采样和崩溃符号化。

4.6 Linux 交叉构建

OpenCV 源码提供多种工具链文件,例如:

1
2
3
4
platforms/linux/aarch64-gnu.toolchain.cmake
platforms/linux/arm-gnueabi.toolchain.cmake
platforms/linux/riscv64-gcc.toolchain.cmake
platforms/linux/riscv64-clang.toolchain.cmake

示例:

1
2
3
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-aarch64 -G Ninja -D CMAKE_TOOLCHAIN_FILE=/path/to/opencv-4.13.0/platforms/linux/aarch64-gnu.toolchain.cmake -D CMAKE_INSTALL_PREFIX=/usr -D CMAKE_STAGING_PREFIX=/path/to/stage-aarch64 -D ARM_LINUX_SYSROOT=/path/to/sysroot -D BUILD_LIST=core,imgproc,imgcodecs -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF
cmake --build /path/to/build-aarch64 -j
cmake --install /path/to/build-aarch64

CMAKE_INSTALL_PREFIX=/usr 表示目标机路径。CMAKE_STAGING_PREFIX 是主机侧暂存位置。还可按部署流程使用 DESTDIR,但不要同时混淆两套根目录语义。
交叉构建验收:

  • 编译器目标三元组正确;sysroot 中头和库属于目标架构;
  • filereadelf 显示正确 ELF 架构;CMake 没有误用主机 /usr/lib
  • Python 绑定没有把主机解释器库误当目标库;在真实设备或模拟环境运行最小测试。

5. 安装与卸载边界

安装后常见布局:

1
2
3
4
/path/to/install-opencv/include/opencv4/
/path/to/install-opencv/lib/
/path/to/install-opencv/lib/cmake/opencv4/
/path/to/install-opencv/bin/

精确布局受平台和 GNUInstallDirs 影响。消费工程应通过 OpenCVConfig.cmake 查找,不应依赖固定相对层数。
安装到系统前缀:

1
sudo cmake --install /path/to/build-opencv

更推荐先安装到项目管理的独立前缀。源码构建通常没有可靠的通用 uninstall 目标。使用独立前缀可通过删除整个前缀干净移除。不要覆盖发行版管理器拥有的同名文件。

6. C++ 工程消费

6.1 推荐 CMake 写法

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
cmake_minimum_required(VERSION 3.16)
project(opencv_demo LANGUAGES CXX)

find_package(OpenCV 4.13 REQUIRED
COMPONENTS core imgproc imgcodecs videoio dnn)

add_executable(opencv_demo main.cpp)
target_compile_features(opencv_demo PRIVATE cxx_std_17)
target_include_directories(opencv_demo PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(opencv_demo PRIVATE ${OpenCV_LIBS})

配置消费工程:

1
2
cmake -S /path/to/app -B /path/to/build-app -G Ninja -D OpenCV_DIR=/path/to/install-opencv/lib/cmake/opencv4
cmake --build /path/to/build-app

某些安装还提供导出的具体 target。可用名称应以该安装的 OpenCVConfig.cmake 为准。${OpenCV_LIBS} 是跨不同 OpenCV 包布局更常见的兼容写法。

6.2 pkg-config

根配置中的 OPENCV_GENERATE_PKGCONFIG 默认关闭且标为 deprecated。新工程优先使用 CMake package config。必须兼容旧构建系统时,可显式请求生成并验证:

1
pkg-config --cflags --libs opencv4

静态链接时还要检查:

1
pkg-config --static --libs opencv4

6.3 最小图像程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

int main(int argc, char** argv) {
if (argc != 3) {
std::cerr << "usage: app input output\n";
return 2;
}

cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
if (image.empty()) {
std::cerr << "cannot decode input\n";
return 3;
}

cv::Mat gray, edges;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.2);
cv::Canny(gray, edges, 50, 150);

if (!cv::imwrite(argv[2], edges)) {
std::cerr << "cannot encode output\n";
return 4;
}
return 0;
}

检查 imread()VideoCapture::isOpened() 和模型读取结果。不要让空矩阵继续进入算法后才处理异常。

7. Python 构建与使用

7.1 在虚拟环境中构建

1
2
3
4
5
6
python3 -m venv /path/to/venv
/path/to/venv/bin/python -m pip install --upgrade pip numpy

cmake -S /path/to/opencv-4.13.0 -B /path/to/build-python -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-python -D BUILD_opencv_python3=ON -D PYTHON3_EXECUTABLE=/path/to/venv/bin/python -D PYTHON3_PACKAGES_PATH=/path/to/venv/lib/python3.x/site-packages
cmake --build /path/to/build-python -j
cmake --install /path/to/build-python

python3.x 替换为实际版本目录。安装后验证实际加载文件:

1
2
3
4
5
6
/path/to/venv/bin/python - <<'PY'
import cv2
print(cv2.__version__)
print(cv2.__file__)
print(cv2.getBuildInformation())
PY

7.2 Python API 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pathlib import Path
import cv2

src_path = Path("/path/to/input.jpg")
dst_path = Path("/path/to/output.png")

image = cv2.imread(str(src_path), cv2.IMREAD_COLOR)
if image is None:
raise FileNotFoundError(src_path)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
if not cv2.imwrite(str(dst_path), edges):
raise RuntimeError(f"cannot write {dst_path}")

Python 的 NumPy 数组常与 cv::Mat 共享或包装内存。注意 dtype、shape、stride、连续性和生命周期。避免在热点循环中无意义调用 np.ascontiguousarray() 或复制。

7.3 常见 Python 混装

系统包、pip wheel 和源码构建的 cv2 可能同时存在。表现包括:

  • cv2.__version__ 不是 4.13.0;getBuildInformation() 缺少刚启用的后端;
  • 导入时报未定义符号;NumPy ABI 不匹配;
  • IDE 与终端使用不同解释器。
    总是先打印:
1
2
import cv2, sys
print(sys.executable); print(cv2.__file__); print(cv2.__version__)

8. 视频读取与写入

C++ 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cv::VideoCapture cap("/path/to/input.mp4", cv::CAP_ANY);
if (!cap.isOpened())
throw std::runtime_error("cannot open video");

double fps = cap.get(cv::CAP_PROP_FPS);
int width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
int height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));

cv::VideoWriter out(
"/path/to/output.mp4",
cv::VideoWriter::fourcc('m', 'p', '4', 'v'),
fps > 0 ? fps : 30.0,
cv::Size(width, height));
if (!out.isOpened())
throw std::runtime_error("cannot open writer");

cv::Mat frame;
while (cap.read(frame)) {
cv::putText(frame, "OpenCV", {20, 40},
cv::FONT_HERSHEY_SIMPLEX, 1.0, {0, 255, 0}, 2);
out.write(frame);
}

后端、容器和 codec 是三层概念。文件扩展名不能保证编码器存在。用 cap.getBackendName() 或调试日志确认实际后端。相机可显式传 cv::CAP_V4L2cv::CAP_GSTREAMER 等偏好,但必须由构建支持。
在 Python 中:

1
2
3
4
5
6
7
8
9
10
11
12
cap = cv2.VideoCapture("/path/to/input.mp4", cv2.CAP_ANY)
if not cap.isOpened():
raise RuntimeError("cannot open video")

try:
while True:
ok, frame = cap.read()
if not ok:
break
# process frame
finally:
cap.release()

生产服务应限制网络流的连接、读取和重连策略。不要无限阻塞或无限缓存来自不可信源的视频。

9. DNN 推理

9.1 ONNX 基本流程

1
2
3
4
5
6
7
8
9
10
11
12
cv::dnn::Net net = cv::dnn::readNetFromONNX("/path/to/model.onnx");
if (net.empty())
throw std::runtime_error("cannot load model");

net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

cv::Mat blob = cv::dnn::blobFromImage(
image, 1.0 / 255.0, cv::Size(640, 640),
cv::Scalar(), true, false, CV_32F);
net.setInput(blob);
cv::Mat output = net.forward();

预处理参数必须来自模型契约:

  • 输入尺寸;NCHW 或其他布局;
  • BGR/RGB 顺序;scale;
  • mean;crop 或 letterbox;
  • 输入精度;输出节点和后处理。
    “能运行”不代表预处理正确。应使用已知样本与参考框架对齐输出。

9.2 查询并选择后端

1
2
for (const auto& p : cv::dnn::getAvailableBackends())
std::cout << p.first << ':' << p.second << '\n';

公开后端包括 OpenCV、OpenVINO、CUDA、Halide、VkCom、WebNN、TIM-VX 和 CANN 等。实际可用组合由构建与运行时依赖决定。先查询,再设置 backend/target。首次推理通常包含初始化或编译,性能测试要预热。

9.3 DNN 诊断

可先提高日志等级:

1
OPENCV_LOG_LEVEL=DEBUG /path/to/dnn-app

进一步排查可使用:

1
OPENCV_DNN_CHECK_NAN_INF=1 OPENCV_DNN_CHECK_NAN_INF_RAISE_ERROR=1 /path/to/dnn-app

这些检查会影响性能,仅用于诊断。对不支持的 ONNX 算子,先最小化模型并记录导出器版本、opset 和错误层。

10. samples、tests 与 perf

源码中的主要样例目录:

1
2
3
4
5
6
7
samples/cpp/
samples/python/
samples/dnn/
samples/tapi/
samples/opencl/
samples/gpu/
samples/hal/

启用示例:

1
2
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-samples -D CMAKE_BUILD_TYPE=Release -D BUILD_EXAMPLES=ON
cmake --build /path/to/build-samples -j

正确性与性能测试分别位于各模块的 test/perf/。常见目标名:

1
2
3
4
opencv_test_core
opencv_test_imgproc
opencv_perf_core
opencv_perf_imgproc

运行单个测试:

1
/path/to/build-opencv/bin/opencv_test_core --gtest_filter='Core_Mat.*'

通过 CTest:

1
ctest --test-dir /path/to/build-opencv --output-on-failure

性能测试:

1
/path/to/build-opencv/bin/opencv_perf_imgproc --gtest_filter='*GaussianBlur*'

先运行可执行文件的 --help 确认当前参数。测试数据可能要求额外数据仓库或环境变量。跨机器比较 perf 前固定构建类型、线程数、温度、频率和输入。

11. 调试与日志

11.1 运行时构建信息

1
2
3
4
std::cout << cv::getVersionString() << '\n';
std::cout << cv::getBuildInformation() << '\n';
std::cout << cv::getCPUFeaturesLine() << '\n';
std::cout << cv::getNumThreads() << '\n';

Python 对应:

1
print(cv2.__version__); print(cv2.getBuildInformation()); print(cv2.getCPUFeaturesLine()); print(cv2.getNumThreads())

11.2 日志级别

环境变量方式:

1
OPENCV_LOG_LEVEL=DEBUG /path/to/app

C++ API:

1
2
3
4
#include <opencv2/core/utils/logger.hpp>

cv::utils::logging::setLogLevel(
cv::utils::logging::LOG_LEVEL_VERBOSE);

详细日志可能包含设备、后端和文件信息。生产环境应控制等级并避免把敏感路径直接发送到外部日志。

11.3 GDB 与 sanitizer

1
gdb --args /path/to/app /path/to/input.jpg

应用和 OpenCV 都有符号时回溯最有价值。如需 sanitizer,建议建立独立构建并统一编译、链接选项。

1
cmake -S /path/to/opencv-4.13.0 -B /path/to/build-asan -G Ninja -D CMAKE_BUILD_TYPE=Debug -D CMAKE_C_FLAGS='-fsanitize=address -fno-omit-frame-pointer' -D CMAKE_CXX_FLAGS='-fsanitize=address -fno-omit-frame-pointer' -D CMAKE_EXE_LINKER_FLAGS='-fsanitize=address' -D CMAKE_SHARED_LINKER_FLAGS='-fsanitize=address'

常规定位顺序:

  1. 确认实际加载的 OpenCV;
  2. 保存原始输入和最小复现;
  3. 打印尺寸、类型、步长和连续性;
  4. 单线程复现;
  5. 关闭特定加速后端做对照;
  6. 使用 Debug、断言和 sanitizer;
  7. 修复后增加回归测试。

12. 部署

12.1 共享库部署

查看 ELF 依赖:

1
2
ldd /path/to/app
readelf -d /path/to/app

部署时包含:

  • 应用直接依赖的 OpenCV .so;OpenCV 所需第三方运行库;
  • 视频、GUI 或 DNN 插件;模型、级联文件和配置;
  • 与目标系统兼容的 C++ 运行库。
    使用 RPATH/RUNPATH 或系统动态链接器配置管理查找路径。不要依赖开发机的 LD_LIBRARY_PATH 作为正式部署方案。

12.2 容器部署

多阶段构建可将编译环境与运行环境分开。运行镜像只复制安装前缀、应用和必要运行库。还要考虑:

  • 摄像头设备映射;GPU 驱动与容器 runtime;
  • GUI socket;codec 和字体;
  • 非 root 用户权限;只读文件系统下的缓存目录。

12.3 静态部署

静态链接降低部分运行时查找问题,但会:

  • 增大文件;增加第三方依赖传播复杂度;
  • 影响插件能力;加重许可证合规工作;
  • 使安全更新需要重新链接和发布。
    无论共享或静态,都应生成软件物料清单并保留构建配置。

13. ABI 与版本共存

不要假设所有 OpenCV 4.x 二进制 ABI 永久兼容。风险来源包括:

  • 编译器和 libstdc++ ABI;Debug 与 Release 混用;
  • _GLIBCXX_USE_CXX11_ABI;静态与共享库组合;
  • contrib 与主库版本不一致;第三方库 ABI;
  • DNN 插件与核心库版本;Python 与 NumPy ABI。
    最佳实践:
  • 应用与 OpenCV 使用兼容工具链;编译时和运行时加载同一安装前缀;
  • 通过 OpenCV_DIR 固定消费版本;不混合多个前缀的头和库;
  • 插件与主库一起构建、测试和部署;升级小版本也执行 ABI 与回归验证;
  • 对公共接口避免暴露 cv::Mat 跨不受控插件边界,除非双方 ABI 被锁定。
    并行安装可使用不同前缀。运行时通过 RUNPATH 或隔离容器选择版本。不要用覆盖系统库的方式实现升级。

14. 迁移到 4.13.0

迁移检查清单:

  • 移除旧 C API 和废弃常量;核对模块是否移动到 contrib;
  • 检查返回值、默认参数和 Python tuple 形态;重新导出并验证 DNN 模型;
  • 核对 ONNX opset 和后端覆盖;重新验证视频后端、codec 和设备索引;
  • 检查序列化文件、标定参数和模型兼容性;更新 CMake 的组件列表;
  • 重跑正确性、性能和资源泄漏测试;检查许可证与部署依赖变化。
    迁移时先固定旧版输出样本。对浮点算法定义绝对或相对误差,而不是要求逐位一致。同时比较性能分布,避免因后端改变出现隐性回退。

15. 安全与资源管理

OpenCV 处理的是复杂二进制格式、视频流和模型。不可信输入应视为攻击面。

15.1 输入控制

  • 在解码前限制文件大小;解码后限制宽、高、通道和总像素;
  • 对视频限制帧率、分辨率、时长和重连次数;对模型限制来源、大小和允许格式;
  • 拒绝路径穿越和意外覆盖输出;设置任务超时和内存上限;
  • 将解析服务放入低权限进程或容器;跟踪 OpenCV 与 codec 库安全更新。
    像素内存约为:
1
rows * step

不能只用压缩文件大小估算解码内存。超高压缩比图片和畸形尺寸可能导致资源耗尽。

15.2 C++ 生命周期

cv::Mat 使用引用计数并支持浅拷贝。返回引用、ROI 或包装外部缓冲区时,必须保证底层内存仍存活。跨线程共享只读矩阵通常可行,但并发写入需要应用自行同步。
资源对象使用 RAII:

1
2
3
4
5
6
{
cv::VideoCapture cap("/path/to/input.mp4");
if (!cap.isOpened())
throw std::runtime_error("open failed");
// cap leaves scope and releases resources
}

不要把 Mat::data 保存到超过矩阵生命周期的异步任务。包装外部内存时,OpenCV 不一定拥有或释放该内存。

15.3 Python 生命周期

使用 try/finally 释放摄像头和 writer。长服务中不要无界保存帧列表。NumPy 视图与 cv2 返回数组共享数据时,保留拥有者引用。捕获 cv2.error 时记录操作和输入元数据,但避免记录敏感图像本身。

16. FAQ

16.1 找不到 OpenCVConfig.cmake

显式指定:

1
-D OpenCV_DIR=/path/to/install-opencv/lib/cmake/opencv4

确认该文件确实由 cmake --install 生成。不要把 OpenCV_DIR 指向源码根目录。

16.2 头文件找到但链接失败

常见原因:

  • 头来自一个版本,库来自另一个版本;忘记请求对应组件;
  • 静态第三方依赖未传播;Debug/Release 或 C++ ABI 不一致;
  • 链接顺序不适合手写静态库列表。
    删除手写 -lopencv_*,先用安装导出的 CMake 配置复现。

16.3 运行时找不到 .so

先查看:

1
2
ldd /path/to/app
readelf -d /path/to/app

为部署配置 RUNPATH,或将库安装到受管理的系统路径。不要复制单个 OpenCV 库后忽略其第三方依赖。

16.4 imread() 返回空

检查:

  • 路径与当前工作目录;文件读取权限;
  • 文件是否完整;对应 codec 是否在 Summary 中启用;
  • 输入是否超出资源限制;cv::haveImageReader() 是否识别该文件。
    内存输入使用 imdecode(),并验证字节缓冲区完整。

16.5 VideoCapture 打不开

检查:

  • WITH_FFMPEG / WITH_GSTREAMER 的最终探测;摄像头设备权限;
  • 容器设备映射;backend preference;
  • URL、认证、网络与超时;codec 和像素格式。
    OPENCV_LOG_LEVEL=DEBUG 查看后端尝试。

16.6 imshow() 在服务器失败

无桌面环境通常没有可用显示后端或 display server。改为 imwrite()、Web 输出或无头测试。不要为了 imshow() 给生产容器引入整套 GUI,除非确有需求。

16.7 Python 导入了错误版本

打印:

1
2
import cv2, sys
print(sys.executable); print(cv2.__file__); print(cv2.getBuildInformation())

清理冲突的 pip、系统包或 PYTHONPATH。重新配置时确认 Summary 指向目标虚拟环境。

16.8 打开 CUDA 但算法仍在 CPU

WITH_CUDA=ON 不会让普通 cv::Mat 算法自动迁移到 GPU。CUDA 模块通常使用专用 cv::cuda API,并可能来自 contrib。DNN 还需要选择 CUDA backend/target,并满足对应构建依赖。

16.9 Release 仍然很慢

按顺序确认:

  1. 实际加载的是 Release 库;
  2. 输入没有重复复制和转换;
  3. CPU dispatch 与并行后端存在;
  4. 线程没有过度订阅;
  5. GPU/OpenCL 计时包含同步;
  6. DNN 已预热且未回退;
  7. 热点确实位于 OpenCV 调用内部。

16.10 CMake 选项显示 ON,但功能不可用

选项表达请求,不表达探测成功。检查 Summary、CMakeCache.txtgetBuildInformation() 和日志。依赖版本、头、库、目标架构或工具链任一不匹配都可能使能力不可用。

17. 发布前验收清单

  • 使用干净构建目录完成配置;保存完整 CMake 命令和 Summary;
  • 构建类型是预期的 Release 或 RelWithDebInfo;安装到独立前缀;
  • 消费工程只使用该前缀;C++ 最小程序可编译和运行;
  • Python 时确认 cv2.__file__;图片、视频和 DNN 各跑一个真实样本;
  • 执行目标模块 tests;在目标设备运行 perf 或业务基准;
  • 检查共享库和插件依赖;核对模型、codec、contrib 和 nonfree 许可;
  • 对不可信输入设置尺寸、时间和内存限制;记录 ABI、编译器和第三方版本;
  • 保留回滚所需的旧安装前缀和构建清单。
    完成这些步骤后,构建结果才不仅是“编译通过”,而是可定位、可复现、可部署和可维护的 OpenCV 4.13.0 工程。

OpenCV 4.13.0 源码文件索引与导航

OpenCV 4.13.0 源码文件索引与导航

1. 使用范围与路径约定

本文是一份可独立使用的 OpenCV 4.13.0 源码导航,内容按源码树实际文件核验。

  • 所有路径都相对于源码根目录 opencv-4.13.0/
  • “公开头”指安装后供使用者包含的头文件;“内部头”通常只参与 OpenCV 自身编译。
  • src/ 是实现主入口,test/ 是正确性与回归测试,perf/ 是性能基准。
  • 同一 API 可能经过分派层、HAL、第三方库或硬件后端,不能只凭第一个同名函数判断最终执行位置。
  • 本文不依赖同目录或上级目录中的其他说明文档。

建议按“公开声明 → 普通实现 → 分派/HAL → 测试 → perf → Demo”的顺序阅读。

2. 根目录导航

路径 作用 阅读重点
CMakeLists.txt 全工程构建入口 版本、平台、全局选项、模块扫描、HAL 与第三方依赖
cmake/ CMake 基础设施 模块声明、CPU 分派、依赖探测、安装与包导出
modules/ OpenCV 主模块 每个模块一般含公开头、实现、测试、性能测试
include/opencv2/opencv.hpp 常用聚合头 汇总主要模块头,适合应用,不适合定位具体声明
hal/ 树内可选 HAL 实现 Carotene、FastCV、IPP、OpenVX、RVV、KleidiCV 等
3rdparty/ 随源码构建的第三方组件 图像格式、并行库、模型格式等可选依赖
apps/ 官方命令行工具 标注、级联训练、模型诊断、交互标定等完整应用
samples/ C++、Python、DNN、G-API 等示例 从 API 用法反查模块和源码的首选入口
platforms/ 平台构建与交叉编译 Android、Apple、JavaScript、Linux 工具链与打包
data/ 运行示例所需数据 Haar/LBP 分类器和算法数据
doc/ 官方文档源文件 API 分组、教程和构建文档源
LICENSE 项目许可证 二次分发前应核对
README.md 项目入口说明 支持平台、构建和项目概况

3. 模块总览

模块 主要公开头 主要实现目录 测试/性能
core modules/core/include/opencv2/core.hppmodules/core/include/opencv2/core/ modules/core/src/ modules/core/test/modules/core/perf/
imgproc modules/imgproc/include/opencv2/imgproc.hpp modules/imgproc/src/ modules/imgproc/test/modules/imgproc/perf/
imgcodecs modules/imgcodecs/include/opencv2/imgcodecs.hpp modules/imgcodecs/src/ modules/imgcodecs/test/modules/imgcodecs/perf/
highgui modules/highgui/include/opencv2/highgui.hpp modules/highgui/src/ modules/highgui/test/
features2d modules/features2d/include/opencv2/features2d.hpp modules/features2d/src/ modules/features2d/test/modules/features2d/perf/
calib3d modules/calib3d/include/opencv2/calib3d.hpp modules/calib3d/src/ modules/calib3d/test/modules/calib3d/perf/
video modules/video/include/opencv2/video.hppmodules/video/include/opencv2/video/ modules/video/src/ modules/video/test/modules/video/perf/
videoio modules/videoio/include/opencv2/videoio.hpp modules/videoio/src/ modules/videoio/test/modules/videoio/perf/
dnn modules/dnn/include/opencv2/dnn.hpp modules/dnn/src/ modules/dnn/test/modules/dnn/perf/
gapi modules/gapi/include/opencv2/gapi.hpp modules/gapi/src/ modules/gapi/test/modules/gapi/perf/
stitching modules/stitching/include/opencv2/stitching.hpp modules/stitching/src/ modules/stitching/test/modules/stitching/perf/
objdetect modules/objdetect/include/opencv2/objdetect.hpp modules/objdetect/src/ modules/objdetect/test/modules/objdetect/perf/
photo modules/photo/include/opencv2/photo.hpp modules/photo/src/ modules/photo/test/modules/photo/perf/
ts modules/ts/include/opencv2/ts/ modules/ts/src/ 测试与 perf 的公共支撑
world modules/world/CMakeLists.txt 聚合其他模块 生成单一 opencv_world

4. Core:数据结构、基础运算与运行时

4.1 公开 API 与内部实现

主题 声明入口 实现入口
Mat、引用计数、ROI modules/core/include/opencv2/core/mat.hpp modules/core/src/matrix.cppmodules/core/src/matrix_wrap.cpp
Mat 迭代器 modules/core/include/opencv2/core/mat.hpp modules/core/src/matrix_iterator.cpp
矩阵分解 modules/core/include/opencv2/core.hpp modules/core/src/matrix_decomp.cpp
基础类型 modules/core/include/opencv2/core/types.hpp 多数为头内定义
错误码与基础宏 modules/core/include/opencv2/core/base.hpp modules/core/src/system.cpp
算术运算 modules/core/include/opencv2/core.hpp modules/core/src/arithm.cppmodules/core/src/arithm.dispatch.cpp
矩阵乘法 modules/core/include/opencv2/core.hpp modules/core/src/matmul.dispatch.cpp
统计与归约 modules/core/include/opencv2/core.hpp modules/core/src/stat_c.cppmodules/core/src/stat.dispatch.cpp
DFT/DCT modules/core/include/opencv2/core.hpp modules/core/src/dxt.cpp
线性代数/LAPACK 路径 modules/core/include/opencv2/core.hpp modules/core/src/lapack.cpp
CPU 与构建信息 modules/core/include/opencv2/core/utility.hpp modules/core/src/system.cpp
并行循环 modules/core/include/opencv2/core/utility.hpp modules/core/src/parallel.cppmodules/core/src/parallel/
文件存储 modules/core/include/opencv2/core/persistence.hpp modules/core/src/persistence.cpppersistence_xml.cpppersistence_yml.cpppersistence_json.cpp
OpenCL/UMat modules/core/include/opencv2/core/ocl.hpp modules/core/src/ocl.cppmodules/core/src/opencl/
CUDA 基础类型 modules/core/include/opencv2/core/cuda.hpp modules/core/src/cuda_host_mem.cpp
文件系统工具 modules/core/include/opencv2/core/utils/filesystem.hpp modules/core/src/utils/filesystem.cpp

4.2 Core 的分派、测试与性能入口

目的 文件
查看标量实现与 HAL 选择 modules/core/src/arithm.cpp
查看 CPU 分派包装 modules/core/src/arithm.dispatch.cpp
查看 SIMD 实现 modules/core/src/arithm.simd.hpp
查看 GEMM/乘法分派 modules/core/src/matmul.dispatch.cppmodules/core/src/matmul.simd.hpp
查看默认 HAL 回退 modules/core/src/hal_replacement.hpp
查看运行时并行后端注册 modules/core/src/parallel/registry_parallel.impl.hpp
算术正确性测试 modules/core/test/test_arithm.cpp
通用运算测试 modules/core/test/test_operations.cpp
矩阵性能 modules/core/perf/perf_mat.cpp
算术性能 modules/core/perf/perf_arithm.cpp
统计性能 modules/core/perf/perf_stat.cpp

5. Imgproc:图像处理主干

公开声明集中在 modules/imgproc/include/opencv2/imgproc.hpp;较细的分割接口还可见
modules/imgproc/include/opencv2/imgproc/segmentation.hpp

算法域 主要实现文件 典型测试或 perf
通用滤波引擎 modules/imgproc/src/filter.dispatch.cppfilterengine.hpp test/test_filter.cppperf/perf_filter2d.cpp
平滑与高斯滤波 modules/imgproc/src/smooth.dispatch.cppsmooth.simd.hpp test/test_filter.cpp
双边滤波 modules/imgproc/src/bilateral_filter.dispatch.cppbilateral_filter.simd.hpp test/test_filter.cpp
中值滤波 modules/imgproc/src/median_blur.dispatch.cpp test/test_filter.cpp
形态学 modules/imgproc/src/morph.dispatch.cppmorph.simd.hpp test/test_filter.cpp
颜色转换总入口 modules/imgproc/src/color.cpp test/test_color.cppperf/perf_cvt_color.cpp
RGB/灰度转换 modules/imgproc/src/color_rgb.dispatch.cppcolor_rgb.simd.hpp test/test_color.cpp
HSV 转换 modules/imgproc/src/color_hsv.dispatch.cppcolor_hsv.simd.hpp test/test_color.cpp
YUV 转换 modules/imgproc/src/color_yuv.dispatch.cppcolor_yuv.simd.hpp test/test_color.cpp
仿射/透视/重映射 modules/imgproc/src/imgwarp.cpp test/test_imgwarp.cppperf/perf_warp.cpp
缩放 modules/imgproc/src/resize.cpp test/test_imgwarp.cppperf/perf_warp.cpp
Canny modules/imgproc/src/canny.cpp test/test_canny.cpp
Sobel/Laplacian modules/imgproc/src/deriv.cpp test/test_filter.cpp
阈值 modules/imgproc/src/thresh.cpp test/test_thresh.cppperf/perf_threshold.cpp
直方图/反投影 modules/imgproc/src/histogram.cpp test/test_histograms.cpp
轮廓 modules/imgproc/src/contours.cppcontours_new.cppcontours_approx.cpp test/test_contours.cpptest/test_contours_new.cpp
几何与形状 modules/imgproc/src/geometry.cppconvhull.cpp test/test_convhull.cpp
连通组件 modules/imgproc/src/connectedcomponents.cpp test/test_connectedcomponents.cpp
分水岭 modules/imgproc/src/segmentation.cpp test/test_watershed.cpp
GrabCut modules/imgproc/src/grabcut.cpp test/test_grabcut.cpp
漫水填充 modules/imgproc/src/floodfill.cpp test/test_floodfill.cpp
霍夫变换 modules/imgproc/src/hough.cpp test/test_houghlines.cpptest/test_houghcircles.cpp
模板匹配 modules/imgproc/src/templmatch.cpp test/test_templmatch.cpp
绘制与文字 modules/imgproc/src/drawing.cpp test/test_drawing.cpp
OpenCL kernel modules/imgproc/src/opencl/ 各算法 OCL 测试

Imgproc HAL 的公开边界是 modules/imgproc/include/opencv2/imgproc/hal/hal.hpp
modules/imgproc/include/opencv2/imgproc/hal/interface.h,默认回退位于
modules/imgproc/src/hal_replacement.hpp

6. Features2d:检测、描述与匹配

公开 API 入口为 modules/features2d/include/opencv2/features2d.hpp

功能/API 实现 测试/perf
Feature2D 抽象 modules/features2d/src/feature2d.cpp test/test_detectors_invariance.cpp
KeyPoint 工具 modules/features2d/src/keypoint.cpp test/test_keypoints.cpp
FAST modules/features2d/src/fast.cpp test/test_fast.cppperf/perf_fast.cpp
AGAST modules/features2d/src/agast.cpp test/test_fast.cpp
ORB modules/features2d/src/orb.cpp test/test_orb.cpp
SIFT modules/features2d/src/sift.dispatch.cppsift.simd.hpp test/test_sift.cpp
BRISK modules/features2d/src/brisk.cpp test/test_brisk.cpp
KAZE/AKAZE modules/features2d/src/kaze.cppakaze.cppsrc/kaze/ test/test_akaze.cpp
BF/FLANN 匹配器 modules/features2d/src/matchers.cpp test/test_matchers_algorithmic.cpp
Bag of Words modules/features2d/src/bagofwords.cpp 结合匹配器测试验证
关键点与匹配绘制 modules/features2d/src/draw.cpp test/test_keypoints.cpp

定位特征算法时,先区分检测器、描述子和匹配器;ORB 等类可能同时提供检测和描述。

7. Calib3d:多视图几何与标定

公开入口为 modules/calib3d/include/opencv2/calib3d.hpp,兼容 C 接口位于
modules/calib3d/include/opencv2/calib3d/calib3d_c.h

功能/API 实现 测试/perf
相机标定 modules/calib3d/src/calibration.cpp test/test_cameracalibration.cpp
标定异常参数 modules/calib3d/src/calibration.cpp test/test_cameracalibration_badarg.cpp
PnP 总入口 modules/calib3d/src/solvepnp.cpp test/test_solvepnp_ransac.cpp
EPnP/SQPNP modules/calib3d/src/epnp.cppsqpnp.cpp test/test_solvepnp_ransac.cpp
基础矩阵/单应 modules/calib3d/src/fundam.cpp test/test_fundam.cpptest/test_homography.cpp
五点法 modules/calib3d/src/five-point.cpp test/test_fundam.cpp
USAC/RANSAC modules/calib3d/src/usac/ test/test_modelest.cpp
双目几何 modules/calib3d/src/stereo_geom.cpp test/test_stereomatching.cpp
StereoBM modules/calib3d/src/stereobm.cpp test/test_stereomatching.cpp
StereoSGBM modules/calib3d/src/stereosgbm.cpp test/test_stereomatching.cppperf/perf_stereosgbm.cpp
鱼眼模型 modules/calib3d/src/fisheye.cpp test/test_fisheye.cpp
去畸变 modules/calib3d/src/undistort.dispatch.cpp test/test_undistort.cppperf/perf_undistort.cpp
棋盘初始化 modules/calib3d/src/calibinit.cpp test/test_chesscorners.cpp
圆点阵 modules/calib3d/src/circlesgrid.cpp test/test_cameracalibration.cpp
棋盘快速检查 modules/calib3d/src/checkchessboard.cpp test/test_chesscorners.cpp

8. Video:光流、背景建模与跟踪

功能/API 声明 实现 验证入口
稀疏 LK 光流 modules/video/include/opencv2/video/tracking.hpp modules/video/src/lkpyramid.cpp modules/video/test/test_optflowpyrlk.cpp
Farneback 稠密光流 modules/video/include/opencv2/video/tracking.hpp modules/video/src/optflowgf.cpp modules/video/test/ocl/test_optflow_farneback.cpp
DIS 光流 modules/video/include/opencv2/video/tracking.hpp modules/video/src/dis_flow.cpp modules/video/perf/perf_disflow.cpp
MOG2 modules/video/include/opencv2/video/background_segm.hpp modules/video/src/bgfg_gaussmix2.cpp modules/video/perf/perf_bgfg_mog2.cpp
KNN 背景模型 modules/video/include/opencv2/video/background_segm.hpp modules/video/src/bgfg_KNN.cpp modules/video/test/test_bgfg2.cpp
Kalman modules/video/include/opencv2/video/tracking.hpp modules/video/src/kalman.cpp modules/video/test/test_kalman.cpp
CamShift/MeanShift modules/video/include/opencv2/video/tracking.hpp modules/video/src/camshift.cpp modules/video/test/test_camshift.cpp
Tracker 框架 modules/video/include/opencv2/video/tracking.hpp modules/video/src/tracking/ modules/video/test/test_trackers.cpp

9. 图像、窗口与视频 I/O

9.1 Imgcodecs

层次 文件 作用
公开 API modules/imgcodecs/include/opencv2/imgcodecs.hpp imreadimwriteimdecodeimencode
调度入口 modules/imgcodecs/src/loadsave.cpp 格式探测、解码器/编码器选择
编解码抽象 modules/imgcodecs/src/grfmts.hppgrfmt_base.cpp 基类和注册集合
JPEG modules/imgcodecs/src/grfmt_jpeg.cpp JPEG 读写
PNG modules/imgcodecs/src/grfmt_png.cpp PNG 读写
TIFF modules/imgcodecs/src/grfmt_tiff.cpp TIFF 读写
回归测试 modules/imgcodecs/test/test_read_write.cpp 通用读写
格式测试 modules/imgcodecs/test/test_jpeg.cpptest_png.cpptest_tiff.cpp 格式专项
性能 modules/imgcodecs/perf/perf_decode_encode.cpp 编解码吞吐

9.2 Highgui

路径 作用
modules/highgui/include/opencv2/highgui.hpp 窗口、事件、控件和图像显示 API
modules/highgui/src/window.cpp 通用窗口 API 与后端调用入口
modules/highgui/src/registry.impl.hpp UI 后端注册
modules/highgui/test/test_gui.cpp GUI 基础测试

9.3 Videoio

后端/功能 公开或实现入口 测试/perf
VideoCapture/VideoWriter modules/videoio/include/opencv2/videoio.hppsrc/cap.cpp test/test_video_io.cpp
后端枚举与查询 modules/videoio/include/opencv2/videoio/registry.hpp test/test_plugins.cpp
后端注册表 modules/videoio/src/videoio_registry.cpp test/test_dynamic.cpp
插件桥接 modules/videoio/src/backend_plugin.cpp test/test_plugins.cpp
FFmpeg modules/videoio/src/cap_ffmpeg.cppcap_ffmpeg_impl.hpp test/test_ffmpeg.cpp
GStreamer modules/videoio/src/cap_gstreamer.cpp test/test_gstreamer.cpp
Linux V4L/V4L2 modules/videoio/src/cap_v4l.cpp test/test_v4l2.cpp
图像序列 modules/videoio/src/cap_images.cpp test/test_images.cpp
Windows Media Foundation modules/videoio/src/cap_msmf.cpp test/test_camera.cpp
Apple AVFoundation modules/videoio/src/cap_avfoundation.mm 平台测试
输入性能 modules/videoio/perf/perf_input.cpp 解码/读取吞吐
输出性能 modules/videoio/perf/perf_output.cpp 编码/写入吞吐

10. DNN:模型导入、网络执行与后端

层次 路径 说明
聚合公开头 modules/dnn/include/opencv2/dnn.hpp 常用 DNN API
网络与模型 API modules/dnn/include/opencv2/dnn/dnn.hpp Net、blob、模型读取、NMS
层基类 modules/dnn/include/opencv2/dnn/layer.hpp Layer 生命周期与后端支持
层声明集合 modules/dnn/include/opencv2/dnn/all_layers.hpp 内置层类型
Net 外观 modules/dnn/src/net.cpp 公开成员函数入口
Net 内部执行 modules/dnn/src/net_impl.cpp 图、内存、forward 主逻辑
后端选择 modules/dnn/src/net_impl_backend.cpp backend/target 分派
通用模型读取 modules/dnn/src/dnn_read.cpp 按格式读取模型
层工厂 modules/dnn/src/layer_factory.cpp 层注册与构造
CPU 层实现 modules/dnn/src/layers/ 卷积、池化、激活、检测等
ONNX 导入 modules/dnn/src/onnx/onnx_importer.cpp ONNX 图解析与层转换
TensorFlow 导入 modules/dnn/src/tensorflow/tf_importer.cpp TensorFlow 图导入
Darknet 导入 modules/dnn/src/darknet/darknet_importer.cpp cfg/weights 导入
CUDA 后端 modules/dnn/src/cuda4dnn/ CUDA primitive、kernel 与封装
OpenCL kernel modules/dnn/src/opencl/ OpenCL 层内核
网络综合测试 modules/dnn/test/test_misc.cpp Net 行为与杂项回归
层测试 modules/dnn/test/test_layers.cpp 层正确性与后端对齐
ONNX 测试 modules/dnn/test/test_onnx_importer.cpp 导入回归
NMS 测试 modules/dnn/test/test_nms.cpp NMS 与边界条件
网络性能 modules/dnn/perf/perf_net.cpp 网络 forward 性能
层性能 modules/dnn/perf/perf_convolution3d.cpp 代表性的卷积基准

排查 DNN 数值差异时,应同时记录模型导入器、层实现、backend 和 target;只检查
net.cpp 往往无法看到真正的计算内核。

11. G-API:计算图、编译器与后端

层次 路径 说明
聚合头 modules/gapi/include/opencv2/gapi.hpp 常用图 API
图计算 modules/gapi/include/opencv2/gapi/gcomputation.hpp GComputation
图数据 modules/gapi/include/opencv2/gapi/gmat.hpp GMat 等图节点数据
Kernel 声明 modules/gapi/include/opencv2/gapi/gkernel.hpp 操作与实现包
流式输入 modules/gapi/include/opencv2/gapi/streaming/source.hpp 流源接口
图 API 实现 modules/gapi/src/api/gcomputation.cpp compile/apply 入口
编译器 modules/gapi/src/compiler/gcompiler.cpp 编译阶段组织
图模型 modules/gapi/src/compiler/gmodel.cpp 内部图表示
编译 passes modules/gapi/src/compiler/passes/ meta、islands、kernels、exec 等
CPU 后端 modules/gapi/src/backends/cpu/gcpubackend.cpp CPU kernel 执行
OpenCL 后端 modules/gapi/src/backends/ocl/goclbackend.cpp OCL 后端
Fluid 后端 modules/gapi/src/backends/fluid/gfluidbackend.cpp 流水化执行
核心测试 modules/gapi/test/gapi_mat_tests.cpp 图数据语义
流式测试 modules/gapi/test/streaming/gapi_streaming_tests.cpp streaming 行为
Fluid 测试 modules/gapi/test/gapi_fluid_test.cpp Fluid 后端

12. Stitching:全景拼接流水线

组件 公开声明 实现
高层 Stitcher modules/stitching/include/opencv2/stitching.hpp modules/stitching/src/stitcher.cpp
特征匹配 modules/stitching/include/opencv2/stitching/detail/matchers.hpp modules/stitching/src/matchers.cpp
运动估计与 BA modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp modules/stitching/src/motion_estimators.cpp
自动标定 modules/stitching/include/opencv2/stitching/detail/autocalib.hpp modules/stitching/src/autocalib.cpp
缝线搜索 modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp modules/stitching/src/seam_finders.cpp
曝光补偿 modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp modules/stitching/src/exposure_compensate.cpp
融合 modules/stitching/include/opencv2/stitching/detail/blenders.hpp modules/stitching/src/blenders.cpp
图像变换 modules/stitching/include/opencv2/stitching/warpers.hpp modules/stitching/src/warpers.cpp
匹配测试 modules/stitching/test/test_matchers.cpp 组件级验证
融合测试 modules/stitching/test/test_blenders.cpp 融合验证
性能 modules/stitching/perf/perf_stich.cpp 拼接性能入口

13. Objdetect:级联、HOG、二维码与 ArUco

功能 声明 实现/测试
级联分类器 modules/objdetect/include/opencv2/objdetect.hpp src/cascadedetect.cpptest/test_cascadeandhog.cpp
HOG 检测 modules/objdetect/include/opencv2/objdetect.hpp src/hog.cpptest/test_cascadeandhog.cpp
QRCode modules/objdetect/include/opencv2/objdetect.hpp src/qrcode.cpptest/test_qrcode.cpp
ArUco 检测器 modules/objdetect/include/opencv2/objdetect/aruco_detector.hpp src/aruco/aruco_detector.cpp
ArUco 字典 modules/objdetect/include/opencv2/objdetect/aruco_dictionary.hpp src/aruco/aruco_dictionary.cpp
Board modules/objdetect/include/opencv2/objdetect/aruco_board.hpp test/test_boarddetection.cpp
ChArUco modules/objdetect/include/opencv2/objdetect/charuco_detector.hpp src/aruco/
人脸接口 modules/objdetect/include/opencv2/objdetect/face.hpp modules/objdetect/src/

14. Photo:修复、克隆、去噪与 HDR

公开入口为 modules/photo/include/opencv2/photo.hpp,CUDA 相关声明位于
modules/photo/include/opencv2/photo/cuda.hpp

功能/API 实现 验证入口
图像修复 inpaint modules/photo/src/inpaint.cpp test/test_inpaint.cppperf/perf_inpaint.cpp
无缝克隆 modules/photo/src/seamless_cloning.cpp test/test_cloning.cpp
非局部均值去噪 modules/photo/src/denoising.cpp test/test_denoising.cpp
HDR 对齐 modules/photo/src/align.cpp test/test_hdr.cpp
相机响应标定 modules/photo/src/calibrate.cpp test/test_hdr.cpp
HDR 合并 modules/photo/src/merge.cpp test/test_hdr.cpp
色调映射 modules/photo/src/tonemap.cpp test/test_hdr.cpp
HDR 公共内部逻辑 modules/photo/src/hdr_common.cpp 由 HDR 各阶段共用

15. HAL、SIMD、OpenCL 与运行时分派

15.1 HAL 边界

路径 用途
modules/core/include/opencv2/core/hal/interface.h Core HAL C 风格接口与类型
modules/core/include/opencv2/core/hal/hal.hpp Core HAL 包装
modules/imgproc/include/opencv2/imgproc/hal/interface.h Imgproc HAL 接口
modules/imgproc/include/opencv2/imgproc/hal/hal.hpp Imgproc HAL 包装
modules/core/src/hal_replacement.hpp Core 默认实现映射
modules/imgproc/src/hal_replacement.hpp Imgproc 默认实现映射
modules/calib3d/src/hal_replacement.hpp Calib3d 默认 HAL 回退
modules/video/src/hal_replacement.hpp Video 默认 HAL 回退

15.2 通用 SIMD

路径 架构/作用
modules/core/include/opencv2/core/hal/intrin.hpp 通用 SIMD 聚合入口
modules/core/include/opencv2/core/hal/intrin_cpp.hpp 可移植向量抽象
modules/core/include/opencv2/core/hal/intrin_sse.hpp x86 SSE
modules/core/include/opencv2/core/hal/intrin_avx.hpp x86 AVX
modules/core/include/opencv2/core/hal/intrin_avx512.hpp x86 AVX-512
modules/core/include/opencv2/core/hal/intrin_neon.hpp Arm NEON
modules/core/include/opencv2/core/hal/intrin_vsx.hpp Power VSX
modules/core/include/opencv2/core/hal/intrin_wasm.hpp WebAssembly SIMD
modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp RISC-V 可伸缩向量
modules/core/include/opencv2/core/hal/intrin_lsx.hpp LoongArch LSX
modules/core/include/opencv2/core/hal/intrin_lasx.hpp LoongArch LASX

15.3 树内 HAL 实现

HAL 路径 主要目标
Carotene hal/carotene/ Arm NEON 优化
FastCV hal/fastcv/ Qualcomm FastCV
IPP hal/ipp/ Intel IPP
NDSRVP hal/ndsrvp/ Andes RVP/DSP
OpenVX hal/openvx/ OpenVX
RISC-V RVV hal/riscv-rvv/ RISC-V Vector
KleidiCV hal/kleidicv/ Arm KleidiCV
自定义 HAL 示例 samples/hal/c_hal/samples/hal/slow_hal/ 外接 HAL 的构建与替换方式

典型调用链是“公开 API → 普通入口 → HAL 宏/函数 → 外部 HAL 或默认替换 → SIMD/标量”。
若输入是 UMat,还可能在普通 CPU 路径之前进入 src/opencl/ 中的 kernel。

16. CMake:从模块声明到 CPU 分派

文件 定位价值
CMakeLists.txt 全局选项、平台初始化和模块构建入口
cmake/OpenCVModule.cmake ocv_define_module 等模块基础宏
cmake/OpenCVCompilerOptimizations.cmake CPU baseline/dispatch 检测和编译策略
cmake/OpenCVFindLibsGrfmt.cmake 图像格式依赖
cmake/OpenCVFindLibsGUI.cmake GUI 依赖
cmake/OpenCVFindLibsPerf.cmake 性能相关依赖
cmake/templates/cvconfig.h.in 生成构建能力宏
cmake/templates/OpenCVConfig.cmake.in 安装后的 CMake 包配置
modules/core/CMakeLists.txt Core、并行与 CPU 分派
modules/imgproc/CMakeLists.txt Imgproc 源文件与 HAL
modules/videoio/CMakeLists.txt 视频后端条件编译
modules/dnn/CMakeLists.txt DNN 模型格式与后端
modules/gapi/CMakeLists.txt G-API 后端与依赖
modules/world/CMakeLists.txt 聚合动态/静态库

阅读 .dispatch.cpp 时,同时在模块 CMakeLists.txt 中搜索
ocv_add_dispatched_file,可确认哪些源码会按 ISA 生成多个编译变体。

17. 语言绑定

17.1 Python

路径 作用
modules/python/CMakeLists.txt Python 模块总构建入口
modules/python/bindings/CMakeLists.txt 绑定生成目标
modules/python/python3/CMakeLists.txt Python 3 扩展构建
modules/python/src2/hdr_parser.py 解析带导出标注的 C++ 头
modules/python/src2/gen2.py 生成 C++ Python 包装代码
modules/python/src2/typing_stubs_generation/ 生成 Python 类型提示
modules/python/test/test_mat.py Mat/ndarray 行为
modules/python/test/test_features2d.py 特征 API 绑定
modules/python/test/test_imread.py 图像读取绑定
modules/python/test/tests_common.py Python 测试公共设施

Python API 不一定有手写的同名包装函数;应先查 C++ 公开头上的导出标注,再查生成器。

17.2 Java

路径 作用
modules/java/CMakeLists.txt Java 模块入口
modules/java/jni/CMakeLists.txt JNI 本地库构建
modules/java/generator/gen_java.py Java/JNI 代码生成
modules/java/generator/src/cpp/opencv_java.cpp 本地绑定公共入口
modules/java/generator/src/cpp/Mat.cpp Mat 的 JNI 支撑
modules/java/generator/src/cpp/converters.cpp Java/C++ 类型转换
modules/java/generator/src/java/org/opencv/utils/Converters.java Java 侧转换工具
modules/java/test/pure_test/src/ Java 绑定测试

17.3 JavaScript

路径 作用
modules/js/generator/CMakeLists.txt JS 绑定生成
modules/js/generator/embindgen.py Embind 包装生成
modules/js/src/core_bindings.cpp 手写核心绑定
modules/js/src/helpers.js JS 运行时辅助
modules/js/src/make_umd.py UMD 输出辅助
platforms/js/build_js.py WebAssembly/JS 构建入口
platforms/js/opencv_js.config.py 导出 API 配置
modules/js/test/test_core.js Core JS 测试
modules/js/test/test_imgproc.js Imgproc JS 测试
modules/js/test/test_calib3d.js Calib3d JS 测试

Objective-C 构建入口可从 modules/objc/CMakeLists.txt
modules/objc/generator/CMakeLists.txt 开始。

18. 测试与性能基准的阅读方法

目录/文件 作用
modules/ts/include/opencv2/ts/ OpenCV 测试系统的断言、数据和性能宏
modules/ts/CMakeLists.txt 测试支撑库构建
modules/<name>/test/test_main.cpp 模块测试程序入口
modules/<name>/test/test_*.cpp 正确性、边界、回归和坏参数测试
modules/<name>/perf/perf_main.cpp 模块性能程序入口
modules/<name>/perf/perf_*.cpp 参数化性能用例

19. 从 API 找到声明、实现、测试和 perf

以一个 API 名称 foo 为例,可按下列顺序查找:

  1. modules/*/include/opencv2/ 搜索 foo,确认命名空间、重载和默认参数;
  2. modules/*/src/ 搜索 foo( 或类的 ClassName::foo
  3. 若入口只有包装,继续跟踪 CV_OCL_RUNCALL_HALCV_CPU_DISPATCH
  4. 查看同目录的 .dispatch.cpp.simd.hppsrc/opencl/*.cl
  5. modules/*/test/ 搜索 API 名、测试夹具名和相关枚举;
  6. modules/*/perf/ 搜索 API 名,确认性能参数;
  7. samples/ 搜索调用方式,观察输入准备和完整数据流;
  8. 在模块 CMakeLists.txt 中确认文件是否受平台或依赖条件控制。

19.1 常见“搜索不到实现”的原因

现象 应继续检查
只找到头文件声明 搜索类成员限定名、宏展开后的底层名字
实现只做参数检查 查后续内部函数、HAL、IPP、OpenCL 或 backend
找到 .dispatch.cpp 再查同名前缀的 .simd.hpp
找到工厂函数 查注册表、创建器和具体派生类
Python/Java 名称与 C++ 不同 查绑定生成器和公开头导出标注
Videoio 在不同机器行为不同 查后端注册表、插件和构建配置
DNN 结果依设备而异 查 backend、target、层支持判断和 fallback

20. 任务到源码速查

任务 首选源码入口
研究 Mat 浅拷贝和引用计数 modules/core/src/matrix.cpp
研究 ROI/步长/连续性 modules/core/include/opencv2/core/mat.hppsrc/matrix.cpp
优化加减乘除 modules/core/src/arithm.cpparithm.dispatch.cpparithm.simd.hpp
优化矩阵乘法 modules/core/src/matmul.dispatch.cppmatmul.simd.hpp
修改 GaussianBlur modules/imgproc/src/smooth.dispatch.cppsmooth.simd.hpp
修改 resize/remap/warp modules/imgproc/src/resize.cppimgwarp.cpp
修改颜色转换 modules/imgproc/src/color.cppcolor_*.dispatch.cpp
修改 Canny modules/imgproc/src/canny.cppsrc/opencl/canny.cl
修改轮廓算法 modules/imgproc/src/contours.cppcontours_new.cpp
修改 ORB/SIFT modules/features2d/src/orb.cppsift.dispatch.cpp
修改匹配器 modules/features2d/src/matchers.cpp
修改单应/RANSAC modules/calib3d/src/fundam.cppsrc/usac/
修改标定/PnP modules/calib3d/src/calibration.cppsolvepnp.cpp
修改光流 modules/video/src/lkpyramid.cppoptflowgf.cppdis_flow.cpp
排查摄像头打不开 modules/videoio/src/cap.cppvideoio_registry.cpp、具体后端
添加视频后端 modules/videoio/src/backend_plugin.cppvideoio_registry.cpp
添加图像格式 modules/imgcodecs/src/loadsave.cppgrfmts.hpp、对应 grfmt_*
修改 DNN 模型导入 modules/dnn/src/onnx/tensorflow/darknet/
添加 DNN 层 modules/dnn/src/layers/layer_factory.cpp
排查 DNN backend fallback modules/dnn/src/net_impl_backend.cpp
修改 G-API 图编译 modules/gapi/src/compiler/
修改拼接接缝/融合 modules/stitching/src/seam_finders.cppblenders.cpp
修改 QR/ArUco modules/objdetect/src/qrcode.cppsrc/aruco/
修改修复/克隆 modules/photo/src/inpaint.cppseamless_cloning.cpp
添加 Python 暴露 C++ 公开头、modules/python/src2/
添加 JS 暴露 platforms/js/opencv_js.config.pymodules/js/generator/

21. 推荐断点

调试目标 推荐断点
Mat 分配/释放 modules/core/src/matrix.cppMat::createMat::release
错误抛出 modules/core/src/system.cppcv::error
CPU 能力与优化开关 modules/core/src/system.cpp 中硬件支持查询
算术调用链 modules/core/src/arithm.cpp 中对应公开函数
并行执行 modules/core/src/parallel.cppparallel_for_
OpenCL 是否启用 modules/core/src/ocl.cppuseOpenCL 相关逻辑
图像读取 modules/imgcodecs/src/loadsave.cppimread_
图像写入 modules/imgcodecs/src/loadsave.cppimwrite_
视频后端选择 modules/videoio/src/cap.cppVideoCapture::open
后端注册 modules/videoio/src/videoio_registry.cpp 中 backend 查询
特征匹配 modules/features2d/src/matchers.cppDescriptorMatcher 调用
单应估计 modules/calib3d/src/fundam.cppfindHomography
PnP modules/calib3d/src/solvepnp.cppsolvePnP
DNN forward modules/dnn/src/net.cppNet::forward
DNN 内部执行 modules/dnn/src/net_impl.cpp 中 forward 相关内部函数
DNN 后端选择 modules/dnn/src/net_impl_backend.cpp 中后端初始化
G-API 编译 modules/gapi/src/compiler/gcompiler.cpp 中编译入口
拼接主流程 modules/stitching/src/stitcher.cppestimateTransformcomposePanorama
ArUco 检测 modules/objdetect/src/aruco/aruco_detector.cppdetectMarkers

断点若始终不命中,先确认是否走 OpenCL、IPP、插件、CUDA 或 CPU 分派版本,并核对当前
构建是否包含调试符号。

22. 二次开发的典型修改点

目标 最小修改范围 必须补充
新增普通 C++ API 模块公开头、src/ 实现 文档注释、正确性测试
新增可导出的绑定 API 公开头及生成器可识别标注 Python/Java/JS 对应测试
新增图像处理算法 modules/imgproc/include/src/ 边界测试、类型组合、perf
新增 SIMD 路径 .dispatch.cpp.simd.hpp、模块 CMake 标量一致性和多 ISA 构建
新增 HAL 实现 HAL 接口、外部实现、CMake 默认回退和不支持返回语义
新增 OpenCL 路径 CPU 入口、src/opencl/*.cl CPU/OCL 结果一致性测试
新增 Videoio 后端 后端实现、注册表、模块 CMake 插件/静态构建、属性测试
新增 DNN 层 层声明/实现、层工厂 导入映射、各后端 fallback、测试
新增 G-API kernel G-API 声明、后端实现 kernel package 和编译测试
修改拼接组件 stitching/detail 接口和对应实现 单组件测试与端到端样例
新增 ArUco 字典/检测逻辑 objdetect 公开头与 src/aruco/ 字典、旋转、误码测试

修改原则:先保留可靠的标量实现,再增加加速路径;先补最小回归测试,再运行宽参数 perf。

23. 官方 Demo 到源码映射

Demo 展示主题 反查源码
samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp Mat 所有权与构造 modules/core/src/matrix.cpp
samples/cpp/tutorial_code/core/mat_operations/mat_operations.cpp 矩阵访问与操作 modules/core/include/opencv2/core/mat.hpp
samples/cpp/edge.cpp 灰度、模糊、Canny modules/imgproc/src/canny.cppsmooth.dispatch.cpp
samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp 多种平滑 modules/imgproc/src/smooth.dispatch.cpp
samples/cpp/tutorial_code/ImgProc/Threshold.cpp 阈值 modules/imgproc/src/thresh.cpp
samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp 轮廓 modules/imgproc/src/contours.cpp
samples/cpp/tutorial_code/ImgTrans/houghlines.cpp 霍夫线 modules/imgproc/src/hough.cpp
samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp 模板匹配 modules/imgproc/src/templmatch.cpp
samples/cpp/tutorial_code/features2D/AKAZE_match.cpp AKAZE 与匹配 modules/features2d/src/akaze.cppmatchers.cpp
samples/python/find_obj.py 特征、匹配、单应 features2dcalib3d/src/fundam.cpp
samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp 相机标定 modules/calib3d/src/calibration.cpp
samples/cpp/stereo_match.cpp 双目匹配 modules/calib3d/src/stereobm.cppstereosgbm.cpp
samples/python/opt_flow.py 稀疏光流 modules/video/src/lkpyramid.cpp
samples/cpp/tutorial_code/video/optical_flow/optical_flow_dense.cpp 稠密光流 modules/video/src/optflowgf.cpp
samples/cpp/tutorial_code/video/bg_sub.cpp 背景建模 modules/video/src/bgfg_gaussmix2.cpp
samples/cpp/kalman.cpp Kalman modules/video/src/kalman.cpp
samples/cpp/videocapture_basic.cpp 摄像头读取 modules/videoio/src/cap.cpp
samples/cpp/facedetect.cpp 级联人脸检测 modules/objdetect/src/cascadedetect.cpp
samples/cpp/peopledetect.cpp HOG 行人检测 modules/objdetect/src/hog.cpp
samples/cpp/tutorial_code/photo/seamless_cloning/cloning_demo.cpp 无缝克隆 modules/photo/src/seamless_cloning.cpp
samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp HDR 流水线 modules/photo/src/align.cppcalibrate.cppmerge.cpptonemap.cpp
samples/dnn/object_detection.cpp DNN 目标检测 modules/dnn/src/net.cppnet_impl.cpp
samples/dnn/segmentation.cpp DNN 语义分割 modules/dnn/src/layers/
samples/dnn/face_detect.cpp DNN 人脸检测 modules/dnn/src/onnx/ 与网络执行层

24. 推荐阅读路线

  1. modules/core/include/opencv2/core/mat.hppmodules/core/src/matrix.cpp 理解数据模型。
  2. 选择一个熟悉的 Imgproc API,对照公开声明、CPU 实现、测试和 perf。
  3. 阅读一个 .dispatch.cpp 与其 .simd.hpp,理解 CPU 分派。
  4. 对照 hal_replacement.hpphal/,理解默认实现与外接实现。
  5. 阅读 Features2d → Calib3d 的匹配与几何估计链。
  6. 阅读 Videoio 的注册表与两个不同平台后端,理解运行时选择。
  7. 阅读 DNN 的导入器 → Net → layer → backend 数据流。
  8. 阅读 G-API 的 API → 图模型 → passes → backend 编译流程。
  9. 最后回到根 CMakeLists.txtcmake/OpenCVModule.cmake 和模块 CMake 串联构建。