<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>fish</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>http://example.com/</id>
  <link href="http://example.com/" rel="alternate"/>
  <link href="http://example.com/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, fish</rights>
  <subtitle>专注嵌入式开发</subtitle>
  <title>fishBlog</title>
  <updated>2026-09-16T03:49:31.699Z</updated>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="OpenCV-4-13-0-源码文件索引与导航"><a href="#OpenCV-4-13-0-源码文件索引与导航" class="headerlink" title="OpenCV 4.13.0 源码文件索引与导航"></a>OpenCV 4.13.0 源码文件索引与导航</h1><h2 id="1-使用范围与路径约定"><a href="#1-使用范围与路径约定" class="headerlink" title="1. 使用范围与路径约定"></a>1. 使用范围与路径约定</h2><p>本文是一份可独立使用的 OpenCV 4.13.0 源码导航，内容按源码树实际文件核验。</p><ul><li>所有路径都相对于源码根目录 <code>opencv-4.13.0/</code>。</li><li>“公开头”指安装后供使用者包含的头文件；“内部头”通常只参与 OpenCV 自身编译。</li><li><code>src/</code> 是实现主入口，<code>test/</code> 是正确性与回归测试，<code>perf/</code> 是性能基准。</li><li>同一 API 可能经过分派层、HAL、第三方库或硬件后端，不能只凭第一个同名函数判断最终执行位置。</li><li>本文不依赖同目录或上级目录中的其他说明文档。</li></ul><p>建议按“公开声明 → 普通实现 → 分派&#x2F;HAL → 测试 → perf → Demo”的顺序阅读。</p><h2 id="2-根目录导航"><a href="#2-根目录导航" class="headerlink" title="2. 根目录导航"></a>2. 根目录导航</h2><table><thead><tr><th>路径</th><th>作用</th><th>阅读重点</th></tr></thead><tbody><tr><td><code>CMakeLists.txt</code></td><td>全工程构建入口</td><td>版本、平台、全局选项、模块扫描、HAL 与第三方依赖</td></tr><tr><td><code>cmake/</code></td><td>CMake 基础设施</td><td>模块声明、CPU 分派、依赖探测、安装与包导出</td></tr><tr><td><code>modules/</code></td><td>OpenCV 主模块</td><td>每个模块一般含公开头、实现、测试、性能测试</td></tr><tr><td><code>include/opencv2/opencv.hpp</code></td><td>常用聚合头</td><td>汇总主要模块头，适合应用，不适合定位具体声明</td></tr><tr><td><code>hal/</code></td><td>树内可选 HAL 实现</td><td>Carotene、FastCV、IPP、OpenVX、RVV、KleidiCV 等</td></tr><tr><td><code>3rdparty/</code></td><td>随源码构建的第三方组件</td><td>图像格式、并行库、模型格式等可选依赖</td></tr><tr><td><code>apps/</code></td><td>官方命令行工具</td><td>标注、级联训练、模型诊断、交互标定等完整应用</td></tr><tr><td><code>samples/</code></td><td>C++、Python、DNN、G-API 等示例</td><td>从 API 用法反查模块和源码的首选入口</td></tr><tr><td><code>platforms/</code></td><td>平台构建与交叉编译</td><td>Android、Apple、JavaScript、Linux 工具链与打包</td></tr><tr><td><code>data/</code></td><td>运行示例所需数据</td><td>Haar&#x2F;LBP 分类器和算法数据</td></tr><tr><td><code>doc/</code></td><td>官方文档源文件</td><td>API 分组、教程和构建文档源</td></tr><tr><td><code>LICENSE</code></td><td>项目许可证</td><td>二次分发前应核对</td></tr><tr><td><code>README.md</code></td><td>项目入口说明</td><td>支持平台、构建和项目概况</td></tr></tbody></table><h2 id="3-模块总览"><a href="#3-模块总览" class="headerlink" title="3. 模块总览"></a>3. 模块总览</h2><table><thead><tr><th>模块</th><th>主要公开头</th><th>主要实现目录</th><th>测试&#x2F;性能</th></tr></thead><tbody><tr><td>core</td><td><code>modules/core/include/opencv2/core.hpp</code>、<code>modules/core/include/opencv2/core/</code></td><td><code>modules/core/src/</code></td><td><code>modules/core/test/</code>、<code>modules/core/perf/</code></td></tr><tr><td>imgproc</td><td><code>modules/imgproc/include/opencv2/imgproc.hpp</code></td><td><code>modules/imgproc/src/</code></td><td><code>modules/imgproc/test/</code>、<code>modules/imgproc/perf/</code></td></tr><tr><td>imgcodecs</td><td><code>modules/imgcodecs/include/opencv2/imgcodecs.hpp</code></td><td><code>modules/imgcodecs/src/</code></td><td><code>modules/imgcodecs/test/</code>、<code>modules/imgcodecs/perf/</code></td></tr><tr><td>highgui</td><td><code>modules/highgui/include/opencv2/highgui.hpp</code></td><td><code>modules/highgui/src/</code></td><td><code>modules/highgui/test/</code></td></tr><tr><td>features2d</td><td><code>modules/features2d/include/opencv2/features2d.hpp</code></td><td><code>modules/features2d/src/</code></td><td><code>modules/features2d/test/</code>、<code>modules/features2d/perf/</code></td></tr><tr><td>calib3d</td><td><code>modules/calib3d/include/opencv2/calib3d.hpp</code></td><td><code>modules/calib3d/src/</code></td><td><code>modules/calib3d/test/</code>、<code>modules/calib3d/perf/</code></td></tr><tr><td>video</td><td><code>modules/video/include/opencv2/video.hpp</code>、<code>modules/video/include/opencv2/video/</code></td><td><code>modules/video/src/</code></td><td><code>modules/video/test/</code>、<code>modules/video/perf/</code></td></tr><tr><td>videoio</td><td><code>modules/videoio/include/opencv2/videoio.hpp</code></td><td><code>modules/videoio/src/</code></td><td><code>modules/videoio/test/</code>、<code>modules/videoio/perf/</code></td></tr><tr><td>dnn</td><td><code>modules/dnn/include/opencv2/dnn.hpp</code></td><td><code>modules/dnn/src/</code></td><td><code>modules/dnn/test/</code>、<code>modules/dnn/perf/</code></td></tr><tr><td>gapi</td><td><code>modules/gapi/include/opencv2/gapi.hpp</code></td><td><code>modules/gapi/src/</code></td><td><code>modules/gapi/test/</code>、<code>modules/gapi/perf/</code></td></tr><tr><td>stitching</td><td><code>modules/stitching/include/opencv2/stitching.hpp</code></td><td><code>modules/stitching/src/</code></td><td><code>modules/stitching/test/</code>、<code>modules/stitching/perf/</code></td></tr><tr><td>objdetect</td><td><code>modules/objdetect/include/opencv2/objdetect.hpp</code></td><td><code>modules/objdetect/src/</code></td><td><code>modules/objdetect/test/</code>、<code>modules/objdetect/perf/</code></td></tr><tr><td>photo</td><td><code>modules/photo/include/opencv2/photo.hpp</code></td><td><code>modules/photo/src/</code></td><td><code>modules/photo/test/</code>、<code>modules/photo/perf/</code></td></tr><tr><td>ts</td><td><code>modules/ts/include/opencv2/ts/</code></td><td><code>modules/ts/src/</code></td><td>测试与 perf 的公共支撑</td></tr><tr><td>world</td><td><code>modules/world/CMakeLists.txt</code></td><td>聚合其他模块</td><td>生成单一 <code>opencv_world</code> 库</td></tr></tbody></table><h2 id="4-Core：数据结构、基础运算与运行时"><a href="#4-Core：数据结构、基础运算与运行时" class="headerlink" title="4. Core：数据结构、基础运算与运行时"></a>4. Core：数据结构、基础运算与运行时</h2><h3 id="4-1-公开-API-与内部实现"><a href="#4-1-公开-API-与内部实现" class="headerlink" title="4.1 公开 API 与内部实现"></a>4.1 公开 API 与内部实现</h3><table><thead><tr><th>主题</th><th>声明入口</th><th>实现入口</th></tr></thead><tbody><tr><td><code>Mat</code>、引用计数、ROI</td><td><code>modules/core/include/opencv2/core/mat.hpp</code></td><td><code>modules/core/src/matrix.cpp</code>、<code>modules/core/src/matrix_wrap.cpp</code></td></tr><tr><td><code>Mat</code> 迭代器</td><td><code>modules/core/include/opencv2/core/mat.hpp</code></td><td><code>modules/core/src/matrix_iterator.cpp</code></td></tr><tr><td>矩阵分解</td><td><code>modules/core/include/opencv2/core.hpp</code></td><td><code>modules/core/src/matrix_decomp.cpp</code></td></tr><tr><td>基础类型</td><td><code>modules/core/include/opencv2/core/types.hpp</code></td><td>多数为头内定义</td></tr><tr><td>错误码与基础宏</td><td><code>modules/core/include/opencv2/core/base.hpp</code></td><td><code>modules/core/src/system.cpp</code></td></tr><tr><td>算术运算</td><td><code>modules/core/include/opencv2/core.hpp</code></td><td><code>modules/core/src/arithm.cpp</code>、<code>modules/core/src/arithm.dispatch.cpp</code></td></tr><tr><td>矩阵乘法</td><td><code>modules/core/include/opencv2/core.hpp</code></td><td><code>modules/core/src/matmul.dispatch.cpp</code></td></tr><tr><td>统计与归约</td><td><code>modules/core/include/opencv2/core.hpp</code></td><td><code>modules/core/src/stat_c.cpp</code>、<code>modules/core/src/stat.dispatch.cpp</code></td></tr><tr><td>DFT&#x2F;DCT</td><td><code>modules/core/include/opencv2/core.hpp</code></td><td><code>modules/core/src/dxt.cpp</code></td></tr><tr><td>线性代数&#x2F;LAPACK 路径</td><td><code>modules/core/include/opencv2/core.hpp</code></td><td><code>modules/core/src/lapack.cpp</code></td></tr><tr><td>CPU 与构建信息</td><td><code>modules/core/include/opencv2/core/utility.hpp</code></td><td><code>modules/core/src/system.cpp</code></td></tr><tr><td>并行循环</td><td><code>modules/core/include/opencv2/core/utility.hpp</code></td><td><code>modules/core/src/parallel.cpp</code>、<code>modules/core/src/parallel/</code></td></tr><tr><td>文件存储</td><td><code>modules/core/include/opencv2/core/persistence.hpp</code></td><td><code>modules/core/src/persistence.cpp</code>、<code>persistence_xml.cpp</code>、<code>persistence_yml.cpp</code>、<code>persistence_json.cpp</code></td></tr><tr><td>OpenCL&#x2F;UMat</td><td><code>modules/core/include/opencv2/core/ocl.hpp</code></td><td><code>modules/core/src/ocl.cpp</code>、<code>modules/core/src/opencl/</code></td></tr><tr><td>CUDA 基础类型</td><td><code>modules/core/include/opencv2/core/cuda.hpp</code></td><td><code>modules/core/src/cuda_host_mem.cpp</code></td></tr><tr><td>文件系统工具</td><td><code>modules/core/include/opencv2/core/utils/filesystem.hpp</code></td><td><code>modules/core/src/utils/filesystem.cpp</code></td></tr></tbody></table><h3 id="4-2-Core-的分派、测试与性能入口"><a href="#4-2-Core-的分派、测试与性能入口" class="headerlink" title="4.2 Core 的分派、测试与性能入口"></a>4.2 Core 的分派、测试与性能入口</h3><table><thead><tr><th>目的</th><th>文件</th></tr></thead><tbody><tr><td>查看标量实现与 HAL 选择</td><td><code>modules/core/src/arithm.cpp</code></td></tr><tr><td>查看 CPU 分派包装</td><td><code>modules/core/src/arithm.dispatch.cpp</code></td></tr><tr><td>查看 SIMD 实现</td><td><code>modules/core/src/arithm.simd.hpp</code></td></tr><tr><td>查看 GEMM&#x2F;乘法分派</td><td><code>modules/core/src/matmul.dispatch.cpp</code>、<code>modules/core/src/matmul.simd.hpp</code></td></tr><tr><td>查看默认 HAL 回退</td><td><code>modules/core/src/hal_replacement.hpp</code></td></tr><tr><td>查看运行时并行后端注册</td><td><code>modules/core/src/parallel/registry_parallel.impl.hpp</code></td></tr><tr><td>算术正确性测试</td><td><code>modules/core/test/test_arithm.cpp</code></td></tr><tr><td>通用运算测试</td><td><code>modules/core/test/test_operations.cpp</code></td></tr><tr><td>矩阵性能</td><td><code>modules/core/perf/perf_mat.cpp</code></td></tr><tr><td>算术性能</td><td><code>modules/core/perf/perf_arithm.cpp</code></td></tr><tr><td>统计性能</td><td><code>modules/core/perf/perf_stat.cpp</code></td></tr></tbody></table><h2 id="5-Imgproc：图像处理主干"><a href="#5-Imgproc：图像处理主干" class="headerlink" title="5. Imgproc：图像处理主干"></a>5. Imgproc：图像处理主干</h2><p>公开声明集中在 <code>modules/imgproc/include/opencv2/imgproc.hpp</code>；较细的分割接口还可见<br><code>modules/imgproc/include/opencv2/imgproc/segmentation.hpp</code>。</p><table><thead><tr><th>算法域</th><th>主要实现文件</th><th>典型测试或 perf</th></tr></thead><tbody><tr><td>通用滤波引擎</td><td><code>modules/imgproc/src/filter.dispatch.cpp</code>、<code>filterengine.hpp</code></td><td><code>test/test_filter.cpp</code>、<code>perf/perf_filter2d.cpp</code></td></tr><tr><td>平滑与高斯滤波</td><td><code>modules/imgproc/src/smooth.dispatch.cpp</code>、<code>smooth.simd.hpp</code></td><td><code>test/test_filter.cpp</code></td></tr><tr><td>双边滤波</td><td><code>modules/imgproc/src/bilateral_filter.dispatch.cpp</code>、<code>bilateral_filter.simd.hpp</code></td><td><code>test/test_filter.cpp</code></td></tr><tr><td>中值滤波</td><td><code>modules/imgproc/src/median_blur.dispatch.cpp</code></td><td><code>test/test_filter.cpp</code></td></tr><tr><td>形态学</td><td><code>modules/imgproc/src/morph.dispatch.cpp</code>、<code>morph.simd.hpp</code></td><td><code>test/test_filter.cpp</code></td></tr><tr><td>颜色转换总入口</td><td><code>modules/imgproc/src/color.cpp</code></td><td><code>test/test_color.cpp</code>、<code>perf/perf_cvt_color.cpp</code></td></tr><tr><td>RGB&#x2F;灰度转换</td><td><code>modules/imgproc/src/color_rgb.dispatch.cpp</code>、<code>color_rgb.simd.hpp</code></td><td><code>test/test_color.cpp</code></td></tr><tr><td>HSV 转换</td><td><code>modules/imgproc/src/color_hsv.dispatch.cpp</code>、<code>color_hsv.simd.hpp</code></td><td><code>test/test_color.cpp</code></td></tr><tr><td>YUV 转换</td><td><code>modules/imgproc/src/color_yuv.dispatch.cpp</code>、<code>color_yuv.simd.hpp</code></td><td><code>test/test_color.cpp</code></td></tr><tr><td>仿射&#x2F;透视&#x2F;重映射</td><td><code>modules/imgproc/src/imgwarp.cpp</code></td><td><code>test/test_imgwarp.cpp</code>、<code>perf/perf_warp.cpp</code></td></tr><tr><td>缩放</td><td><code>modules/imgproc/src/resize.cpp</code></td><td><code>test/test_imgwarp.cpp</code>、<code>perf/perf_warp.cpp</code></td></tr><tr><td>Canny</td><td><code>modules/imgproc/src/canny.cpp</code></td><td><code>test/test_canny.cpp</code></td></tr><tr><td>Sobel&#x2F;Laplacian</td><td><code>modules/imgproc/src/deriv.cpp</code></td><td><code>test/test_filter.cpp</code></td></tr><tr><td>阈值</td><td><code>modules/imgproc/src/thresh.cpp</code></td><td><code>test/test_thresh.cpp</code>、<code>perf/perf_threshold.cpp</code></td></tr><tr><td>直方图&#x2F;反投影</td><td><code>modules/imgproc/src/histogram.cpp</code></td><td><code>test/test_histograms.cpp</code></td></tr><tr><td>轮廓</td><td><code>modules/imgproc/src/contours.cpp</code>、<code>contours_new.cpp</code>、<code>contours_approx.cpp</code></td><td><code>test/test_contours.cpp</code>、<code>test/test_contours_new.cpp</code></td></tr><tr><td>几何与形状</td><td><code>modules/imgproc/src/geometry.cpp</code>、<code>convhull.cpp</code></td><td><code>test/test_convhull.cpp</code></td></tr><tr><td>连通组件</td><td><code>modules/imgproc/src/connectedcomponents.cpp</code></td><td><code>test/test_connectedcomponents.cpp</code></td></tr><tr><td>分水岭</td><td><code>modules/imgproc/src/segmentation.cpp</code></td><td><code>test/test_watershed.cpp</code></td></tr><tr><td>GrabCut</td><td><code>modules/imgproc/src/grabcut.cpp</code></td><td><code>test/test_grabcut.cpp</code></td></tr><tr><td>漫水填充</td><td><code>modules/imgproc/src/floodfill.cpp</code></td><td><code>test/test_floodfill.cpp</code></td></tr><tr><td>霍夫变换</td><td><code>modules/imgproc/src/hough.cpp</code></td><td><code>test/test_houghlines.cpp</code>、<code>test/test_houghcircles.cpp</code></td></tr><tr><td>模板匹配</td><td><code>modules/imgproc/src/templmatch.cpp</code></td><td><code>test/test_templmatch.cpp</code></td></tr><tr><td>绘制与文字</td><td><code>modules/imgproc/src/drawing.cpp</code></td><td><code>test/test_drawing.cpp</code></td></tr><tr><td>OpenCL kernel</td><td><code>modules/imgproc/src/opencl/</code></td><td>各算法 OCL 测试</td></tr></tbody></table><p>Imgproc HAL 的公开边界是 <code>modules/imgproc/include/opencv2/imgproc/hal/hal.hpp</code> 和<br><code>modules/imgproc/include/opencv2/imgproc/hal/interface.h</code>，默认回退位于<br><code>modules/imgproc/src/hal_replacement.hpp</code>。</p><h2 id="6-Features2d：检测、描述与匹配"><a href="#6-Features2d：检测、描述与匹配" class="headerlink" title="6. Features2d：检测、描述与匹配"></a>6. Features2d：检测、描述与匹配</h2><p>公开 API 入口为 <code>modules/features2d/include/opencv2/features2d.hpp</code>。</p><table><thead><tr><th>功能&#x2F;API</th><th>实现</th><th>测试&#x2F;perf</th></tr></thead><tbody><tr><td><code>Feature2D</code> 抽象</td><td><code>modules/features2d/src/feature2d.cpp</code></td><td><code>test/test_detectors_invariance.cpp</code></td></tr><tr><td><code>KeyPoint</code> 工具</td><td><code>modules/features2d/src/keypoint.cpp</code></td><td><code>test/test_keypoints.cpp</code></td></tr><tr><td>FAST</td><td><code>modules/features2d/src/fast.cpp</code></td><td><code>test/test_fast.cpp</code>、<code>perf/perf_fast.cpp</code></td></tr><tr><td>AGAST</td><td><code>modules/features2d/src/agast.cpp</code></td><td><code>test/test_fast.cpp</code></td></tr><tr><td>ORB</td><td><code>modules/features2d/src/orb.cpp</code></td><td><code>test/test_orb.cpp</code></td></tr><tr><td>SIFT</td><td><code>modules/features2d/src/sift.dispatch.cpp</code>、<code>sift.simd.hpp</code></td><td><code>test/test_sift.cpp</code></td></tr><tr><td>BRISK</td><td><code>modules/features2d/src/brisk.cpp</code></td><td><code>test/test_brisk.cpp</code></td></tr><tr><td>KAZE&#x2F;AKAZE</td><td><code>modules/features2d/src/kaze.cpp</code>、<code>akaze.cpp</code>、<code>src/kaze/</code></td><td><code>test/test_akaze.cpp</code></td></tr><tr><td>BF&#x2F;FLANN 匹配器</td><td><code>modules/features2d/src/matchers.cpp</code></td><td><code>test/test_matchers_algorithmic.cpp</code></td></tr><tr><td>Bag of Words</td><td><code>modules/features2d/src/bagofwords.cpp</code></td><td>结合匹配器测试验证</td></tr><tr><td>关键点与匹配绘制</td><td><code>modules/features2d/src/draw.cpp</code></td><td><code>test/test_keypoints.cpp</code></td></tr></tbody></table><p>定位特征算法时，先区分检测器、描述子和匹配器；ORB 等类可能同时提供检测和描述。</p><h2 id="7-Calib3d：多视图几何与标定"><a href="#7-Calib3d：多视图几何与标定" class="headerlink" title="7. Calib3d：多视图几何与标定"></a>7. Calib3d：多视图几何与标定</h2><p>公开入口为 <code>modules/calib3d/include/opencv2/calib3d.hpp</code>，兼容 C 接口位于<br><code>modules/calib3d/include/opencv2/calib3d/calib3d_c.h</code>。</p><table><thead><tr><th>功能&#x2F;API</th><th>实现</th><th>测试&#x2F;perf</th></tr></thead><tbody><tr><td>相机标定</td><td><code>modules/calib3d/src/calibration.cpp</code></td><td><code>test/test_cameracalibration.cpp</code></td></tr><tr><td>标定异常参数</td><td><code>modules/calib3d/src/calibration.cpp</code></td><td><code>test/test_cameracalibration_badarg.cpp</code></td></tr><tr><td>PnP 总入口</td><td><code>modules/calib3d/src/solvepnp.cpp</code></td><td><code>test/test_solvepnp_ransac.cpp</code></td></tr><tr><td>EPnP&#x2F;SQPNP</td><td><code>modules/calib3d/src/epnp.cpp</code>、<code>sqpnp.cpp</code></td><td><code>test/test_solvepnp_ransac.cpp</code></td></tr><tr><td>基础矩阵&#x2F;单应</td><td><code>modules/calib3d/src/fundam.cpp</code></td><td><code>test/test_fundam.cpp</code>、<code>test/test_homography.cpp</code></td></tr><tr><td>五点法</td><td><code>modules/calib3d/src/five-point.cpp</code></td><td><code>test/test_fundam.cpp</code></td></tr><tr><td>USAC&#x2F;RANSAC</td><td><code>modules/calib3d/src/usac/</code></td><td><code>test/test_modelest.cpp</code></td></tr><tr><td>双目几何</td><td><code>modules/calib3d/src/stereo_geom.cpp</code></td><td><code>test/test_stereomatching.cpp</code></td></tr><tr><td>StereoBM</td><td><code>modules/calib3d/src/stereobm.cpp</code></td><td><code>test/test_stereomatching.cpp</code></td></tr><tr><td>StereoSGBM</td><td><code>modules/calib3d/src/stereosgbm.cpp</code></td><td><code>test/test_stereomatching.cpp</code>、<code>perf/perf_stereosgbm.cpp</code></td></tr><tr><td>鱼眼模型</td><td><code>modules/calib3d/src/fisheye.cpp</code></td><td><code>test/test_fisheye.cpp</code></td></tr><tr><td>去畸变</td><td><code>modules/calib3d/src/undistort.dispatch.cpp</code></td><td><code>test/test_undistort.cpp</code>、<code>perf/perf_undistort.cpp</code></td></tr><tr><td>棋盘初始化</td><td><code>modules/calib3d/src/calibinit.cpp</code></td><td><code>test/test_chesscorners.cpp</code></td></tr><tr><td>圆点阵</td><td><code>modules/calib3d/src/circlesgrid.cpp</code></td><td><code>test/test_cameracalibration.cpp</code></td></tr><tr><td>棋盘快速检查</td><td><code>modules/calib3d/src/checkchessboard.cpp</code></td><td><code>test/test_chesscorners.cpp</code></td></tr></tbody></table><h2 id="8-Video：光流、背景建模与跟踪"><a href="#8-Video：光流、背景建模与跟踪" class="headerlink" title="8. Video：光流、背景建模与跟踪"></a>8. Video：光流、背景建模与跟踪</h2><table><thead><tr><th>功能&#x2F;API</th><th>声明</th><th>实现</th><th>验证入口</th></tr></thead><tbody><tr><td>稀疏 LK 光流</td><td><code>modules/video/include/opencv2/video/tracking.hpp</code></td><td><code>modules/video/src/lkpyramid.cpp</code></td><td><code>modules/video/test/test_optflowpyrlk.cpp</code></td></tr><tr><td>Farneback 稠密光流</td><td><code>modules/video/include/opencv2/video/tracking.hpp</code></td><td><code>modules/video/src/optflowgf.cpp</code></td><td><code>modules/video/test/ocl/test_optflow_farneback.cpp</code></td></tr><tr><td>DIS 光流</td><td><code>modules/video/include/opencv2/video/tracking.hpp</code></td><td><code>modules/video/src/dis_flow.cpp</code></td><td><code>modules/video/perf/perf_disflow.cpp</code></td></tr><tr><td>MOG2</td><td><code>modules/video/include/opencv2/video/background_segm.hpp</code></td><td><code>modules/video/src/bgfg_gaussmix2.cpp</code></td><td><code>modules/video/perf/perf_bgfg_mog2.cpp</code></td></tr><tr><td>KNN 背景模型</td><td><code>modules/video/include/opencv2/video/background_segm.hpp</code></td><td><code>modules/video/src/bgfg_KNN.cpp</code></td><td><code>modules/video/test/test_bgfg2.cpp</code></td></tr><tr><td>Kalman</td><td><code>modules/video/include/opencv2/video/tracking.hpp</code></td><td><code>modules/video/src/kalman.cpp</code></td><td><code>modules/video/test/test_kalman.cpp</code></td></tr><tr><td>CamShift&#x2F;MeanShift</td><td><code>modules/video/include/opencv2/video/tracking.hpp</code></td><td><code>modules/video/src/camshift.cpp</code></td><td><code>modules/video/test/test_camshift.cpp</code></td></tr><tr><td>Tracker 框架</td><td><code>modules/video/include/opencv2/video/tracking.hpp</code></td><td><code>modules/video/src/tracking/</code></td><td><code>modules/video/test/test_trackers.cpp</code></td></tr></tbody></table><h2 id="9-图像、窗口与视频-I-O"><a href="#9-图像、窗口与视频-I-O" class="headerlink" title="9. 图像、窗口与视频 I&#x2F;O"></a>9. 图像、窗口与视频 I&#x2F;O</h2><h3 id="9-1-Imgcodecs"><a href="#9-1-Imgcodecs" class="headerlink" title="9.1 Imgcodecs"></a>9.1 Imgcodecs</h3><table><thead><tr><th>层次</th><th>文件</th><th>作用</th></tr></thead><tbody><tr><td>公开 API</td><td><code>modules/imgcodecs/include/opencv2/imgcodecs.hpp</code></td><td><code>imread</code>、<code>imwrite</code>、<code>imdecode</code>、<code>imencode</code></td></tr><tr><td>调度入口</td><td><code>modules/imgcodecs/src/loadsave.cpp</code></td><td>格式探测、解码器&#x2F;编码器选择</td></tr><tr><td>编解码抽象</td><td><code>modules/imgcodecs/src/grfmts.hpp</code>、<code>grfmt_base.cpp</code></td><td>基类和注册集合</td></tr><tr><td>JPEG</td><td><code>modules/imgcodecs/src/grfmt_jpeg.cpp</code></td><td>JPEG 读写</td></tr><tr><td>PNG</td><td><code>modules/imgcodecs/src/grfmt_png.cpp</code></td><td>PNG 读写</td></tr><tr><td>TIFF</td><td><code>modules/imgcodecs/src/grfmt_tiff.cpp</code></td><td>TIFF 读写</td></tr><tr><td>回归测试</td><td><code>modules/imgcodecs/test/test_read_write.cpp</code></td><td>通用读写</td></tr><tr><td>格式测试</td><td><code>modules/imgcodecs/test/test_jpeg.cpp</code>、<code>test_png.cpp</code>、<code>test_tiff.cpp</code></td><td>格式专项</td></tr><tr><td>性能</td><td><code>modules/imgcodecs/perf/perf_decode_encode.cpp</code></td><td>编解码吞吐</td></tr></tbody></table><h3 id="9-2-Highgui"><a href="#9-2-Highgui" class="headerlink" title="9.2 Highgui"></a>9.2 Highgui</h3><table><thead><tr><th>路径</th><th>作用</th></tr></thead><tbody><tr><td><code>modules/highgui/include/opencv2/highgui.hpp</code></td><td>窗口、事件、控件和图像显示 API</td></tr><tr><td><code>modules/highgui/src/window.cpp</code></td><td>通用窗口 API 与后端调用入口</td></tr><tr><td><code>modules/highgui/src/registry.impl.hpp</code></td><td>UI 后端注册</td></tr><tr><td><code>modules/highgui/test/test_gui.cpp</code></td><td>GUI 基础测试</td></tr></tbody></table><h3 id="9-3-Videoio"><a href="#9-3-Videoio" class="headerlink" title="9.3 Videoio"></a>9.3 Videoio</h3><table><thead><tr><th>后端&#x2F;功能</th><th>公开或实现入口</th><th>测试&#x2F;perf</th></tr></thead><tbody><tr><td><code>VideoCapture</code>&#x2F;<code>VideoWriter</code></td><td><code>modules/videoio/include/opencv2/videoio.hpp</code>、<code>src/cap.cpp</code></td><td><code>test/test_video_io.cpp</code></td></tr><tr><td>后端枚举与查询</td><td><code>modules/videoio/include/opencv2/videoio/registry.hpp</code></td><td><code>test/test_plugins.cpp</code></td></tr><tr><td>后端注册表</td><td><code>modules/videoio/src/videoio_registry.cpp</code></td><td><code>test/test_dynamic.cpp</code></td></tr><tr><td>插件桥接</td><td><code>modules/videoio/src/backend_plugin.cpp</code></td><td><code>test/test_plugins.cpp</code></td></tr><tr><td>FFmpeg</td><td><code>modules/videoio/src/cap_ffmpeg.cpp</code>、<code>cap_ffmpeg_impl.hpp</code></td><td><code>test/test_ffmpeg.cpp</code></td></tr><tr><td>GStreamer</td><td><code>modules/videoio/src/cap_gstreamer.cpp</code></td><td><code>test/test_gstreamer.cpp</code></td></tr><tr><td>Linux V4L&#x2F;V4L2</td><td><code>modules/videoio/src/cap_v4l.cpp</code></td><td><code>test/test_v4l2.cpp</code></td></tr><tr><td>图像序列</td><td><code>modules/videoio/src/cap_images.cpp</code></td><td><code>test/test_images.cpp</code></td></tr><tr><td>Windows Media Foundation</td><td><code>modules/videoio/src/cap_msmf.cpp</code></td><td><code>test/test_camera.cpp</code></td></tr><tr><td>Apple AVFoundation</td><td><code>modules/videoio/src/cap_avfoundation.mm</code></td><td>平台测试</td></tr><tr><td>输入性能</td><td><code>modules/videoio/perf/perf_input.cpp</code></td><td>解码&#x2F;读取吞吐</td></tr><tr><td>输出性能</td><td><code>modules/videoio/perf/perf_output.cpp</code></td><td>编码&#x2F;写入吞吐</td></tr></tbody></table><h2 id="10-DNN：模型导入、网络执行与后端"><a href="#10-DNN：模型导入、网络执行与后端" class="headerlink" title="10. DNN：模型导入、网络执行与后端"></a>10. DNN：模型导入、网络执行与后端</h2><table><thead><tr><th>层次</th><th>路径</th><th>说明</th></tr></thead><tbody><tr><td>聚合公开头</td><td><code>modules/dnn/include/opencv2/dnn.hpp</code></td><td>常用 DNN API</td></tr><tr><td>网络与模型 API</td><td><code>modules/dnn/include/opencv2/dnn/dnn.hpp</code></td><td><code>Net</code>、blob、模型读取、NMS</td></tr><tr><td>层基类</td><td><code>modules/dnn/include/opencv2/dnn/layer.hpp</code></td><td><code>Layer</code> 生命周期与后端支持</td></tr><tr><td>层声明集合</td><td><code>modules/dnn/include/opencv2/dnn/all_layers.hpp</code></td><td>内置层类型</td></tr><tr><td><code>Net</code> 外观</td><td><code>modules/dnn/src/net.cpp</code></td><td>公开成员函数入口</td></tr><tr><td><code>Net</code> 内部执行</td><td><code>modules/dnn/src/net_impl.cpp</code></td><td>图、内存、forward 主逻辑</td></tr><tr><td>后端选择</td><td><code>modules/dnn/src/net_impl_backend.cpp</code></td><td>backend&#x2F;target 分派</td></tr><tr><td>通用模型读取</td><td><code>modules/dnn/src/dnn_read.cpp</code></td><td>按格式读取模型</td></tr><tr><td>层工厂</td><td><code>modules/dnn/src/layer_factory.cpp</code></td><td>层注册与构造</td></tr><tr><td>CPU 层实现</td><td><code>modules/dnn/src/layers/</code></td><td>卷积、池化、激活、检测等</td></tr><tr><td>ONNX 导入</td><td><code>modules/dnn/src/onnx/onnx_importer.cpp</code></td><td>ONNX 图解析与层转换</td></tr><tr><td>TensorFlow 导入</td><td><code>modules/dnn/src/tensorflow/tf_importer.cpp</code></td><td>TensorFlow 图导入</td></tr><tr><td>Darknet 导入</td><td><code>modules/dnn/src/darknet/darknet_importer.cpp</code></td><td>cfg&#x2F;weights 导入</td></tr><tr><td>CUDA 后端</td><td><code>modules/dnn/src/cuda4dnn/</code></td><td>CUDA primitive、kernel 与封装</td></tr><tr><td>OpenCL kernel</td><td><code>modules/dnn/src/opencl/</code></td><td>OpenCL 层内核</td></tr><tr><td>网络综合测试</td><td><code>modules/dnn/test/test_misc.cpp</code></td><td><code>Net</code> 行为与杂项回归</td></tr><tr><td>层测试</td><td><code>modules/dnn/test/test_layers.cpp</code></td><td>层正确性与后端对齐</td></tr><tr><td>ONNX 测试</td><td><code>modules/dnn/test/test_onnx_importer.cpp</code></td><td>导入回归</td></tr><tr><td>NMS 测试</td><td><code>modules/dnn/test/test_nms.cpp</code></td><td>NMS 与边界条件</td></tr><tr><td>网络性能</td><td><code>modules/dnn/perf/perf_net.cpp</code></td><td>网络 forward 性能</td></tr><tr><td>层性能</td><td><code>modules/dnn/perf/perf_convolution3d.cpp</code></td><td>代表性的卷积基准</td></tr></tbody></table><p>排查 DNN 数值差异时，应同时记录模型导入器、层实现、backend 和 target；只检查<br><code>net.cpp</code> 往往无法看到真正的计算内核。</p><h2 id="11-G-API：计算图、编译器与后端"><a href="#11-G-API：计算图、编译器与后端" class="headerlink" title="11. G-API：计算图、编译器与后端"></a>11. G-API：计算图、编译器与后端</h2><table><thead><tr><th>层次</th><th>路径</th><th>说明</th></tr></thead><tbody><tr><td>聚合头</td><td><code>modules/gapi/include/opencv2/gapi.hpp</code></td><td>常用图 API</td></tr><tr><td>图计算</td><td><code>modules/gapi/include/opencv2/gapi/gcomputation.hpp</code></td><td><code>GComputation</code></td></tr><tr><td>图数据</td><td><code>modules/gapi/include/opencv2/gapi/gmat.hpp</code></td><td><code>GMat</code> 等图节点数据</td></tr><tr><td>Kernel 声明</td><td><code>modules/gapi/include/opencv2/gapi/gkernel.hpp</code></td><td>操作与实现包</td></tr><tr><td>流式输入</td><td><code>modules/gapi/include/opencv2/gapi/streaming/source.hpp</code></td><td>流源接口</td></tr><tr><td>图 API 实现</td><td><code>modules/gapi/src/api/gcomputation.cpp</code></td><td>compile&#x2F;apply 入口</td></tr><tr><td>编译器</td><td><code>modules/gapi/src/compiler/gcompiler.cpp</code></td><td>编译阶段组织</td></tr><tr><td>图模型</td><td><code>modules/gapi/src/compiler/gmodel.cpp</code></td><td>内部图表示</td></tr><tr><td>编译 passes</td><td><code>modules/gapi/src/compiler/passes/</code></td><td>meta、islands、kernels、exec 等</td></tr><tr><td>CPU 后端</td><td><code>modules/gapi/src/backends/cpu/gcpubackend.cpp</code></td><td>CPU kernel 执行</td></tr><tr><td>OpenCL 后端</td><td><code>modules/gapi/src/backends/ocl/goclbackend.cpp</code></td><td>OCL 后端</td></tr><tr><td>Fluid 后端</td><td><code>modules/gapi/src/backends/fluid/gfluidbackend.cpp</code></td><td>流水化执行</td></tr><tr><td>核心测试</td><td><code>modules/gapi/test/gapi_mat_tests.cpp</code></td><td>图数据语义</td></tr><tr><td>流式测试</td><td><code>modules/gapi/test/streaming/gapi_streaming_tests.cpp</code></td><td>streaming 行为</td></tr><tr><td>Fluid 测试</td><td><code>modules/gapi/test/gapi_fluid_test.cpp</code></td><td>Fluid 后端</td></tr></tbody></table><h2 id="12-Stitching：全景拼接流水线"><a href="#12-Stitching：全景拼接流水线" class="headerlink" title="12. Stitching：全景拼接流水线"></a>12. Stitching：全景拼接流水线</h2><table><thead><tr><th>组件</th><th>公开声明</th><th>实现</th></tr></thead><tbody><tr><td>高层 <code>Stitcher</code></td><td><code>modules/stitching/include/opencv2/stitching.hpp</code></td><td><code>modules/stitching/src/stitcher.cpp</code></td></tr><tr><td>特征匹配</td><td><code>modules/stitching/include/opencv2/stitching/detail/matchers.hpp</code></td><td><code>modules/stitching/src/matchers.cpp</code></td></tr><tr><td>运动估计与 BA</td><td><code>modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp</code></td><td><code>modules/stitching/src/motion_estimators.cpp</code></td></tr><tr><td>自动标定</td><td><code>modules/stitching/include/opencv2/stitching/detail/autocalib.hpp</code></td><td><code>modules/stitching/src/autocalib.cpp</code></td></tr><tr><td>缝线搜索</td><td><code>modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp</code></td><td><code>modules/stitching/src/seam_finders.cpp</code></td></tr><tr><td>曝光补偿</td><td><code>modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp</code></td><td><code>modules/stitching/src/exposure_compensate.cpp</code></td></tr><tr><td>融合</td><td><code>modules/stitching/include/opencv2/stitching/detail/blenders.hpp</code></td><td><code>modules/stitching/src/blenders.cpp</code></td></tr><tr><td>图像变换</td><td><code>modules/stitching/include/opencv2/stitching/warpers.hpp</code></td><td><code>modules/stitching/src/warpers.cpp</code></td></tr><tr><td>匹配测试</td><td><code>modules/stitching/test/test_matchers.cpp</code></td><td>组件级验证</td></tr><tr><td>融合测试</td><td><code>modules/stitching/test/test_blenders.cpp</code></td><td>融合验证</td></tr><tr><td>性能</td><td><code>modules/stitching/perf/perf_stich.cpp</code></td><td>拼接性能入口</td></tr></tbody></table><h2 id="13-Objdetect：级联、HOG、二维码与-ArUco"><a href="#13-Objdetect：级联、HOG、二维码与-ArUco" class="headerlink" title="13. Objdetect：级联、HOG、二维码与 ArUco"></a>13. Objdetect：级联、HOG、二维码与 ArUco</h2><table><thead><tr><th>功能</th><th>声明</th><th>实现&#x2F;测试</th></tr></thead><tbody><tr><td>级联分类器</td><td><code>modules/objdetect/include/opencv2/objdetect.hpp</code></td><td><code>src/cascadedetect.cpp</code>、<code>test/test_cascadeandhog.cpp</code></td></tr><tr><td>HOG 检测</td><td><code>modules/objdetect/include/opencv2/objdetect.hpp</code></td><td><code>src/hog.cpp</code>、<code>test/test_cascadeandhog.cpp</code></td></tr><tr><td>QRCode</td><td><code>modules/objdetect/include/opencv2/objdetect.hpp</code></td><td><code>src/qrcode.cpp</code>、<code>test/test_qrcode.cpp</code></td></tr><tr><td>ArUco 检测器</td><td><code>modules/objdetect/include/opencv2/objdetect/aruco_detector.hpp</code></td><td><code>src/aruco/aruco_detector.cpp</code></td></tr><tr><td>ArUco 字典</td><td><code>modules/objdetect/include/opencv2/objdetect/aruco_dictionary.hpp</code></td><td><code>src/aruco/aruco_dictionary.cpp</code></td></tr><tr><td>Board</td><td><code>modules/objdetect/include/opencv2/objdetect/aruco_board.hpp</code></td><td><code>test/test_boarddetection.cpp</code></td></tr><tr><td>ChArUco</td><td><code>modules/objdetect/include/opencv2/objdetect/charuco_detector.hpp</code></td><td><code>src/aruco/</code></td></tr><tr><td>人脸接口</td><td><code>modules/objdetect/include/opencv2/objdetect/face.hpp</code></td><td><code>modules/objdetect/src/</code></td></tr></tbody></table><h2 id="14-Photo：修复、克隆、去噪与-HDR"><a href="#14-Photo：修复、克隆、去噪与-HDR" class="headerlink" title="14. Photo：修复、克隆、去噪与 HDR"></a>14. Photo：修复、克隆、去噪与 HDR</h2><p>公开入口为 <code>modules/photo/include/opencv2/photo.hpp</code>，CUDA 相关声明位于<br><code>modules/photo/include/opencv2/photo/cuda.hpp</code>。</p><table><thead><tr><th>功能&#x2F;API</th><th>实现</th><th>验证入口</th></tr></thead><tbody><tr><td>图像修复 <code>inpaint</code></td><td><code>modules/photo/src/inpaint.cpp</code></td><td><code>test/test_inpaint.cpp</code>、<code>perf/perf_inpaint.cpp</code></td></tr><tr><td>无缝克隆</td><td><code>modules/photo/src/seamless_cloning.cpp</code></td><td><code>test/test_cloning.cpp</code></td></tr><tr><td>非局部均值去噪</td><td><code>modules/photo/src/denoising.cpp</code></td><td><code>test/test_denoising.cpp</code></td></tr><tr><td>HDR 对齐</td><td><code>modules/photo/src/align.cpp</code></td><td><code>test/test_hdr.cpp</code></td></tr><tr><td>相机响应标定</td><td><code>modules/photo/src/calibrate.cpp</code></td><td><code>test/test_hdr.cpp</code></td></tr><tr><td>HDR 合并</td><td><code>modules/photo/src/merge.cpp</code></td><td><code>test/test_hdr.cpp</code></td></tr><tr><td>色调映射</td><td><code>modules/photo/src/tonemap.cpp</code></td><td><code>test/test_hdr.cpp</code></td></tr><tr><td>HDR 公共内部逻辑</td><td><code>modules/photo/src/hdr_common.cpp</code></td><td>由 HDR 各阶段共用</td></tr></tbody></table><h2 id="15-HAL、SIMD、OpenCL-与运行时分派"><a href="#15-HAL、SIMD、OpenCL-与运行时分派" class="headerlink" title="15. HAL、SIMD、OpenCL 与运行时分派"></a>15. HAL、SIMD、OpenCL 与运行时分派</h2><h3 id="15-1-HAL-边界"><a href="#15-1-HAL-边界" class="headerlink" title="15.1 HAL 边界"></a>15.1 HAL 边界</h3><table><thead><tr><th>路径</th><th>用途</th></tr></thead><tbody><tr><td><code>modules/core/include/opencv2/core/hal/interface.h</code></td><td>Core HAL C 风格接口与类型</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/hal.hpp</code></td><td>Core HAL 包装</td></tr><tr><td><code>modules/imgproc/include/opencv2/imgproc/hal/interface.h</code></td><td>Imgproc HAL 接口</td></tr><tr><td><code>modules/imgproc/include/opencv2/imgproc/hal/hal.hpp</code></td><td>Imgproc HAL 包装</td></tr><tr><td><code>modules/core/src/hal_replacement.hpp</code></td><td>Core 默认实现映射</td></tr><tr><td><code>modules/imgproc/src/hal_replacement.hpp</code></td><td>Imgproc 默认实现映射</td></tr><tr><td><code>modules/calib3d/src/hal_replacement.hpp</code></td><td>Calib3d 默认 HAL 回退</td></tr><tr><td><code>modules/video/src/hal_replacement.hpp</code></td><td>Video 默认 HAL 回退</td></tr></tbody></table><h3 id="15-2-通用-SIMD"><a href="#15-2-通用-SIMD" class="headerlink" title="15.2 通用 SIMD"></a>15.2 通用 SIMD</h3><table><thead><tr><th>路径</th><th>架构&#x2F;作用</th></tr></thead><tbody><tr><td><code>modules/core/include/opencv2/core/hal/intrin.hpp</code></td><td>通用 SIMD 聚合入口</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_cpp.hpp</code></td><td>可移植向量抽象</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_sse.hpp</code></td><td>x86 SSE</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_avx.hpp</code></td><td>x86 AVX</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_avx512.hpp</code></td><td>x86 AVX-512</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_neon.hpp</code></td><td>Arm NEON</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_vsx.hpp</code></td><td>Power VSX</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_wasm.hpp</code></td><td>WebAssembly SIMD</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp</code></td><td>RISC-V 可伸缩向量</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_lsx.hpp</code></td><td>LoongArch LSX</td></tr><tr><td><code>modules/core/include/opencv2/core/hal/intrin_lasx.hpp</code></td><td>LoongArch LASX</td></tr></tbody></table><h3 id="15-3-树内-HAL-实现"><a href="#15-3-树内-HAL-实现" class="headerlink" title="15.3 树内 HAL 实现"></a>15.3 树内 HAL 实现</h3><table><thead><tr><th>HAL</th><th>路径</th><th>主要目标</th></tr></thead><tbody><tr><td>Carotene</td><td><code>hal/carotene/</code></td><td>Arm NEON 优化</td></tr><tr><td>FastCV</td><td><code>hal/fastcv/</code></td><td>Qualcomm FastCV</td></tr><tr><td>IPP</td><td><code>hal/ipp/</code></td><td>Intel IPP</td></tr><tr><td>NDSRVP</td><td><code>hal/ndsrvp/</code></td><td>Andes RVP&#x2F;DSP</td></tr><tr><td>OpenVX</td><td><code>hal/openvx/</code></td><td>OpenVX</td></tr><tr><td>RISC-V RVV</td><td><code>hal/riscv-rvv/</code></td><td>RISC-V Vector</td></tr><tr><td>KleidiCV</td><td><code>hal/kleidicv/</code></td><td>Arm KleidiCV</td></tr><tr><td>自定义 HAL 示例</td><td><code>samples/hal/c_hal/</code>、<code>samples/hal/slow_hal/</code></td><td>外接 HAL 的构建与替换方式</td></tr></tbody></table><p>典型调用链是“公开 API → 普通入口 → HAL 宏&#x2F;函数 → 外部 HAL 或默认替换 → SIMD&#x2F;标量”。<br>若输入是 <code>UMat</code>，还可能在普通 CPU 路径之前进入 <code>src/opencl/</code> 中的 kernel。</p><h2 id="16-CMake：从模块声明到-CPU-分派"><a href="#16-CMake：从模块声明到-CPU-分派" class="headerlink" title="16. CMake：从模块声明到 CPU 分派"></a>16. CMake：从模块声明到 CPU 分派</h2><table><thead><tr><th>文件</th><th>定位价值</th></tr></thead><tbody><tr><td><code>CMakeLists.txt</code></td><td>全局选项、平台初始化和模块构建入口</td></tr><tr><td><code>cmake/OpenCVModule.cmake</code></td><td><code>ocv_define_module</code> 等模块基础宏</td></tr><tr><td><code>cmake/OpenCVCompilerOptimizations.cmake</code></td><td>CPU baseline&#x2F;dispatch 检测和编译策略</td></tr><tr><td><code>cmake/OpenCVFindLibsGrfmt.cmake</code></td><td>图像格式依赖</td></tr><tr><td><code>cmake/OpenCVFindLibsGUI.cmake</code></td><td>GUI 依赖</td></tr><tr><td><code>cmake/OpenCVFindLibsPerf.cmake</code></td><td>性能相关依赖</td></tr><tr><td><code>cmake/templates/cvconfig.h.in</code></td><td>生成构建能力宏</td></tr><tr><td><code>cmake/templates/OpenCVConfig.cmake.in</code></td><td>安装后的 CMake 包配置</td></tr><tr><td><code>modules/core/CMakeLists.txt</code></td><td>Core、并行与 CPU 分派</td></tr><tr><td><code>modules/imgproc/CMakeLists.txt</code></td><td>Imgproc 源文件与 HAL</td></tr><tr><td><code>modules/videoio/CMakeLists.txt</code></td><td>视频后端条件编译</td></tr><tr><td><code>modules/dnn/CMakeLists.txt</code></td><td>DNN 模型格式与后端</td></tr><tr><td><code>modules/gapi/CMakeLists.txt</code></td><td>G-API 后端与依赖</td></tr><tr><td><code>modules/world/CMakeLists.txt</code></td><td>聚合动态&#x2F;静态库</td></tr></tbody></table><p>阅读 <code>.dispatch.cpp</code> 时，同时在模块 <code>CMakeLists.txt</code> 中搜索<br><code>ocv_add_dispatched_file</code>，可确认哪些源码会按 ISA 生成多个编译变体。</p><h2 id="17-语言绑定"><a href="#17-语言绑定" class="headerlink" title="17. 语言绑定"></a>17. 语言绑定</h2><h3 id="17-1-Python"><a href="#17-1-Python" class="headerlink" title="17.1 Python"></a>17.1 Python</h3><table><thead><tr><th>路径</th><th>作用</th></tr></thead><tbody><tr><td><code>modules/python/CMakeLists.txt</code></td><td>Python 模块总构建入口</td></tr><tr><td><code>modules/python/bindings/CMakeLists.txt</code></td><td>绑定生成目标</td></tr><tr><td><code>modules/python/python3/CMakeLists.txt</code></td><td>Python 3 扩展构建</td></tr><tr><td><code>modules/python/src2/hdr_parser.py</code></td><td>解析带导出标注的 C++ 头</td></tr><tr><td><code>modules/python/src2/gen2.py</code></td><td>生成 C++ Python 包装代码</td></tr><tr><td><code>modules/python/src2/typing_stubs_generation/</code></td><td>生成 Python 类型提示</td></tr><tr><td><code>modules/python/test/test_mat.py</code></td><td><code>Mat</code>&#x2F;ndarray 行为</td></tr><tr><td><code>modules/python/test/test_features2d.py</code></td><td>特征 API 绑定</td></tr><tr><td><code>modules/python/test/test_imread.py</code></td><td>图像读取绑定</td></tr><tr><td><code>modules/python/test/tests_common.py</code></td><td>Python 测试公共设施</td></tr></tbody></table><p>Python API 不一定有手写的同名包装函数；应先查 C++ 公开头上的导出标注，再查生成器。</p><h3 id="17-2-Java"><a href="#17-2-Java" class="headerlink" title="17.2 Java"></a>17.2 Java</h3><table><thead><tr><th>路径</th><th>作用</th></tr></thead><tbody><tr><td><code>modules/java/CMakeLists.txt</code></td><td>Java 模块入口</td></tr><tr><td><code>modules/java/jni/CMakeLists.txt</code></td><td>JNI 本地库构建</td></tr><tr><td><code>modules/java/generator/gen_java.py</code></td><td>Java&#x2F;JNI 代码生成</td></tr><tr><td><code>modules/java/generator/src/cpp/opencv_java.cpp</code></td><td>本地绑定公共入口</td></tr><tr><td><code>modules/java/generator/src/cpp/Mat.cpp</code></td><td><code>Mat</code> 的 JNI 支撑</td></tr><tr><td><code>modules/java/generator/src/cpp/converters.cpp</code></td><td>Java&#x2F;C++ 类型转换</td></tr><tr><td><code>modules/java/generator/src/java/org/opencv/utils/Converters.java</code></td><td>Java 侧转换工具</td></tr><tr><td><code>modules/java/test/pure_test/src/</code></td><td>Java 绑定测试</td></tr></tbody></table><h3 id="17-3-JavaScript"><a href="#17-3-JavaScript" class="headerlink" title="17.3 JavaScript"></a>17.3 JavaScript</h3><table><thead><tr><th>路径</th><th>作用</th></tr></thead><tbody><tr><td><code>modules/js/generator/CMakeLists.txt</code></td><td>JS 绑定生成</td></tr><tr><td><code>modules/js/generator/embindgen.py</code></td><td>Embind 包装生成</td></tr><tr><td><code>modules/js/src/core_bindings.cpp</code></td><td>手写核心绑定</td></tr><tr><td><code>modules/js/src/helpers.js</code></td><td>JS 运行时辅助</td></tr><tr><td><code>modules/js/src/make_umd.py</code></td><td>UMD 输出辅助</td></tr><tr><td><code>platforms/js/build_js.py</code></td><td>WebAssembly&#x2F;JS 构建入口</td></tr><tr><td><code>platforms/js/opencv_js.config.py</code></td><td>导出 API 配置</td></tr><tr><td><code>modules/js/test/test_core.js</code></td><td>Core JS 测试</td></tr><tr><td><code>modules/js/test/test_imgproc.js</code></td><td>Imgproc JS 测试</td></tr><tr><td><code>modules/js/test/test_calib3d.js</code></td><td>Calib3d JS 测试</td></tr></tbody></table><p>Objective-C 构建入口可从 <code>modules/objc/CMakeLists.txt</code> 和<br><code>modules/objc/generator/CMakeLists.txt</code> 开始。</p><h2 id="18-测试与性能基准的阅读方法"><a href="#18-测试与性能基准的阅读方法" class="headerlink" title="18. 测试与性能基准的阅读方法"></a>18. 测试与性能基准的阅读方法</h2><table><thead><tr><th>目录&#x2F;文件</th><th>作用</th></tr></thead><tbody><tr><td><code>modules/ts/include/opencv2/ts/</code></td><td>OpenCV 测试系统的断言、数据和性能宏</td></tr><tr><td><code>modules/ts/CMakeLists.txt</code></td><td>测试支撑库构建</td></tr><tr><td><code>modules/&lt;name&gt;/test/test_main.cpp</code></td><td>模块测试程序入口</td></tr><tr><td><code>modules/&lt;name&gt;/test/test_*.cpp</code></td><td>正确性、边界、回归和坏参数测试</td></tr><tr><td><code>modules/&lt;name&gt;/perf/perf_main.cpp</code></td><td>模块性能程序入口</td></tr><tr><td><code>modules/&lt;name&gt;/perf/perf_*.cpp</code></td><td>参数化性能用例</td></tr></tbody></table><h2 id="19-从-API-找到声明、实现、测试和-perf"><a href="#19-从-API-找到声明、实现、测试和-perf" class="headerlink" title="19. 从 API 找到声明、实现、测试和 perf"></a>19. 从 API 找到声明、实现、测试和 perf</h2><p>以一个 API 名称 <code>foo</code> 为例，可按下列顺序查找：</p><ol><li>在 <code>modules/*/include/opencv2/</code> 搜索 <code>foo</code>，确认命名空间、重载和默认参数；</li><li>在 <code>modules/*/src/</code> 搜索 <code>foo(</code> 或类的 <code>ClassName::foo</code>；</li><li>若入口只有包装，继续跟踪 <code>CV_OCL_RUN</code>、<code>CALL_HAL</code>、<code>CV_CPU_DISPATCH</code>；</li><li>查看同目录的 <code>.dispatch.cpp</code>、<code>.simd.hpp</code> 和 <code>src/opencl/*.cl</code>；</li><li>在 <code>modules/*/test/</code> 搜索 API 名、测试夹具名和相关枚举；</li><li>在 <code>modules/*/perf/</code> 搜索 API 名，确认性能参数；</li><li>在 <code>samples/</code> 搜索调用方式，观察输入准备和完整数据流；</li><li>在模块 <code>CMakeLists.txt</code> 中确认文件是否受平台或依赖条件控制。</li></ol><h3 id="19-1-常见“搜索不到实现”的原因"><a href="#19-1-常见“搜索不到实现”的原因" class="headerlink" title="19.1 常见“搜索不到实现”的原因"></a>19.1 常见“搜索不到实现”的原因</h3><table><thead><tr><th>现象</th><th>应继续检查</th></tr></thead><tbody><tr><td>只找到头文件声明</td><td>搜索类成员限定名、宏展开后的底层名字</td></tr><tr><td>实现只做参数检查</td><td>查后续内部函数、HAL、IPP、OpenCL 或 backend</td></tr><tr><td>找到 <code>.dispatch.cpp</code></td><td>再查同名前缀的 <code>.simd.hpp</code></td></tr><tr><td>找到工厂函数</td><td>查注册表、创建器和具体派生类</td></tr><tr><td>Python&#x2F;Java 名称与 C++ 不同</td><td>查绑定生成器和公开头导出标注</td></tr><tr><td>Videoio 在不同机器行为不同</td><td>查后端注册表、插件和构建配置</td></tr><tr><td>DNN 结果依设备而异</td><td>查 backend、target、层支持判断和 fallback</td></tr></tbody></table><h2 id="20-任务到源码速查"><a href="#20-任务到源码速查" class="headerlink" title="20. 任务到源码速查"></a>20. 任务到源码速查</h2><table><thead><tr><th>任务</th><th>首选源码入口</th></tr></thead><tbody><tr><td>研究 <code>Mat</code> 浅拷贝和引用计数</td><td><code>modules/core/src/matrix.cpp</code></td></tr><tr><td>研究 ROI&#x2F;步长&#x2F;连续性</td><td><code>modules/core/include/opencv2/core/mat.hpp</code>、<code>src/matrix.cpp</code></td></tr><tr><td>优化加减乘除</td><td><code>modules/core/src/arithm.cpp</code>、<code>arithm.dispatch.cpp</code>、<code>arithm.simd.hpp</code></td></tr><tr><td>优化矩阵乘法</td><td><code>modules/core/src/matmul.dispatch.cpp</code>、<code>matmul.simd.hpp</code></td></tr><tr><td>修改 GaussianBlur</td><td><code>modules/imgproc/src/smooth.dispatch.cpp</code>、<code>smooth.simd.hpp</code></td></tr><tr><td>修改 resize&#x2F;remap&#x2F;warp</td><td><code>modules/imgproc/src/resize.cpp</code>、<code>imgwarp.cpp</code></td></tr><tr><td>修改颜色转换</td><td><code>modules/imgproc/src/color.cpp</code>、<code>color_*.dispatch.cpp</code></td></tr><tr><td>修改 Canny</td><td><code>modules/imgproc/src/canny.cpp</code>、<code>src/opencl/canny.cl</code></td></tr><tr><td>修改轮廓算法</td><td><code>modules/imgproc/src/contours.cpp</code>、<code>contours_new.cpp</code></td></tr><tr><td>修改 ORB&#x2F;SIFT</td><td><code>modules/features2d/src/orb.cpp</code>、<code>sift.dispatch.cpp</code></td></tr><tr><td>修改匹配器</td><td><code>modules/features2d/src/matchers.cpp</code></td></tr><tr><td>修改单应&#x2F;RANSAC</td><td><code>modules/calib3d/src/fundam.cpp</code>、<code>src/usac/</code></td></tr><tr><td>修改标定&#x2F;PnP</td><td><code>modules/calib3d/src/calibration.cpp</code>、<code>solvepnp.cpp</code></td></tr><tr><td>修改光流</td><td><code>modules/video/src/lkpyramid.cpp</code>、<code>optflowgf.cpp</code>、<code>dis_flow.cpp</code></td></tr><tr><td>排查摄像头打不开</td><td><code>modules/videoio/src/cap.cpp</code>、<code>videoio_registry.cpp</code>、具体后端</td></tr><tr><td>添加视频后端</td><td><code>modules/videoio/src/backend_plugin.cpp</code>、<code>videoio_registry.cpp</code></td></tr><tr><td>添加图像格式</td><td><code>modules/imgcodecs/src/loadsave.cpp</code>、<code>grfmts.hpp</code>、对应 <code>grfmt_*</code></td></tr><tr><td>修改 DNN 模型导入</td><td><code>modules/dnn/src/onnx/</code>、<code>tensorflow/</code> 或 <code>darknet/</code></td></tr><tr><td>添加 DNN 层</td><td><code>modules/dnn/src/layers/</code>、<code>layer_factory.cpp</code></td></tr><tr><td>排查 DNN backend fallback</td><td><code>modules/dnn/src/net_impl_backend.cpp</code></td></tr><tr><td>修改 G-API 图编译</td><td><code>modules/gapi/src/compiler/</code></td></tr><tr><td>修改拼接接缝&#x2F;融合</td><td><code>modules/stitching/src/seam_finders.cpp</code>、<code>blenders.cpp</code></td></tr><tr><td>修改 QR&#x2F;ArUco</td><td><code>modules/objdetect/src/qrcode.cpp</code>、<code>src/aruco/</code></td></tr><tr><td>修改修复&#x2F;克隆</td><td><code>modules/photo/src/inpaint.cpp</code>、<code>seamless_cloning.cpp</code></td></tr><tr><td>添加 Python 暴露</td><td>C++ 公开头、<code>modules/python/src2/</code></td></tr><tr><td>添加 JS 暴露</td><td><code>platforms/js/opencv_js.config.py</code>、<code>modules/js/generator/</code></td></tr></tbody></table><h2 id="21-推荐断点"><a href="#21-推荐断点" class="headerlink" title="21. 推荐断点"></a>21. 推荐断点</h2><table><thead><tr><th>调试目标</th><th>推荐断点</th></tr></thead><tbody><tr><td><code>Mat</code> 分配&#x2F;释放</td><td><code>modules/core/src/matrix.cpp</code> 中 <code>Mat::create</code>、<code>Mat::release</code></td></tr><tr><td>错误抛出</td><td><code>modules/core/src/system.cpp</code> 中 <code>cv::error</code></td></tr><tr><td>CPU 能力与优化开关</td><td><code>modules/core/src/system.cpp</code> 中硬件支持查询</td></tr><tr><td>算术调用链</td><td><code>modules/core/src/arithm.cpp</code> 中对应公开函数</td></tr><tr><td>并行执行</td><td><code>modules/core/src/parallel.cpp</code> 中 <code>parallel_for_</code></td></tr><tr><td>OpenCL 是否启用</td><td><code>modules/core/src/ocl.cpp</code> 中 <code>useOpenCL</code> 相关逻辑</td></tr><tr><td>图像读取</td><td><code>modules/imgcodecs/src/loadsave.cpp</code> 中 <code>imread_</code></td></tr><tr><td>图像写入</td><td><code>modules/imgcodecs/src/loadsave.cpp</code> 中 <code>imwrite_</code></td></tr><tr><td>视频后端选择</td><td><code>modules/videoio/src/cap.cpp</code> 中 <code>VideoCapture::open</code></td></tr><tr><td>后端注册</td><td><code>modules/videoio/src/videoio_registry.cpp</code> 中 backend 查询</td></tr><tr><td>特征匹配</td><td><code>modules/features2d/src/matchers.cpp</code> 中 <code>DescriptorMatcher</code> 调用</td></tr><tr><td>单应估计</td><td><code>modules/calib3d/src/fundam.cpp</code> 中 <code>findHomography</code></td></tr><tr><td>PnP</td><td><code>modules/calib3d/src/solvepnp.cpp</code> 中 <code>solvePnP</code></td></tr><tr><td>DNN forward</td><td><code>modules/dnn/src/net.cpp</code> 中 <code>Net::forward</code></td></tr><tr><td>DNN 内部执行</td><td><code>modules/dnn/src/net_impl.cpp</code> 中 forward 相关内部函数</td></tr><tr><td>DNN 后端选择</td><td><code>modules/dnn/src/net_impl_backend.cpp</code> 中后端初始化</td></tr><tr><td>G-API 编译</td><td><code>modules/gapi/src/compiler/gcompiler.cpp</code> 中编译入口</td></tr><tr><td>拼接主流程</td><td><code>modules/stitching/src/stitcher.cpp</code> 中 <code>estimateTransform</code>、<code>composePanorama</code></td></tr><tr><td>ArUco 检测</td><td><code>modules/objdetect/src/aruco/aruco_detector.cpp</code> 中 <code>detectMarkers</code></td></tr></tbody></table><p>断点若始终不命中，先确认是否走 OpenCL、IPP、插件、CUDA 或 CPU 分派版本，并核对当前<br>构建是否包含调试符号。</p><h2 id="22-二次开发的典型修改点"><a href="#22-二次开发的典型修改点" class="headerlink" title="22. 二次开发的典型修改点"></a>22. 二次开发的典型修改点</h2><table><thead><tr><th>目标</th><th>最小修改范围</th><th>必须补充</th></tr></thead><tbody><tr><td>新增普通 C++ API</td><td>模块公开头、<code>src/</code> 实现</td><td>文档注释、正确性测试</td></tr><tr><td>新增可导出的绑定 API</td><td>公开头及生成器可识别标注</td><td>Python&#x2F;Java&#x2F;JS 对应测试</td></tr><tr><td>新增图像处理算法</td><td><code>modules/imgproc/include/</code>、<code>src/</code></td><td>边界测试、类型组合、perf</td></tr><tr><td>新增 SIMD 路径</td><td><code>.dispatch.cpp</code>、<code>.simd.hpp</code>、模块 CMake</td><td>标量一致性和多 ISA 构建</td></tr><tr><td>新增 HAL 实现</td><td>HAL 接口、外部实现、CMake</td><td>默认回退和不支持返回语义</td></tr><tr><td>新增 OpenCL 路径</td><td>CPU 入口、<code>src/opencl/*.cl</code></td><td>CPU&#x2F;OCL 结果一致性测试</td></tr><tr><td>新增 Videoio 后端</td><td>后端实现、注册表、模块 CMake</td><td>插件&#x2F;静态构建、属性测试</td></tr><tr><td>新增 DNN 层</td><td>层声明&#x2F;实现、层工厂</td><td>导入映射、各后端 fallback、测试</td></tr><tr><td>新增 G-API kernel</td><td>G-API 声明、后端实现</td><td>kernel package 和编译测试</td></tr><tr><td>修改拼接组件</td><td><code>stitching/detail</code> 接口和对应实现</td><td>单组件测试与端到端样例</td></tr><tr><td>新增 ArUco 字典&#x2F;检测逻辑</td><td><code>objdetect</code> 公开头与 <code>src/aruco/</code></td><td>字典、旋转、误码测试</td></tr></tbody></table><p>修改原则：先保留可靠的标量实现，再增加加速路径；先补最小回归测试，再运行宽参数 perf。</p><h2 id="23-官方-Demo-到源码映射"><a href="#23-官方-Demo-到源码映射" class="headerlink" title="23. 官方 Demo 到源码映射"></a>23. 官方 Demo 到源码映射</h2><table><thead><tr><th>Demo</th><th>展示主题</th><th>反查源码</th></tr></thead><tbody><tr><td><code>samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp</code></td><td><code>Mat</code> 所有权与构造</td><td><code>modules/core/src/matrix.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/core/mat_operations/mat_operations.cpp</code></td><td>矩阵访问与操作</td><td><code>modules/core/include/opencv2/core/mat.hpp</code></td></tr><tr><td><code>samples/cpp/edge.cpp</code></td><td>灰度、模糊、Canny</td><td><code>modules/imgproc/src/canny.cpp</code>、<code>smooth.dispatch.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp</code></td><td>多种平滑</td><td><code>modules/imgproc/src/smooth.dispatch.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/ImgProc/Threshold.cpp</code></td><td>阈值</td><td><code>modules/imgproc/src/thresh.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp</code></td><td>轮廓</td><td><code>modules/imgproc/src/contours.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/ImgTrans/houghlines.cpp</code></td><td>霍夫线</td><td><code>modules/imgproc/src/hough.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp</code></td><td>模板匹配</td><td><code>modules/imgproc/src/templmatch.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/features2D/AKAZE_match.cpp</code></td><td>AKAZE 与匹配</td><td><code>modules/features2d/src/akaze.cpp</code>、<code>matchers.cpp</code></td></tr><tr><td><code>samples/python/find_obj.py</code></td><td>特征、匹配、单应</td><td><code>features2d</code> 与 <code>calib3d/src/fundam.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp</code></td><td>相机标定</td><td><code>modules/calib3d/src/calibration.cpp</code></td></tr><tr><td><code>samples/cpp/stereo_match.cpp</code></td><td>双目匹配</td><td><code>modules/calib3d/src/stereobm.cpp</code>、<code>stereosgbm.cpp</code></td></tr><tr><td><code>samples/python/opt_flow.py</code></td><td>稀疏光流</td><td><code>modules/video/src/lkpyramid.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/video/optical_flow/optical_flow_dense.cpp</code></td><td>稠密光流</td><td><code>modules/video/src/optflowgf.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/video/bg_sub.cpp</code></td><td>背景建模</td><td><code>modules/video/src/bgfg_gaussmix2.cpp</code></td></tr><tr><td><code>samples/cpp/kalman.cpp</code></td><td>Kalman</td><td><code>modules/video/src/kalman.cpp</code></td></tr><tr><td><code>samples/cpp/videocapture_basic.cpp</code></td><td>摄像头读取</td><td><code>modules/videoio/src/cap.cpp</code></td></tr><tr><td><code>samples/cpp/facedetect.cpp</code></td><td>级联人脸检测</td><td><code>modules/objdetect/src/cascadedetect.cpp</code></td></tr><tr><td><code>samples/cpp/peopledetect.cpp</code></td><td>HOG 行人检测</td><td><code>modules/objdetect/src/hog.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/photo/seamless_cloning/cloning_demo.cpp</code></td><td>无缝克隆</td><td><code>modules/photo/src/seamless_cloning.cpp</code></td></tr><tr><td><code>samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp</code></td><td>HDR 流水线</td><td><code>modules/photo/src/align.cpp</code>、<code>calibrate.cpp</code>、<code>merge.cpp</code>、<code>tonemap.cpp</code></td></tr><tr><td><code>samples/dnn/object_detection.cpp</code></td><td>DNN 目标检测</td><td><code>modules/dnn/src/net.cpp</code>、<code>net_impl.cpp</code></td></tr><tr><td><code>samples/dnn/segmentation.cpp</code></td><td>DNN 语义分割</td><td><code>modules/dnn/src/layers/</code></td></tr><tr><td><code>samples/dnn/face_detect.cpp</code></td><td>DNN 人脸检测</td><td><code>modules/dnn/src/onnx/</code> 与网络执行层</td></tr></tbody></table><h2 id="24-推荐阅读路线"><a href="#24-推荐阅读路线" class="headerlink" title="24. 推荐阅读路线"></a>24. 推荐阅读路线</h2><ol><li>从 <code>modules/core/include/opencv2/core/mat.hpp</code> 和 <code>modules/core/src/matrix.cpp</code> 理解数据模型。</li><li>选择一个熟悉的 Imgproc API，对照公开声明、CPU 实现、测试和 perf。</li><li>阅读一个 <code>.dispatch.cpp</code> 与其 <code>.simd.hpp</code>，理解 CPU 分派。</li><li>对照 <code>hal_replacement.hpp</code> 和 <code>hal/</code>，理解默认实现与外接实现。</li><li>阅读 Features2d → Calib3d 的匹配与几何估计链。</li><li>阅读 Videoio 的注册表与两个不同平台后端，理解运行时选择。</li><li>阅读 DNN 的导入器 → <code>Net</code> → layer → backend 数据流。</li><li>阅读 G-API 的 API → 图模型 → passes → backend 编译流程。</li><li>最后回到根 <code>CMakeLists.txt</code>、<code>cmake/OpenCVModule.cmake</code> 和模块 CMake 串联构建。</li></ol>]]>
    </content>
    <id>http://example.com/n/1206/</id>
    <link href="http://example.com/n/1206/"/>
    <published>2026-09-16T03:06:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="OpenCV-4-13-0-源码文件索引与导航"><a href="#OpenCV-4-13-0-源码文件索引与导航" class="headerlink" title="OpenCV 4.13.0 源码文件索引与导航"></a>OpenCV 4.13.0 源码文]]>
    </summary>
    <title>OpenCV 4.13.0 源码文件索引与导航</title>
    <updated>2026-09-16T03:49:31.699Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="07-源码文件索引"><a href="#07-源码文件索引" class="headerlink" title="07 源码文件索引"></a>07 源码文件索引</h1><p>根路径：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">YOLO/yolov5-7.0/</span><br></pre></td></tr></table></figure><h2 id="7-1-任务入口"><a href="#7-1-任务入口" class="headerlink" title="7.1 任务入口"></a>7.1 任务入口</h2><table><thead><tr><th>文件</th><th>关键入口</th><th>职责</th></tr></thead><tbody><tr><td><code>train.py</code></td><td><code>train</code>, <code>main</code>, <code>run</code></td><td>检测训练、验证、保存、超参进化</td></tr><tr><td><code>val.py</code></td><td><code>run</code>, <code>process_batch</code></td><td>检测评估、AP、JSON&#x2F;TXT</td></tr><tr><td><code>detect.py</code></td><td><code>run</code></td><td>图片&#x2F;视频&#x2F;流检测</td></tr><tr><td><code>export.py</code></td><td><code>run</code>, <code>export_*</code></td><td>多格式模型导出</td></tr><tr><td><code>benchmarks.py</code></td><td><code>run</code></td><td>导出格式速度和精度基准</td></tr><tr><td><code>hubconf.py</code></td><td><code>_create</code>, <code>custom</code>, <code>yolov5*</code></td><td>PyTorch Hub</td></tr><tr><td><code>segment/train.py</code></td><td><code>train</code></td><td>实例分割训练</td></tr><tr><td><code>segment/val.py</code></td><td><code>run</code></td><td>实例分割评估</td></tr><tr><td><code>segment/predict.py</code></td><td><code>run</code></td><td>实例分割推理</td></tr><tr><td><code>classify/train.py</code></td><td><code>train</code></td><td>分类训练</td></tr><tr><td><code>classify/val.py</code></td><td><code>run</code></td><td>分类评估</td></tr><tr><td><code>classify/predict.py</code></td><td><code>run</code></td><td>分类推理</td></tr></tbody></table><h2 id="7-2-模型核心"><a href="#7-2-模型核心" class="headerlink" title="7.2 模型核心"></a>7.2 模型核心</h2><table><thead><tr><th>文件&#x2F;类</th><th>职责</th></tr></thead><tbody><tr><td><code>models/yolo.py::Detect</code></td><td>三尺度 Anchor 检测头与推理解码</td></tr><tr><td><code>models/yolo.py::Segment</code></td><td>Detect + Proto 实例分割头</td></tr><tr><td><code>models/yolo.py::BaseModel</code></td><td>通用前向、profile、fuse</td></tr><tr><td><code>models/yolo.py::DetectionModel</code></td><td>从 YAML 构建检测模型</td></tr><tr><td><code>models/yolo.py::ClassificationModel</code></td><td>分类模型或检测 backbone 改造</td></tr><tr><td><code>models/yolo.py::parse_model</code></td><td>YAML → <code>nn.Sequential</code></td></tr><tr><td><code>models/common.py::Conv</code></td><td>Conv+BN+SiLU</td></tr><tr><td><code>models/common.py::C3</code></td><td>CSP 主干模块</td></tr><tr><td><code>models/common.py::SPPF</code></td><td>快速空间金字塔池化</td></tr><tr><td><code>models/common.py::Proto</code></td><td>分割原型</td></tr><tr><td><code>models/common.py::Classify</code></td><td>分类头</td></tr><tr><td><code>models/common.py::DetectMultiBackend</code></td><td>多运行时推理</td></tr><tr><td><code>models/common.py::AutoShape</code></td><td>自动预处理&#x2F;NMS</td></tr><tr><td><code>models/common.py::Detections</code></td><td>结果封装</td></tr><tr><td><code>models/experimental.py::attempt_load</code></td><td><code>.pt</code> 权重&#x2F;集成加载</td></tr></tbody></table><h2 id="7-3-数据与增强"><a href="#7-3-数据与增强" class="headerlink" title="7.3 数据与增强"></a>7.3 数据与增强</h2><table><thead><tr><th>文件&#x2F;对象</th><th>职责</th></tr></thead><tbody><tr><td><code>utils/dataloaders.py::create_dataloader</code></td><td>创建训练&#x2F;验证 DataLoader</td></tr><tr><td><code>LoadImagesAndLabels</code></td><td>检测数据、标签、缓存、增强</td></tr><tr><td><code>LoadImages</code></td><td>图片&#x2F;视频推理输入</td></tr><tr><td><code>LoadStreams</code></td><td>摄像头&#x2F;网络流</td></tr><tr><td><code>LoadScreenshots</code></td><td>屏幕输入</td></tr><tr><td><code>InfiniteDataLoader</code></td><td>复用 worker 的无限迭代器</td></tr><tr><td><code>utils/augmentations.py::letterbox</code></td><td>等比例缩放和 padding</td></tr><tr><td><code>random_perspective</code></td><td>几何增强</td></tr><tr><td><code>augment_hsv</code></td><td>HSV 增强</td></tr><tr><td><code>mixup</code></td><td>MixUp</td></tr><tr><td><code>utils/segment/dataloaders.py</code></td><td>分割数据加载</td></tr><tr><td><code>utils/segment/augmentations.py</code></td><td>分割增强</td></tr></tbody></table><h2 id="7-4-损失与指标"><a href="#7-4-损失与指标" class="headerlink" title="7.4 损失与指标"></a>7.4 损失与指标</h2><table><thead><tr><th>文件&#x2F;对象</th><th>职责</th></tr></thead><tbody><tr><td><code>utils/loss.py::ComputeLoss</code></td><td>CIoU + Obj BCE + Class BCE</td></tr><tr><td><code>ComputeLoss.build_targets</code></td><td>Anchor&#x2F;网格正样本匹配</td></tr><tr><td><code>BCEBlurWithLogitsLoss</code></td><td>缓和缺失标签影响</td></tr><tr><td><code>FocalLoss</code> &#x2F; <code>QFocalLoss</code></td><td>难样本加权</td></tr><tr><td><code>utils/metrics.py::box_iou</code></td><td>IoU 计算</td></tr><tr><td><code>ap_per_class</code></td><td>每类别 P&#x2F;R&#x2F;AP</td></tr><tr><td><code>ConfusionMatrix</code></td><td>混淆矩阵</td></tr><tr><td><code>utils/segment/loss.py</code></td><td>分割损失</td></tr><tr><td><code>utils/segment/metrics.py</code></td><td>Mask AP</td></tr></tbody></table><h2 id="7-5-通用与-PyTorch-工具"><a href="#7-5-通用与-PyTorch-工具" class="headerlink" title="7.5 通用与 PyTorch 工具"></a>7.5 通用与 PyTorch 工具</h2><table><thead><tr><th>文件</th><th>高频内容</th></tr></thead><tbody><tr><td><code>utils/general.py</code></td><td>NMS、坐标转换、路径&#x2F;YAML&#x2F;数据检查</td></tr><tr><td><code>utils/torch_utils.py</code></td><td>设备、AMP、DDP、EMA、优化器、早停</td></tr><tr><td><code>utils/autoanchor.py</code></td><td>Anchor 适配度检查和进化</td></tr><tr><td><code>utils/autobatch.py</code></td><td>自动估算 batch size</td></tr><tr><td><code>utils/callbacks.py</code></td><td>生命周期事件</td></tr><tr><td><code>utils/loggers/</code></td><td>日志平台适配</td></tr><tr><td><code>utils/plots.py</code></td><td>Annotator、训练图、框绘制</td></tr><tr><td><code>utils/downloads.py</code></td><td>数据与权重下载</td></tr></tbody></table><h2 id="7-6-配置文件"><a href="#7-6-配置文件" class="headerlink" title="7.6 配置文件"></a>7.6 配置文件</h2><table><thead><tr><th>路径</th><th>内容</th></tr></thead><tbody><tr><td><code>models/yolov5n.yaml</code></td><td>Nano 检测模型</td></tr><tr><td><code>models/yolov5s.yaml</code></td><td>Small 检测模型</td></tr><tr><td><code>models/yolov5m.yaml</code></td><td>Medium 检测模型</td></tr><tr><td><code>models/yolov5l.yaml</code></td><td>Large 检测模型</td></tr><tr><td><code>models/yolov5x.yaml</code></td><td>Extra Large 检测模型</td></tr><tr><td><code>models/segment/*.yaml</code></td><td>分割模型</td></tr><tr><td><code>models/hub/*.yaml</code></td><td>P6&#x2F;P7 与实验结构</td></tr><tr><td><code>data/*.yaml</code></td><td>数据集路径和类别</td></tr><tr><td><code>data/hyps/*.yaml</code></td><td>学习率、损失和增强超参数</td></tr></tbody></table><h2 id="7-7-检测主调用链"><a href="#7-7-检测主调用链" class="headerlink" title="7.7 检测主调用链"></a>7.7 检测主调用链</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">detect.py::run</span><br><span class="line">  → DetectMultiBackend(...)</span><br><span class="line">      → attempt_load()                  # .pt</span><br><span class="line">  → LoadImages / LoadStreams</span><br><span class="line">      → letterbox()</span><br><span class="line">  → DetectMultiBackend.forward()</span><br><span class="line">      → DetectionModel.forward()</span><br><span class="line">          → BaseModel._forward_once()</span><br><span class="line">              → Detect.forward()</span><br><span class="line">  → non_max_suppression()</span><br><span class="line">  → scale_boxes()</span><br><span class="line">  → Annotator.box_label()</span><br><span class="line">  → cv2.imwrite / VideoWriter</span><br></pre></td></tr></table></figure><h2 id="7-8-训练主调用链"><a href="#7-8-训练主调用链" class="headerlink" title="7.8 训练主调用链"></a>7.8 训练主调用链</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">train.py::main</span><br><span class="line">  → select_device / DDP 初始化</span><br><span class="line">  → train()</span><br><span class="line">      → check_dataset()</span><br><span class="line">      → Model(...) = DetectionModel(...)</span><br><span class="line">          → parse_model()</span><br><span class="line">      → create_dataloader()</span><br><span class="line">          → LoadImagesAndLabels</span><br><span class="line">      → check_anchors()</span><br><span class="line">      → ComputeLoss(model)</span><br><span class="line">      → epoch</span><br><span class="line">          → model(imgs)</span><br><span class="line">          → compute_loss(pred, targets)</span><br><span class="line">              → build_targets()</span><br><span class="line">          → AMP backward</span><br><span class="line">          → optimizer.step()</span><br><span class="line">          → ModelEMA.update()</span><br><span class="line">          → val.run()</span><br><span class="line">          → torch.save(last/best)</span><br></pre></td></tr></table></figure><h2 id="7-9-验证主调用链"><a href="#7-9-验证主调用链" class="headerlink" title="7.9 验证主调用链"></a>7.9 验证主调用链</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">val.py::run</span><br><span class="line">  → DetectMultiBackend 或传入 model</span><br><span class="line">  → create_dataloader</span><br><span class="line">  → forward</span><br><span class="line">  → non_max_suppression</span><br><span class="line">  → scale_boxes</span><br><span class="line">  → process_batch</span><br><span class="line">  → ap_per_class</span><br><span class="line">  → P/R/mAP + confusion matrix</span><br></pre></td></tr></table></figure><h2 id="7-10-导出函数"><a href="#7-10-导出函数" class="headerlink" title="7.10 导出函数"></a>7.10 导出函数</h2><p><code>export.py</code> 主要导出器：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">export_torchscript</span><br><span class="line">export_onnx</span><br><span class="line">export_openvino</span><br><span class="line">export_paddle</span><br><span class="line">export_coreml</span><br><span class="line">export_engine</span><br><span class="line">export_saved_model</span><br><span class="line">export_pb</span><br><span class="line">export_tflite</span><br><span class="line">export_edgetpu</span><br><span class="line">export_tfjs</span><br></pre></td></tr></table></figure><h2 id="7-11-推荐阅读顺序"><a href="#7-11-推荐阅读顺序" class="headerlink" title="7.11 推荐阅读顺序"></a>7.11 推荐阅读顺序</h2><ol><li><code>detect.py::run()</code>：先理解端到端推理</li><li><code>models/yolov5s.yaml</code>：看网络图</li><li><code>models/yolo.py::parse_model()</code>：理解 YAML 如何变成模型</li><li><code>BaseModel._forward_once()</code>：理解跳连执行</li><li><code>Detect.forward()</code>：理解训练输出和推理解码差异</li><li><code>utils/general.py::non_max_suppression()</code>：理解后处理</li><li><code>utils/dataloaders.py::LoadImagesAndLabels</code>：理解输入与增强</li><li><code>utils/loss.py::ComputeLoss</code>：理解监督信号</li><li><code>train.py::train()</code>：最后串起 AMP、EMA、DDP、验证与保存</li><li>按需要读 <code>segment/</code>、<code>classify/</code>、<code>export.py</code></li></ol><h2 id="7-12-二次开发定位"><a href="#7-12-二次开发定位" class="headerlink" title="7.12 二次开发定位"></a>7.12 二次开发定位</h2><table><thead><tr><th>想修改的能力</th><th>优先文件</th></tr></thead><tbody><tr><td>Backbone&#x2F;Neck</td><td>模型 YAML + <code>models/common.py</code></td></tr><tr><td>检测头解码</td><td><code>models/yolo.py::Detect</code></td></tr><tr><td>新网络模块</td><td><code>models/common.py</code> + <code>parse_model</code></td></tr><tr><td>损失函数</td><td><code>utils/loss.py</code></td></tr><tr><td>正样本分配</td><td><code>ComputeLoss.build_targets</code></td></tr><tr><td>数据增强</td><td><code>utils/augmentations.py</code>、DataLoader <code>__getitem__</code></td></tr><tr><td>NMS</td><td><code>utils/general.py</code></td></tr><tr><td>图片&#x2F;流输入</td><td><code>utils/dataloaders.py</code></td></tr><tr><td>训练日志</td><td><code>utils/callbacks.py</code>、<code>utils/loggers/</code></td></tr><tr><td>新导出格式</td><td><code>export.py</code> + <code>DetectMultiBackend</code></td></tr></tbody></table>]]>
    </content>
    <id>http://example.com/n/1226/</id>
    <link href="http://example.com/n/1226/"/>
    <published>2026-09-16T03:06:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="07-源码文件索引"><a href="#07-源码文件索引" class="headerlink" title="07 源码文件索引"></a>07 源码文件索引</h1><p>根路径：</p>
<figure class="highlight text"><t]]>
    </summary>
    <title>YOLOv5 7.0：源码文件索引</title>
    <updated>2026-09-16T03:49:31.708Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="OpenCV-4-13-0-配置、构建与使用指南"><a href="#OpenCV-4-13-0-配置、构建与使用指南" class="headerlink" title="OpenCV 4.13.0 配置、构建与使用指南"></a>OpenCV 4.13.0 配置、构建与使用指南</h1><p>本文给出从 Linux 源码构建到 C++&#x2F;Python 使用、测试、调试和部署的完整流程。内容依据 OpenCV 4.13.0 的根 <code>CMakeLists.txt</code>、模块配置和公开头文件核验。所有命令使用 <code>/path/to</code> 占位，不依赖本文之外的说明。</p><h2 id="1-构建前的版本与目录约定"><a href="#1-构建前的版本与目录约定" class="headerlink" title="1. 构建前的版本与目录约定"></a>1. 构建前的版本与目录约定</h2><p>建议准备三个彼此分离的目录：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">/path/to/opencv-4.13.0/       # 只读源码</span><br><span class="line">/path/to/build-opencv/        # CMake 缓存和编译产物</span><br><span class="line">/path/to/install-opencv/      # 安装结果</span><br></pre></td></tr></table></figure><p>源码外构建便于：</p><ul><li>同时维护 Debug、Release、静态和交叉构建；删除构建目录后干净重配；</li><li>避免生成文件污染源码；明确部署内容来自哪个安装前缀。<br>记录源码标签、提交、编译器和 CMake 版本。若使用 <code>opencv_contrib</code>，主仓库与 contrib 应来自相同版本标签。不要把不同小版本的头文件、库和 Python 扩展混在一起。</li></ul><h2 id="2-Linux-构建环境"><a href="#2-Linux-构建环境" class="headerlink" title="2. Linux 构建环境"></a>2. Linux 构建环境</h2><h3 id="2-1-基础工具"><a href="#2-1-基础工具" class="headerlink" title="2.1 基础工具"></a>2.1 基础工具</h3><p>最低实用工具集包括：</p><ul><li>支持 C++11 及项目要求的 GCC 或 Clang；CMake；</li><li>Ninja 或 Make；pkg-config；</li><li>Python 3 和开发文件；Git、下载工具与证书包；</li><li>目标功能对应的开发包。<br>Debian&#x2F;Ubuntu 类系统的常见准备命令：</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> 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</span><br></pre></td></tr></table></figure><p>这只是常见组合，不是强制清单。服务器可省略 GTK。不用视频时可省略 FFmpeg。发行版包名和版本可能不同，应以 CMake Summary 的探测结果为准。</p><h3 id="2-2-首次-Release-构建"><a href="#2-2-首次-Release-构建" class="headerlink" title="2.2 首次 Release 构建"></a>2.2 首次 Release 构建</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line"></span><br><span class="line">cmake --build /path/to/build-opencv -j</span><br><span class="line">cmake --install /path/to/build-opencv</span><br></pre></td></tr></table></figure><p>单配置生成器使用 <code>CMAKE_BUILD_TYPE</code>。Visual Studio、Xcode 等多配置生成器通常在构建和安装时用 <code>--config Release</code>。不要假设环境变量中的编译器会覆盖已有 CMake 缓存。切换编译器、架构或静态&#x2F;动态策略时应使用新的构建目录。</p><h3 id="2-3-配置结果验收"><a href="#2-3-配置结果验收" class="headerlink" title="2.3 配置结果验收"></a>2.3 配置结果验收</h3><p>配置末尾的 Summary 至少检查：</p><ul><li>OpenCV version；C&#x2F;C++ compiler；</li><li>CPU&#x2F;HW baseline 与 dispatched code；To be built &#x2F; Disabled &#x2F; Unavailable modules；</li><li>GUI 与 Video I&#x2F;O；Media I&#x2F;O；</li><li>Parallel framework；OpenCL、IPP、Eigen 等；</li><li>Python 3 interpreter、libraries、numpy 和 install path；Install to。<br><code>WITH_X=ON</code> 表示请求能力。<code>HAVE_X</code> 或 Summary 中的 YES 才表示探测成功。某个模块未进入 “To be built” 时，安装后不会凭空可用。</li></ul><h2 id="3-CMake-选项语义"><a href="#3-CMake-选项语义" class="headerlink" title="3. CMake 选项语义"></a>3. CMake 选项语义</h2><h3 id="3-1-模块选择"><a href="#3-1-模块选择" class="headerlink" title="3.1 模块选择"></a>3.1 模块选择</h3><table><thead><tr><th>选项</th><th>语义</th></tr></thead><tbody><tr><td><code>BUILD_LIST</code></td><td>构建列出的模块及其必要依赖，接受逗号、空格、冒号等分隔</td></tr><tr><td><code>BUILD_opencv_&lt;name&gt;</code></td><td>单独控制某模块</td></tr><tr><td><code>OPENCV_EXTRA_MODULES_PATH</code></td><td>一个或多个额外模块目录，通常指向 contrib 的 <code>modules</code></td></tr><tr><td><code>BUILD_opencv_world</code></td><td>构建聚合库 <code>opencv_world</code></td></tr><tr><td><code>BUILD_SHARED_LIBS</code></td><td><code>ON</code> 生成共享库，<code>OFF</code> 生成静态库</td></tr><tr><td><code>BUILD_TESTS</code></td><td>构建正确性和回归测试</td></tr><tr><td><code>BUILD_PERF_TESTS</code></td><td>构建性能测试</td></tr><tr><td><code>BUILD_EXAMPLES</code></td><td>构建示例</td></tr><tr><td><code>BUILD_LIST=core,imgproc</code> 会自动加入必要依赖。它不会加入“业务上可能需要”的可选模块。例如 <code>imread</code> 需要 <code>imgcodecs</code>，窗口需要 <code>highgui</code>，摄像头需要 <code>videoio</code>。</td><td></td></tr><tr><td><code>BUILD_opencv_world=ON</code> 方便简单链接。它不减少内部模块依赖，也不保证第三方静态依赖自动适合所有消费方式。需要最小部署、插件隔离或清晰依赖时，按组件链接通常更稳妥。</td><td></td></tr></tbody></table><h3 id="3-2-第三方能力"><a href="#3-2-第三方能力" class="headerlink" title="3.2 第三方能力"></a>3.2 第三方能力</h3><table><thead><tr><th>选项</th><th>主要作用</th></tr></thead><tbody><tr><td><code>WITH_IPP</code></td><td>x86&#x2F;x86_64 上的 Intel IPP 优化</td></tr><tr><td><code>WITH_OPENCL</code></td><td>OpenCL 与 Transparent API</td></tr><tr><td><code>WITH_TBB</code></td><td>TBB 并行后端</td></tr><tr><td><code>WITH_OPENMP</code></td><td>OpenMP 并行支持</td></tr><tr><td><code>WITH_FFMPEG</code></td><td>FFmpeg 视频 I&#x2F;O</td></tr><tr><td><code>WITH_GSTREAMER</code></td><td>GStreamer 视频 I&#x2F;O</td></tr><tr><td><code>WITH_GTK</code> &#x2F; <code>WITH_QT</code> &#x2F; <code>WITH_WAYLAND</code></td><td>Linux GUI 后端</td></tr><tr><td><code>WITH_CUDA</code></td><td>CUDA runtime 与相关能力</td></tr><tr><td><code>WITH_CUDNN</code></td><td>DNN CUDA 路径使用 cuDNN</td></tr><tr><td><code>WITH_OPENVINO</code></td><td>OpenVINO DNN 后端</td></tr><tr><td><code>OPENCV_ENABLE_NONFREE</code></td><td>启用受额外许可约束的算法，默认关闭</td></tr><tr><td>选项默认值受平台条件影响。OpenCV 4.13.0 根配置对 <code>WITH_CUDA</code>、<code>WITH_OPENVX</code>、<code>WITH_FASTCV</code> 等默认关闭。打开选项后仍需匹配开发头、库、工具链和版本。</td><td></td></tr></tbody></table><h3 id="3-3-CPU-与构建质量"><a href="#3-3-CPU-与构建质量" class="headerlink" title="3.3 CPU 与构建质量"></a>3.3 CPU 与构建质量</h3><table><thead><tr><th>选项</th><th>语义</th></tr></thead><tbody><tr><td><code>CPU_BASELINE</code></td><td>运行二进制所要求的最低 CPU 指令集</td></tr><tr><td><code>CPU_DISPATCH</code></td><td>额外编译并在运行时选择的指令集</td></tr><tr><td><code>CV_DISABLE_OPTIMIZATION</code></td><td>关闭多类优化，主要用于诊断</td></tr><tr><td><code>ENABLE_LTO</code></td><td>请求链接时优化</td></tr><tr><td><code>ENABLE_FAST_MATH</code></td><td>允许影响严格浮点语义的优化</td></tr><tr><td><code>CMAKE_BUILD_TYPE</code></td><td>单配置生成器的 Release&#x2F;Debug&#x2F;RelWithDebInfo</td></tr><tr><td>提高 baseline 会牺牲旧 CPU 兼容性。通用发布包更适合保守 baseline 加 runtime dispatch。<code>ENABLE_FAST_MATH</code> 可能改变 NaN、舍入和可重复性，不应只因“更快”而默认打开。</td><td></td></tr></tbody></table><h3 id="3-4-Python-相关"><a href="#3-4-Python-相关" class="headerlink" title="3.4 Python 相关"></a>3.4 Python 相关</h3><p>常用变量包括：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">BUILD_opencv_python3</span><br><span class="line">PYTHON3_EXECUTABLE</span><br><span class="line">PYTHON3_INCLUDE_DIR</span><br><span class="line">PYTHON3_LIBRARY</span><br><span class="line">PYTHON3_NUMPY_INCLUDE_DIRS</span><br><span class="line">PYTHON3_PACKAGES_PATH</span><br></pre></td></tr></table></figure><p>优先指定目标虚拟环境中的 <code>PYTHON3_EXECUTABLE</code>。其余变量只有在自动探测错误时再显式设置。配置 Summary 必须显示预期解释器、NumPy 和安装路径。</p><h3 id="3-5-缓存与重配置"><a href="#3-5-缓存与重配置" class="headerlink" title="3.5 缓存与重配置"></a>3.5 缓存与重配置</h3><p>查看缓存：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cmake -L -N /path/to/build-opencv</span><br><span class="line">cmake -LAH -N /path/to/build-opencv</span><br></pre></td></tr></table></figure><p>更改单个普通选项可重新运行 <code>cmake -S ... -B ...</code>。更改编译器、sysroot、生成器、目标架构或主要依赖版本时新建构建目录。不要手工编辑 <code>CMakeCache.txt</code> 作为常规配置方式。</p><h2 id="4-常见构建配方"><a href="#4-常见构建配方" class="headerlink" title="4. 常见构建配方"></a>4. 常见构建配方</h2><h3 id="4-1-最小图像处理"><a href="#4-1-最小图像处理" class="headerlink" title="4.1 最小图像处理"></a>4.1 最小图像处理</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line">cmake --build /path/to/build-min -j</span><br><span class="line">cmake --install /path/to/build-min</span><br></pre></td></tr></table></figure><p>此配方适合无 GUI 的离线图像处理。PNG&#x2F;JPEG 等能力仍取决于 Media I&#x2F;O 探测。</p><h3 id="4-2-完整桌面构建"><a href="#4-2-完整桌面构建" class="headerlink" title="4.2 完整桌面构建"></a>4.2 完整桌面构建</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line">cmake --build /path/to/build-full -j</span><br></pre></td></tr></table></figure><p>“完整”不是开启所有实验后端。只启用目标机器安装、测试和部署得了的能力。</p><h3 id="4-3-contrib-构建"><a href="#4-3-contrib-构建" class="headerlink" title="4.3 contrib 构建"></a>4.3 contrib 构建</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line">cmake --build /path/to/build-contrib -j</span><br><span class="line">cmake --install /path/to/build-contrib</span><br></pre></td></tr></table></figure><p>变量应指向 <code>modules</code> 目录，不是 contrib 仓库根目录。若只需少数模块，可同时使用：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-D BUILD_LIST=core,imgproc,imgcodecs,features2d,xfeatures2d</span><br></pre></td></tr></table></figure><p>启用 <code>OPENCV_ENABLE_NONFREE=ON</code> 前先审查算法和部署地区的许可要求。</p><h3 id="4-4-静态构建"><a href="#4-4-静态构建" class="headerlink" title="4.4 静态构建"></a>4.4 静态构建</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line">cmake --build /path/to/build-static -j</span><br><span class="line">cmake --install /path/to/build-static</span><br></pre></td></tr></table></figure><p>静态 OpenCV 不等于最终应用完全静态。编解码器、线程库、系统库和 C++ 运行库仍可能需要显式链接。优先使用安装导出的 CMake 配置传播依赖，不要手写一串 <code>.a</code>。</p><h3 id="4-5-Debug-和-RelWithDebInfo"><a href="#4-5-Debug-和-RelWithDebInfo" class="headerlink" title="4.5 Debug 和 RelWithDebInfo"></a>4.5 Debug 和 RelWithDebInfo</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line">cmake --build /path/to/build-debug -j</span><br></pre></td></tr></table></figure><p><code>Debug</code> 最便于断言和逐步调试，但性能不能代表发布构建。<code>RelWithDebInfo</code> 常用于接近 Release 的采样和崩溃符号化。</p><h3 id="4-6-Linux-交叉构建"><a href="#4-6-Linux-交叉构建" class="headerlink" title="4.6 Linux 交叉构建"></a>4.6 Linux 交叉构建</h3><p>OpenCV 源码提供多种工具链文件，例如：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">platforms/linux/aarch64-gnu.toolchain.cmake</span><br><span class="line">platforms/linux/arm-gnueabi.toolchain.cmake</span><br><span class="line">platforms/linux/riscv64-gcc.toolchain.cmake</span><br><span class="line">platforms/linux/riscv64-clang.toolchain.cmake</span><br></pre></td></tr></table></figure><p>示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">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</span><br><span class="line">cmake --build /path/to/build-aarch64 -j</span><br><span class="line">cmake --install /path/to/build-aarch64</span><br></pre></td></tr></table></figure><p><code>CMAKE_INSTALL_PREFIX=/usr</code> 表示目标机路径。<code>CMAKE_STAGING_PREFIX</code> 是主机侧暂存位置。还可按部署流程使用 <code>DESTDIR</code>，但不要同时混淆两套根目录语义。<br>交叉构建验收：</p><ul><li>编译器目标三元组正确；sysroot 中头和库属于目标架构；</li><li><code>file</code> 或 <code>readelf</code> 显示正确 ELF 架构；CMake 没有误用主机 <code>/usr/lib</code>；</li><li>Python 绑定没有把主机解释器库误当目标库；在真实设备或模拟环境运行最小测试。</li></ul><h2 id="5-安装与卸载边界"><a href="#5-安装与卸载边界" class="headerlink" title="5. 安装与卸载边界"></a>5. 安装与卸载边界</h2><p>安装后常见布局：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/path/to/install-opencv/include/opencv4/</span><br><span class="line">/path/to/install-opencv/lib/</span><br><span class="line">/path/to/install-opencv/lib/cmake/opencv4/</span><br><span class="line">/path/to/install-opencv/bin/</span><br></pre></td></tr></table></figure><p>精确布局受平台和 GNUInstallDirs 影响。消费工程应通过 <code>OpenCVConfig.cmake</code> 查找，不应依赖固定相对层数。<br>安装到系统前缀：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> cmake --install /path/to/build-opencv</span><br></pre></td></tr></table></figure><p>更推荐先安装到项目管理的独立前缀。源码构建通常没有可靠的通用 <code>uninstall</code> 目标。使用独立前缀可通过删除整个前缀干净移除。不要覆盖发行版管理器拥有的同名文件。</p><h2 id="6-C-工程消费"><a href="#6-C-工程消费" class="headerlink" title="6. C++ 工程消费"></a>6. C++ 工程消费</h2><h3 id="6-1-推荐-CMake-写法"><a href="#6-1-推荐-CMake-写法" class="headerlink" title="6.1 推荐 CMake 写法"></a>6.1 推荐 CMake 写法</h3><p><code>CMakeLists.txt</code>：</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.16</span>)</span><br><span class="line"><span class="keyword">project</span>(opencv_demo LANGUAGES CXX)</span><br><span class="line"></span><br><span class="line"><span class="keyword">find_package</span>(OpenCV <span class="number">4.13</span> REQUIRED</span><br><span class="line">  COMPONENTS core imgproc imgcodecs videoio dnn)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_executable</span>(opencv_demo main.cpp)</span><br><span class="line"><span class="keyword">target_compile_features</span>(opencv_demo PRIVATE cxx_std_17)</span><br><span class="line"><span class="keyword">target_include_directories</span>(opencv_demo PRIVATE <span class="variable">$&#123;OpenCV_INCLUDE_DIRS&#125;</span>)</span><br><span class="line"><span class="keyword">target_link_libraries</span>(opencv_demo PRIVATE <span class="variable">$&#123;OpenCV_LIBS&#125;</span>)</span><br></pre></td></tr></table></figure><p>配置消费工程：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cmake -S /path/to/app -B /path/to/build-app -G Ninja -D OpenCV_DIR=/path/to/install-opencv/lib/cmake/opencv4</span><br><span class="line">cmake --build /path/to/build-app</span><br></pre></td></tr></table></figure><p>某些安装还提供导出的具体 target。可用名称应以该安装的 <code>OpenCVConfig.cmake</code> 为准。<code>${OpenCV_LIBS}</code> 是跨不同 OpenCV 包布局更常见的兼容写法。</p><h3 id="6-2-pkg-config"><a href="#6-2-pkg-config" class="headerlink" title="6.2 pkg-config"></a>6.2 pkg-config</h3><p>根配置中的 <code>OPENCV_GENERATE_PKGCONFIG</code> 默认关闭且标为 deprecated。新工程优先使用 CMake package config。必须兼容旧构建系统时，可显式请求生成并验证：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pkg-config --cflags --libs opencv4</span><br></pre></td></tr></table></figure><p>静态链接时还要检查：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pkg-config --static --libs opencv4</span><br></pre></td></tr></table></figure><h3 id="6-3-最小图像程序"><a href="#6-3-最小图像程序" class="headerlink" title="6.3 最小图像程序"></a>6.3 最小图像程序</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;opencv2/imgcodecs.hpp&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;opencv2/imgproc.hpp&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (argc != <span class="number">3</span>) &#123;</span><br><span class="line">        std::cerr &lt;&lt; <span class="string">&quot;usage: app input output\n&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    cv::Mat image = cv::<span class="built_in">imread</span>(argv[<span class="number">1</span>], cv::IMREAD_COLOR);</span><br><span class="line">    <span class="keyword">if</span> (image.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        std::cerr &lt;&lt; <span class="string">&quot;cannot decode input\n&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">3</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    cv::Mat gray, edges;</span><br><span class="line">    cv::<span class="built_in">cvtColor</span>(image, gray, cv::COLOR_BGR2GRAY);</span><br><span class="line">    cv::<span class="built_in">GaussianBlur</span>(gray, gray, cv::<span class="built_in">Size</span>(<span class="number">5</span>, <span class="number">5</span>), <span class="number">1.2</span>);</span><br><span class="line">    cv::<span class="built_in">Canny</span>(gray, edges, <span class="number">50</span>, <span class="number">150</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!cv::<span class="built_in">imwrite</span>(argv[<span class="number">2</span>], edges)) &#123;</span><br><span class="line">        std::cerr &lt;&lt; <span class="string">&quot;cannot encode output\n&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">4</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>检查 <code>imread()</code>、<code>VideoCapture::isOpened()</code> 和模型读取结果。不要让空矩阵继续进入算法后才处理异常。</p><h2 id="7-Python-构建与使用"><a href="#7-Python-构建与使用" class="headerlink" title="7. Python 构建与使用"></a>7. Python 构建与使用</h2><h3 id="7-1-在虚拟环境中构建"><a href="#7-1-在虚拟环境中构建" class="headerlink" title="7.1 在虚拟环境中构建"></a>7.1 在虚拟环境中构建</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python3 -m venv /path/to/venv</span><br><span class="line">/path/to/venv/bin/python -m pip install --upgrade pip numpy</span><br><span class="line"></span><br><span class="line">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</span><br><span class="line">cmake --build /path/to/build-python -j</span><br><span class="line">cmake --install /path/to/build-python</span><br></pre></td></tr></table></figure><p>把 <code>python3.x</code> 替换为实际版本目录。安装后验证实际加载文件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">/path/to/venv/bin/python - &lt;&lt;<span class="string">&#x27;PY&#x27;</span></span><br><span class="line">import cv2</span><br><span class="line"><span class="built_in">print</span>(cv2.__version__)</span><br><span class="line"><span class="built_in">print</span>(cv2.__file__)</span><br><span class="line"><span class="built_in">print</span>(cv2.getBuildInformation())</span><br><span class="line">PY</span><br></pre></td></tr></table></figure><h3 id="7-2-Python-API-示例"><a href="#7-2-Python-API-示例" class="headerlink" title="7.2 Python API 示例"></a>7.2 Python API 示例</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pathlib <span class="keyword">import</span> Path</span><br><span class="line"><span class="keyword">import</span> cv2</span><br><span class="line"></span><br><span class="line">src_path = Path(<span class="string">&quot;/path/to/input.jpg&quot;</span>)</span><br><span class="line">dst_path = Path(<span class="string">&quot;/path/to/output.png&quot;</span>)</span><br><span class="line"></span><br><span class="line">image = cv2.imread(<span class="built_in">str</span>(src_path), cv2.IMREAD_COLOR)</span><br><span class="line"><span class="keyword">if</span> image <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">    <span class="keyword">raise</span> FileNotFoundError(src_path)</span><br><span class="line"></span><br><span class="line">gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)</span><br><span class="line">edges = cv2.Canny(gray, <span class="number">50</span>, <span class="number">150</span>)</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> cv2.imwrite(<span class="built_in">str</span>(dst_path), edges):</span><br><span class="line">    <span class="keyword">raise</span> RuntimeError(<span class="string">f&quot;cannot write <span class="subst">&#123;dst_path&#125;</span>&quot;</span>)</span><br></pre></td></tr></table></figure><p>Python 的 NumPy 数组常与 <code>cv::Mat</code> 共享或包装内存。注意 dtype、shape、stride、连续性和生命周期。避免在热点循环中无意义调用 <code>np.ascontiguousarray()</code> 或复制。</p><h3 id="7-3-常见-Python-混装"><a href="#7-3-常见-Python-混装" class="headerlink" title="7.3 常见 Python 混装"></a>7.3 常见 Python 混装</h3><p>系统包、pip wheel 和源码构建的 <code>cv2</code> 可能同时存在。表现包括：</p><ul><li><code>cv2.__version__</code> 不是 4.13.0；<code>getBuildInformation()</code> 缺少刚启用的后端；</li><li>导入时报未定义符号；NumPy ABI 不匹配；</li><li>IDE 与终端使用不同解释器。<br>总是先打印：</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> cv2, sys</span><br><span class="line"><span class="built_in">print</span>(sys.executable); <span class="built_in">print</span>(cv2.__file__); <span class="built_in">print</span>(cv2.__version__)</span><br></pre></td></tr></table></figure><h2 id="8-视频读取与写入"><a href="#8-视频读取与写入" class="headerlink" title="8. 视频读取与写入"></a>8. 视频读取与写入</h2><p>C++ 示例：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">cv::VideoCapture <span class="title">cap</span><span class="params">(<span class="string">&quot;/path/to/input.mp4&quot;</span>, cv::CAP_ANY)</span></span>;</span><br><span class="line"><span class="keyword">if</span> (!cap.<span class="built_in">isOpened</span>())</span><br><span class="line">    <span class="keyword">throw</span> std::<span class="built_in">runtime_error</span>(<span class="string">&quot;cannot open video&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">double</span> fps = cap.<span class="built_in">get</span>(cv::CAP_PROP_FPS);</span><br><span class="line"><span class="type">int</span> width = <span class="keyword">static_cast</span>&lt;<span class="type">int</span>&gt;(cap.<span class="built_in">get</span>(cv::CAP_PROP_FRAME_WIDTH));</span><br><span class="line"><span class="type">int</span> height = <span class="keyword">static_cast</span>&lt;<span class="type">int</span>&gt;(cap.<span class="built_in">get</span>(cv::CAP_PROP_FRAME_HEIGHT));</span><br><span class="line"></span><br><span class="line"><span class="function">cv::VideoWriter <span class="title">out</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">    <span class="string">&quot;/path/to/output.mp4&quot;</span>,</span></span></span><br><span class="line"><span class="params"><span class="function">    cv::VideoWriter::fourcc(<span class="string">&#x27;m&#x27;</span>, <span class="string">&#x27;p&#x27;</span>, <span class="string">&#x27;4&#x27;</span>, <span class="string">&#x27;v&#x27;</span>),</span></span></span><br><span class="line"><span class="params"><span class="function">    fps &gt; <span class="number">0</span> ? fps : <span class="number">30.0</span>,</span></span></span><br><span class="line"><span class="params"><span class="function">    cv::Size(width, height))</span></span>;</span><br><span class="line"><span class="keyword">if</span> (!out.<span class="built_in">isOpened</span>())</span><br><span class="line">    <span class="keyword">throw</span> std::<span class="built_in">runtime_error</span>(<span class="string">&quot;cannot open writer&quot;</span>);</span><br><span class="line"></span><br><span class="line">cv::Mat frame;</span><br><span class="line"><span class="keyword">while</span> (cap.<span class="built_in">read</span>(frame)) &#123;</span><br><span class="line">    cv::<span class="built_in">putText</span>(frame, <span class="string">&quot;OpenCV&quot;</span>, &#123;<span class="number">20</span>, <span class="number">40</span>&#125;,</span><br><span class="line">                cv::FONT_HERSHEY_SIMPLEX, <span class="number">1.0</span>, &#123;<span class="number">0</span>, <span class="number">255</span>, <span class="number">0</span>&#125;, <span class="number">2</span>);</span><br><span class="line">    out.<span class="built_in">write</span>(frame);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>后端、容器和 codec 是三层概念。文件扩展名不能保证编码器存在。用 <code>cap.getBackendName()</code> 或调试日志确认实际后端。相机可显式传 <code>cv::CAP_V4L2</code>、<code>cv::CAP_GSTREAMER</code> 等偏好，但必须由构建支持。<br>在 Python 中：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">cap = cv2.VideoCapture(<span class="string">&quot;/path/to/input.mp4&quot;</span>, cv2.CAP_ANY)</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> cap.isOpened():</span><br><span class="line">    <span class="keyword">raise</span> RuntimeError(<span class="string">&quot;cannot open video&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        ok, frame = cap.read()</span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> ok:</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        <span class="comment"># process frame</span></span><br><span class="line"><span class="keyword">finally</span>:</span><br><span class="line">    cap.release()</span><br></pre></td></tr></table></figure><p>生产服务应限制网络流的连接、读取和重连策略。不要无限阻塞或无限缓存来自不可信源的视频。</p><h2 id="9-DNN-推理"><a href="#9-DNN-推理" class="headerlink" title="9. DNN 推理"></a>9. DNN 推理</h2><h3 id="9-1-ONNX-基本流程"><a href="#9-1-ONNX-基本流程" class="headerlink" title="9.1 ONNX 基本流程"></a>9.1 ONNX 基本流程</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">cv::dnn::Net net = cv::dnn::<span class="built_in">readNetFromONNX</span>(<span class="string">&quot;/path/to/model.onnx&quot;</span>);</span><br><span class="line"><span class="keyword">if</span> (net.<span class="built_in">empty</span>())</span><br><span class="line">    <span class="keyword">throw</span> std::<span class="built_in">runtime_error</span>(<span class="string">&quot;cannot load model&quot;</span>);</span><br><span class="line"></span><br><span class="line">net.<span class="built_in">setPreferableBackend</span>(cv::dnn::DNN_BACKEND_OPENCV);</span><br><span class="line">net.<span class="built_in">setPreferableTarget</span>(cv::dnn::DNN_TARGET_CPU);</span><br><span class="line"></span><br><span class="line">cv::Mat blob = cv::dnn::<span class="built_in">blobFromImage</span>(</span><br><span class="line">    image, <span class="number">1.0</span> / <span class="number">255.0</span>, cv::<span class="built_in">Size</span>(<span class="number">640</span>, <span class="number">640</span>),</span><br><span class="line">    cv::<span class="built_in">Scalar</span>(), <span class="literal">true</span>, <span class="literal">false</span>, CV_32F);</span><br><span class="line">net.<span class="built_in">setInput</span>(blob);</span><br><span class="line">cv::Mat output = net.forward();</span><br></pre></td></tr></table></figure><p>预处理参数必须来自模型契约：</p><ul><li>输入尺寸；NCHW 或其他布局；</li><li>BGR&#x2F;RGB 顺序；scale；</li><li>mean；crop 或 letterbox；</li><li>输入精度；输出节点和后处理。<br>“能运行”不代表预处理正确。应使用已知样本与参考框架对齐输出。</li></ul><h3 id="9-2-查询并选择后端"><a href="#9-2-查询并选择后端" class="headerlink" title="9.2 查询并选择后端"></a>9.2 查询并选择后端</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span>&amp; p : cv::dnn::<span class="built_in">getAvailableBackends</span>())</span><br><span class="line">    std::cout &lt;&lt; p.first &lt;&lt; <span class="string">&#x27;:&#x27;</span> &lt;&lt; p.second &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br></pre></td></tr></table></figure><p>公开后端包括 OpenCV、OpenVINO、CUDA、Halide、VkCom、WebNN、TIM-VX 和 CANN 等。实际可用组合由构建与运行时依赖决定。先查询，再设置 backend&#x2F;target。首次推理通常包含初始化或编译，性能测试要预热。</p><h3 id="9-3-DNN-诊断"><a href="#9-3-DNN-诊断" class="headerlink" title="9.3 DNN 诊断"></a>9.3 DNN 诊断</h3><p>可先提高日志等级：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OPENCV_LOG_LEVEL=DEBUG /path/to/dnn-app</span><br></pre></td></tr></table></figure><p>进一步排查可使用：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OPENCV_DNN_CHECK_NAN_INF=1 OPENCV_DNN_CHECK_NAN_INF_RAISE_ERROR=1 /path/to/dnn-app</span><br></pre></td></tr></table></figure><p>这些检查会影响性能，仅用于诊断。对不支持的 ONNX 算子，先最小化模型并记录导出器版本、opset 和错误层。</p><h2 id="10-samples、tests-与-perf"><a href="#10-samples、tests-与-perf" class="headerlink" title="10. samples、tests 与 perf"></a>10. samples、tests 与 perf</h2><p>源码中的主要样例目录：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">samples/cpp/</span><br><span class="line">samples/python/</span><br><span class="line">samples/dnn/</span><br><span class="line">samples/tapi/</span><br><span class="line">samples/opencl/</span><br><span class="line">samples/gpu/</span><br><span class="line">samples/hal/</span><br></pre></td></tr></table></figure><p>启用示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cmake -S /path/to/opencv-4.13.0 -B /path/to/build-samples -D CMAKE_BUILD_TYPE=Release -D BUILD_EXAMPLES=ON</span><br><span class="line">cmake --build /path/to/build-samples -j</span><br></pre></td></tr></table></figure><p>正确性与性能测试分别位于各模块的 <code>test/</code> 和 <code>perf/</code>。常见目标名：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">opencv_test_core</span><br><span class="line">opencv_test_imgproc</span><br><span class="line">opencv_perf_core</span><br><span class="line">opencv_perf_imgproc</span><br></pre></td></tr></table></figure><p>运行单个测试：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/path/to/build-opencv/bin/opencv_test_core --gtest_filter=<span class="string">&#x27;Core_Mat.*&#x27;</span></span><br></pre></td></tr></table></figure><p>通过 CTest：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ctest --test-dir /path/to/build-opencv --output-on-failure</span><br></pre></td></tr></table></figure><p>性能测试：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/path/to/build-opencv/bin/opencv_perf_imgproc --gtest_filter=<span class="string">&#x27;*GaussianBlur*&#x27;</span></span><br></pre></td></tr></table></figure><p>先运行可执行文件的 <code>--help</code> 确认当前参数。测试数据可能要求额外数据仓库或环境变量。跨机器比较 perf 前固定构建类型、线程数、温度、频率和输入。</p><h2 id="11-调试与日志"><a href="#11-调试与日志" class="headerlink" title="11. 调试与日志"></a>11. 调试与日志</h2><h3 id="11-1-运行时构建信息"><a href="#11-1-运行时构建信息" class="headerlink" title="11.1 运行时构建信息"></a>11.1 运行时构建信息</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">std::cout &lt;&lt; cv::<span class="built_in">getVersionString</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">std::cout &lt;&lt; cv::<span class="built_in">getBuildInformation</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">std::cout &lt;&lt; cv::<span class="built_in">getCPUFeaturesLine</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">std::cout &lt;&lt; cv::<span class="built_in">getNumThreads</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br></pre></td></tr></table></figure><p>Python 对应：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(cv2.__version__); <span class="built_in">print</span>(cv2.getBuildInformation()); <span class="built_in">print</span>(cv2.getCPUFeaturesLine()); <span class="built_in">print</span>(cv2.getNumThreads())</span><br></pre></td></tr></table></figure><h3 id="11-2-日志级别"><a href="#11-2-日志级别" class="headerlink" title="11.2 日志级别"></a>11.2 日志级别</h3><p>环境变量方式：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OPENCV_LOG_LEVEL=DEBUG /path/to/app</span><br></pre></td></tr></table></figure><p>C++ API：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;opencv2/core/utils/logger.hpp&gt;</span></span></span><br><span class="line"></span><br><span class="line">cv::utils::logging::<span class="built_in">setLogLevel</span>(</span><br><span class="line">    cv::utils::logging::LOG_LEVEL_VERBOSE);</span><br></pre></td></tr></table></figure><p>详细日志可能包含设备、后端和文件信息。生产环境应控制等级并避免把敏感路径直接发送到外部日志。</p><h3 id="11-3-GDB-与-sanitizer"><a href="#11-3-GDB-与-sanitizer" class="headerlink" title="11.3 GDB 与 sanitizer"></a>11.3 GDB 与 sanitizer</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gdb --args /path/to/app /path/to/input.jpg</span><br></pre></td></tr></table></figure><p>应用和 OpenCV 都有符号时回溯最有价值。如需 sanitizer，建议建立独立构建并统一编译、链接选项。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cmake -S /path/to/opencv-4.13.0 -B /path/to/build-asan -G Ninja -D CMAKE_BUILD_TYPE=Debug -D CMAKE_C_FLAGS=<span class="string">&#x27;-fsanitize=address -fno-omit-frame-pointer&#x27;</span> -D CMAKE_CXX_FLAGS=<span class="string">&#x27;-fsanitize=address -fno-omit-frame-pointer&#x27;</span> -D CMAKE_EXE_LINKER_FLAGS=<span class="string">&#x27;-fsanitize=address&#x27;</span> -D CMAKE_SHARED_LINKER_FLAGS=<span class="string">&#x27;-fsanitize=address&#x27;</span></span><br></pre></td></tr></table></figure><p>常规定位顺序：</p><ol><li>确认实际加载的 OpenCV；</li><li>保存原始输入和最小复现；</li><li>打印尺寸、类型、步长和连续性；</li><li>单线程复现；</li><li>关闭特定加速后端做对照；</li><li>使用 Debug、断言和 sanitizer；</li><li>修复后增加回归测试。</li></ol><h2 id="12-部署"><a href="#12-部署" class="headerlink" title="12. 部署"></a>12. 部署</h2><h3 id="12-1-共享库部署"><a href="#12-1-共享库部署" class="headerlink" title="12.1 共享库部署"></a>12.1 共享库部署</h3><p>查看 ELF 依赖：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ldd /path/to/app</span><br><span class="line">readelf -d /path/to/app</span><br></pre></td></tr></table></figure><p>部署时包含：</p><ul><li>应用直接依赖的 OpenCV <code>.so</code>；OpenCV 所需第三方运行库；</li><li>视频、GUI 或 DNN 插件；模型、级联文件和配置；</li><li>与目标系统兼容的 C++ 运行库。<br>使用 RPATH&#x2F;RUNPATH 或系统动态链接器配置管理查找路径。不要依赖开发机的 <code>LD_LIBRARY_PATH</code> 作为正式部署方案。</li></ul><h3 id="12-2-容器部署"><a href="#12-2-容器部署" class="headerlink" title="12.2 容器部署"></a>12.2 容器部署</h3><p>多阶段构建可将编译环境与运行环境分开。运行镜像只复制安装前缀、应用和必要运行库。还要考虑：</p><ul><li>摄像头设备映射；GPU 驱动与容器 runtime；</li><li>GUI socket；codec 和字体；</li><li>非 root 用户权限；只读文件系统下的缓存目录。</li></ul><h3 id="12-3-静态部署"><a href="#12-3-静态部署" class="headerlink" title="12.3 静态部署"></a>12.3 静态部署</h3><p>静态链接降低部分运行时查找问题，但会：</p><ul><li>增大文件；增加第三方依赖传播复杂度；</li><li>影响插件能力；加重许可证合规工作；</li><li>使安全更新需要重新链接和发布。<br>无论共享或静态，都应生成软件物料清单并保留构建配置。</li></ul><h2 id="13-ABI-与版本共存"><a href="#13-ABI-与版本共存" class="headerlink" title="13. ABI 与版本共存"></a>13. ABI 与版本共存</h2><p>不要假设所有 OpenCV 4.x 二进制 ABI 永久兼容。风险来源包括：</p><ul><li>编译器和 libstdc++ ABI；Debug 与 Release 混用；</li><li><code>_GLIBCXX_USE_CXX11_ABI</code>；静态与共享库组合；</li><li>contrib 与主库版本不一致；第三方库 ABI；</li><li>DNN 插件与核心库版本；Python 与 NumPy ABI。<br>最佳实践：</li><li>应用与 OpenCV 使用兼容工具链；编译时和运行时加载同一安装前缀；</li><li>通过 <code>OpenCV_DIR</code> 固定消费版本；不混合多个前缀的头和库；</li><li>插件与主库一起构建、测试和部署；升级小版本也执行 ABI 与回归验证；</li><li>对公共接口避免暴露 <code>cv::Mat</code> 跨不受控插件边界，除非双方 ABI 被锁定。<br>并行安装可使用不同前缀。运行时通过 RUNPATH 或隔离容器选择版本。不要用覆盖系统库的方式实现升级。</li></ul><h2 id="14-迁移到-4-13-0"><a href="#14-迁移到-4-13-0" class="headerlink" title="14. 迁移到 4.13.0"></a>14. 迁移到 4.13.0</h2><p>迁移检查清单：</p><ul><li>移除旧 C API 和废弃常量；核对模块是否移动到 contrib；</li><li>检查返回值、默认参数和 Python tuple 形态；重新导出并验证 DNN 模型；</li><li>核对 ONNX opset 和后端覆盖；重新验证视频后端、codec 和设备索引；</li><li>检查序列化文件、标定参数和模型兼容性；更新 CMake 的组件列表；</li><li>重跑正确性、性能和资源泄漏测试；检查许可证与部署依赖变化。<br>迁移时先固定旧版输出样本。对浮点算法定义绝对或相对误差，而不是要求逐位一致。同时比较性能分布，避免因后端改变出现隐性回退。</li></ul><h2 id="15-安全与资源管理"><a href="#15-安全与资源管理" class="headerlink" title="15. 安全与资源管理"></a>15. 安全与资源管理</h2><p>OpenCV 处理的是复杂二进制格式、视频流和模型。不可信输入应视为攻击面。</p><h3 id="15-1-输入控制"><a href="#15-1-输入控制" class="headerlink" title="15.1 输入控制"></a>15.1 输入控制</h3><ul><li>在解码前限制文件大小；解码后限制宽、高、通道和总像素；</li><li>对视频限制帧率、分辨率、时长和重连次数；对模型限制来源、大小和允许格式；</li><li>拒绝路径穿越和意外覆盖输出；设置任务超时和内存上限；</li><li>将解析服务放入低权限进程或容器；跟踪 OpenCV 与 codec 库安全更新。<br>像素内存约为：</li></ul><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rows * step</span><br></pre></td></tr></table></figure><p>不能只用压缩文件大小估算解码内存。超高压缩比图片和畸形尺寸可能导致资源耗尽。</p><h3 id="15-2-C-生命周期"><a href="#15-2-C-生命周期" class="headerlink" title="15.2 C++ 生命周期"></a>15.2 C++ 生命周期</h3><p><code>cv::Mat</code> 使用引用计数并支持浅拷贝。返回引用、ROI 或包装外部缓冲区时，必须保证底层内存仍存活。跨线程共享只读矩阵通常可行，但并发写入需要应用自行同步。<br>资源对象使用 RAII：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="function">cv::VideoCapture <span class="title">cap</span><span class="params">(<span class="string">&quot;/path/to/input.mp4&quot;</span>)</span></span>;</span><br><span class="line">    <span class="keyword">if</span> (!cap.<span class="built_in">isOpened</span>())</span><br><span class="line">        <span class="keyword">throw</span> std::<span class="built_in">runtime_error</span>(<span class="string">&quot;open failed&quot;</span>);</span><br><span class="line">    <span class="comment">// cap leaves scope and releases resources</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不要把 <code>Mat::data</code> 保存到超过矩阵生命周期的异步任务。包装外部内存时，OpenCV 不一定拥有或释放该内存。</p><h3 id="15-3-Python-生命周期"><a href="#15-3-Python-生命周期" class="headerlink" title="15.3 Python 生命周期"></a>15.3 Python 生命周期</h3><p>使用 <code>try/finally</code> 释放摄像头和 writer。长服务中不要无界保存帧列表。NumPy 视图与 <code>cv2</code> 返回数组共享数据时，保留拥有者引用。捕获 <code>cv2.error</code> 时记录操作和输入元数据，但避免记录敏感图像本身。</p><h2 id="16-FAQ"><a href="#16-FAQ" class="headerlink" title="16. FAQ"></a>16. FAQ</h2><h3 id="16-1-找不到-OpenCVConfig-cmake"><a href="#16-1-找不到-OpenCVConfig-cmake" class="headerlink" title="16.1 找不到 OpenCVConfig.cmake"></a>16.1 找不到 <code>OpenCVConfig.cmake</code></h3><p>显式指定：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-D OpenCV_DIR=/path/to/install-opencv/lib/cmake/opencv4</span><br></pre></td></tr></table></figure><p>确认该文件确实由 <code>cmake --install</code> 生成。不要把 <code>OpenCV_DIR</code> 指向源码根目录。</p><h3 id="16-2-头文件找到但链接失败"><a href="#16-2-头文件找到但链接失败" class="headerlink" title="16.2 头文件找到但链接失败"></a>16.2 头文件找到但链接失败</h3><p>常见原因：</p><ul><li>头来自一个版本，库来自另一个版本；忘记请求对应组件；</li><li>静态第三方依赖未传播；Debug&#x2F;Release 或 C++ ABI 不一致；</li><li>链接顺序不适合手写静态库列表。<br>删除手写 <code>-lopencv_*</code>，先用安装导出的 CMake 配置复现。</li></ul><h3 id="16-3-运行时找不到-so"><a href="#16-3-运行时找不到-so" class="headerlink" title="16.3 运行时找不到 .so"></a>16.3 运行时找不到 <code>.so</code></h3><p>先查看：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ldd /path/to/app</span><br><span class="line">readelf -d /path/to/app</span><br></pre></td></tr></table></figure><p>为部署配置 RUNPATH，或将库安装到受管理的系统路径。不要复制单个 OpenCV 库后忽略其第三方依赖。</p><h3 id="16-4-imread-返回空"><a href="#16-4-imread-返回空" class="headerlink" title="16.4 imread() 返回空"></a>16.4 <code>imread()</code> 返回空</h3><p>检查：</p><ul><li>路径与当前工作目录；文件读取权限；</li><li>文件是否完整；对应 codec 是否在 Summary 中启用；</li><li>输入是否超出资源限制；<code>cv::haveImageReader()</code> 是否识别该文件。<br>内存输入使用 <code>imdecode()</code>，并验证字节缓冲区完整。</li></ul><h3 id="16-5-VideoCapture-打不开"><a href="#16-5-VideoCapture-打不开" class="headerlink" title="16.5 VideoCapture 打不开"></a>16.5 <code>VideoCapture</code> 打不开</h3><p>检查：</p><ul><li><code>WITH_FFMPEG</code> &#x2F; <code>WITH_GSTREAMER</code> 的最终探测；摄像头设备权限；</li><li>容器设备映射；backend preference；</li><li>URL、认证、网络与超时；codec 和像素格式。<br>用 <code>OPENCV_LOG_LEVEL=DEBUG</code> 查看后端尝试。</li></ul><h3 id="16-6-imshow-在服务器失败"><a href="#16-6-imshow-在服务器失败" class="headerlink" title="16.6 imshow() 在服务器失败"></a>16.6 <code>imshow()</code> 在服务器失败</h3><p>无桌面环境通常没有可用显示后端或 display server。改为 <code>imwrite()</code>、Web 输出或无头测试。不要为了 <code>imshow()</code> 给生产容器引入整套 GUI，除非确有需求。</p><h3 id="16-7-Python-导入了错误版本"><a href="#16-7-Python-导入了错误版本" class="headerlink" title="16.7 Python 导入了错误版本"></a>16.7 Python 导入了错误版本</h3><p>打印：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> cv2, sys</span><br><span class="line"><span class="built_in">print</span>(sys.executable); <span class="built_in">print</span>(cv2.__file__); <span class="built_in">print</span>(cv2.getBuildInformation())</span><br></pre></td></tr></table></figure><p>清理冲突的 pip、系统包或 <code>PYTHONPATH</code>。重新配置时确认 Summary 指向目标虚拟环境。</p><h3 id="16-8-打开-CUDA-但算法仍在-CPU"><a href="#16-8-打开-CUDA-但算法仍在-CPU" class="headerlink" title="16.8 打开 CUDA 但算法仍在 CPU"></a>16.8 打开 CUDA 但算法仍在 CPU</h3><p><code>WITH_CUDA=ON</code> 不会让普通 <code>cv::Mat</code> 算法自动迁移到 GPU。CUDA 模块通常使用专用 <code>cv::cuda</code> API，并可能来自 contrib。DNN 还需要选择 CUDA backend&#x2F;target，并满足对应构建依赖。</p><h3 id="16-9-Release-仍然很慢"><a href="#16-9-Release-仍然很慢" class="headerlink" title="16.9 Release 仍然很慢"></a>16.9 Release 仍然很慢</h3><p>按顺序确认：</p><ol><li>实际加载的是 Release 库；</li><li>输入没有重复复制和转换；</li><li>CPU dispatch 与并行后端存在；</li><li>线程没有过度订阅；</li><li>GPU&#x2F;OpenCL 计时包含同步；</li><li>DNN 已预热且未回退；</li><li>热点确实位于 OpenCV 调用内部。</li></ol><h3 id="16-10-CMake-选项显示-ON，但功能不可用"><a href="#16-10-CMake-选项显示-ON，但功能不可用" class="headerlink" title="16.10 CMake 选项显示 ON，但功能不可用"></a>16.10 CMake 选项显示 ON，但功能不可用</h3><p>选项表达请求，不表达探测成功。检查 Summary、<code>CMakeCache.txt</code>、<code>getBuildInformation()</code> 和日志。依赖版本、头、库、目标架构或工具链任一不匹配都可能使能力不可用。</p><h2 id="17-发布前验收清单"><a href="#17-发布前验收清单" class="headerlink" title="17. 发布前验收清单"></a>17. 发布前验收清单</h2><ul><li>使用干净构建目录完成配置；保存完整 CMake 命令和 Summary；</li><li>构建类型是预期的 Release 或 RelWithDebInfo；安装到独立前缀；</li><li>消费工程只使用该前缀；C++ 最小程序可编译和运行；</li><li>Python 时确认 <code>cv2.__file__</code>；图片、视频和 DNN 各跑一个真实样本；</li><li>执行目标模块 tests；在目标设备运行 perf 或业务基准；</li><li>检查共享库和插件依赖；核对模型、codec、contrib 和 nonfree 许可；</li><li>对不可信输入设置尺寸、时间和内存限制；记录 ABI、编译器和第三方版本；</li><li>保留回滚所需的旧安装前缀和构建清单。<br>完成这些步骤后，构建结果才不仅是“编译通过”，而是可定位、可复现、可部署和可维护的 OpenCV 4.13.0 工程。</li></ul>]]>
    </content>
    <id>http://example.com/n/1205/</id>
    <link href="http://example.com/n/1205/"/>
    <published>2026-09-16T03:05:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="OpenCV-4-13-0-配置、构建与使用指南"><a href="#OpenCV-4-13-0-配置、构建与使用指南" class="headerlink" title="OpenCV 4.13.0 配置、构建与使用指南"></a>OpenCV 4.13.0]]>
    </summary>
    <title>OpenCV 4.13.0 配置、构建与使用指南</title>
    <updated>2026-09-16T03:49:31.697Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="06-配置与使用"><a href="#06-配置与使用" class="headerlink" title="06 配置与使用"></a>06 配置与使用</h1><h2 id="6-1-安装"><a href="#6-1-安装" class="headerlink" title="6.1 安装"></a>6.1 安装</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /home/cp/work2/visualAlgo/YOLO/yolov5-7.0</span><br><span class="line">python3 -m venv .venv</span><br><span class="line"><span class="built_in">source</span> .venv/bin/activate</span><br><span class="line">pip install -r requirements.txt</span><br></pre></td></tr></table></figure><p>PyTorch 是否带 CUDA，应按本机驱动从 PyTorch 官方安装对应版本。仅执行 <code>requirements.txt</code> 不保证获得正确的 CUDA wheel。</p><p>验证环境：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python - &lt;&lt;<span class="string">&#x27;PY&#x27;</span></span><br><span class="line">import torch, cv2</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;torch:&quot;</span>, torch.__version__)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;cuda:&quot;</span>, torch.cuda.is_available())</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;opencv:&quot;</span>, cv2.__version__)</span><br><span class="line">PY</span><br></pre></td></tr></table></figure><h2 id="6-2-权重"><a href="#6-2-权重" class="headerlink" title="6.2 权重"></a>6.2 权重</h2><p>源码目录不等于权重包。常用权重：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">yolov5n.pt  最小最快</span><br><span class="line">yolov5s.pt  常用入门</span><br><span class="line">yolov5m.pt</span><br><span class="line">yolov5l.pt</span><br><span class="line">yolov5x.pt  最大</span><br></pre></td></tr></table></figure><p>传入不存在的官方权重名时，<code>attempt_download()</code> 会尝试下载。离线机器应提前复制 <code>.pt</code>。</p><p>也可执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash data/scripts/download_weights.sh</span><br></pre></td></tr></table></figure><h2 id="6-3-快速检测"><a href="#6-3-快速检测" class="headerlink" title="6.3 快速检测"></a>6.3 快速检测</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python detect.py \</span><br><span class="line">  --weights yolov5s.pt \</span><br><span class="line">  --<span class="built_in">source</span> data/images \</span><br><span class="line">  --img 640 \</span><br><span class="line">  --conf-thres 0.25 \</span><br><span class="line">  --iou-thres 0.45</span><br></pre></td></tr></table></figure><p>结果默认写入：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">runs/detect/exp/</span><br></pre></td></tr></table></figure><p>常见 source：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">--<span class="built_in">source</span> image.jpg</span><br><span class="line">--<span class="built_in">source</span> images/</span><br><span class="line">--<span class="built_in">source</span> video.mp4</span><br><span class="line">--<span class="built_in">source</span> 0</span><br><span class="line">--<span class="built_in">source</span> rtsp://...</span><br><span class="line">--<span class="built_in">source</span> screen</span><br></pre></td></tr></table></figure><p>常见选项：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">--save-txt           <span class="comment"># 保存 class xywh</span></span><br><span class="line">--save-conf          <span class="comment"># TXT 追加置信度</span></span><br><span class="line">--save-crop          <span class="comment"># 保存目标裁剪</span></span><br><span class="line">--classes 0 2        <span class="comment"># 只保留指定类别</span></span><br><span class="line">--agnostic-nms       <span class="comment"># 类别无关 NMS</span></span><br><span class="line">--half               <span class="comment"># 支持的 GPU/后端上 FP16</span></span><br><span class="line">--vid-stride 2       <span class="comment"># 视频隔帧</span></span><br></pre></td></tr></table></figure><h2 id="6-4-自定义数据集"><a href="#6-4-自定义数据集" class="headerlink" title="6.4 自定义数据集"></a>6.4 自定义数据集</h2><p>目录：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">datasets/mydata/</span><br><span class="line">├── images/</span><br><span class="line">│   ├── train/</span><br><span class="line">│   └── val/</span><br><span class="line">└── labels/</span><br><span class="line">    ├── train/</span><br><span class="line">    └── val/</span><br></pre></td></tr></table></figure><p><code>data/mydata.yaml</code>：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">path:</span> <span class="string">../datasets/mydata</span></span><br><span class="line"><span class="attr">train:</span> <span class="string">images/train</span></span><br><span class="line"><span class="attr">val:</span> <span class="string">images/val</span></span><br><span class="line"><span class="attr">names:</span></span><br><span class="line">  <span class="attr">0:</span> <span class="string">cat</span></span><br><span class="line">  <span class="attr">1:</span> <span class="string">dog</span></span><br></pre></td></tr></table></figure><p>标签：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">0 0.512 0.480 0.200 0.350</span><br></pre></td></tr></table></figure><p>含义为 <code>class cx cy w h</code>，坐标归一化。类别必须从 0 连续编号，且小于 <code>nc</code>。</p><h2 id="6-5-训练"><a href="#6-5-训练" class="headerlink" title="6.5 训练"></a>6.5 训练</h2><h3 id="迁移学习"><a href="#迁移学习" class="headerlink" title="迁移学习"></a>迁移学习</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">python train.py \</span><br><span class="line">  --weights yolov5s.pt \</span><br><span class="line">  --data data/mydata.yaml \</span><br><span class="line">  --epochs 100 \</span><br><span class="line">  --img 640 \</span><br><span class="line">  --batch-size 16 \</span><br><span class="line">  --device 0</span><br></pre></td></tr></table></figure><h3 id="从零训练"><a href="#从零训练" class="headerlink" title="从零训练"></a>从零训练</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python train.py \</span><br><span class="line">  --weights <span class="string">&#x27;&#x27;</span> \</span><br><span class="line">  --cfg models/yolov5s.yaml \</span><br><span class="line">  --data data/mydata.yaml \</span><br><span class="line">  --hyp data/hyps/hyp.scratch-low.yaml \</span><br><span class="line">  --epochs 300</span><br></pre></td></tr></table></figure><h3 id="自动-Batch"><a href="#自动-Batch" class="headerlink" title="自动 Batch"></a>自动 Batch</h3><p>单 GPU 可使用：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">--batch-size -1</span><br></pre></td></tr></table></figure><h3 id="冻结-Backbone"><a href="#冻结-Backbone" class="headerlink" title="冻结 Backbone"></a>冻结 Backbone</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">--freeze 10</span><br></pre></td></tr></table></figure><p>表示冻结模型前 10 层，适合小数据集初期迁移。</p><h2 id="6-6-恢复训练"><a href="#6-6-恢复训练" class="headerlink" title="6.6 恢复训练"></a>6.6 恢复训练</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python train.py --resume runs/train/exp/weights/last.pt</span><br></pre></td></tr></table></figure><p>恢复需要 <code>last.pt</code> 中仍包含：</p><ul><li>epoch</li><li>optimizer</li><li>EMA</li><li>opt&#x2F;hyp</li></ul><p>训练结束时 <code>strip_optimizer()</code> 会移除优化器状态并转 FP16；被 strip 的部署权重不适合完整恢复。</p><h2 id="6-7-多-GPU-DDP"><a href="#6-7-多-GPU-DDP" class="headerlink" title="6.7 多 GPU DDP"></a>6.7 多 GPU DDP</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python -m torch.distributed.run \</span><br><span class="line">  --nproc_per_node 4 \</span><br><span class="line">  train.py \</span><br><span class="line">  --batch-size 64 \</span><br><span class="line">  --device 0,1,2,3 \</span><br><span class="line">  --data data/mydata.yaml</span><br></pre></td></tr></table></figure><p>源码明确不推荐传统 DataParallel。DDP 的 <code>batch-size</code> 是总 batch，会按 <code>WORLD_SIZE</code> 分给各 GPU。</p><h2 id="6-8-验证"><a href="#6-8-验证" class="headerlink" title="6.8 验证"></a>6.8 验证</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python val.py \</span><br><span class="line">  --weights runs/train/exp/weights/best.pt \</span><br><span class="line">  --data data/mydata.yaml \</span><br><span class="line">  --img 640 \</span><br><span class="line">  --conf-thres 0.001 \</span><br><span class="line">  --iou-thres 0.6</span><br></pre></td></tr></table></figure><p>主要输出：</p><ul><li>Precision</li><li>Recall</li><li><a href="mailto:&#109;&#x41;&#x50;&#x40;&#48;&#x2e;&#53;">mAP@0.5</a></li><li><a href="mailto:&#x6d;&#65;&#x50;&#64;&#48;&#x2e;&#53;">mAP@0.5</a>:0.95</li><li>各类别 AP</li><li>混淆矩阵和 PR 曲线（未关闭 plots 时）</li></ul><p>验证时低 <code>conf-thres</code> 是为了保留完整 PR 曲线，不等同于部署阈值。</p><h2 id="6-9-分割"><a href="#6-9-分割" class="headerlink" title="6.9 分割"></a>6.9 分割</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">python segment/train.py \</span><br><span class="line">  --model yolov5s-seg.pt \</span><br><span class="line">  --data data/coco128-seg.yaml \</span><br><span class="line">  --epochs 5 \</span><br><span class="line">  --img 640</span><br><span class="line"></span><br><span class="line">python segment/val.py \</span><br><span class="line">  --weights yolov5s-seg.pt \</span><br><span class="line">  --data data/coco128-seg.yaml</span><br><span class="line"></span><br><span class="line">python segment/predict.py \</span><br><span class="line">  --weights yolov5s-seg.pt \</span><br><span class="line">  --<span class="built_in">source</span> data/images</span><br></pre></td></tr></table></figure><h2 id="6-10-分类"><a href="#6-10-分类" class="headerlink" title="6.10 分类"></a>6.10 分类</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">python classify/train.py \</span><br><span class="line">  --model yolov5s-cls.pt \</span><br><span class="line">  --data cifar100 \</span><br><span class="line">  --epochs 5 \</span><br><span class="line">  --img 224</span><br><span class="line"></span><br><span class="line">python classify/val.py \</span><br><span class="line">  --weights yolov5s-cls.pt \</span><br><span class="line">  --data ../datasets/imagenet</span><br><span class="line"></span><br><span class="line">python classify/predict.py \</span><br><span class="line">  --weights yolov5s-cls.pt \</span><br><span class="line">  --<span class="built_in">source</span> data/images</span><br></pre></td></tr></table></figure><h2 id="6-11-PyTorch-Hub"><a href="#6-11-PyTorch-Hub" class="headerlink" title="6.11 PyTorch Hub"></a>6.11 PyTorch Hub</h2><p>本地源码（以下直接传图片的写法适用于检测模型；v7.0 的分类&#x2F;分割模型不会自动套用 <code>AutoShape</code>）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">model = torch.hub.load(</span><br><span class="line">    <span class="string">&quot;/home/cp/work2/visualAlgo/YOLO/yolov5-7.0&quot;</span>,</span><br><span class="line">    <span class="string">&quot;custom&quot;</span>,</span><br><span class="line">    path=<span class="string">&quot;best.pt&quot;</span>,</span><br><span class="line">    source=<span class="string">&quot;local&quot;</span>,</span><br><span class="line">)</span><br><span class="line">results = model(<span class="string">&quot;image.jpg&quot;</span>)</span><br><span class="line">results.<span class="built_in">print</span>()</span><br><span class="line">results.save()</span><br></pre></td></tr></table></figure><p>若输入是 OpenCV 数组，AutoShape 注释期望 RGB：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">rgb = cv2.imread(<span class="string">&quot;image.jpg&quot;</span>)[:, :, ::-<span class="number">1</span>]</span><br><span class="line">results = model(rgb)</span><br></pre></td></tr></table></figure><p>仓库中的 <code>sample_detect.py</code> 是该模式的最小示例。</p><h2 id="6-12-导出"><a href="#6-12-导出" class="headerlink" title="6.12 导出"></a>6.12 导出</h2><h3 id="ONNX"><a href="#ONNX" class="headerlink" title="ONNX"></a>ONNX</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python export.py \</span><br><span class="line">  --weights best.pt \</span><br><span class="line">  --include onnx \</span><br><span class="line">  --img 640 \</span><br><span class="line">  --opset 12 \</span><br><span class="line">  --simplify</span><br></pre></td></tr></table></figure><h3 id="TensorRT"><a href="#TensorRT" class="headerlink" title="TensorRT"></a>TensorRT</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">python export.py \</span><br><span class="line">  --weights best.pt \</span><br><span class="line">  --include engine \</span><br><span class="line">  --device 0 \</span><br><span class="line">  --half</span><br></pre></td></tr></table></figure><h3 id="OpenVINO"><a href="#OpenVINO" class="headerlink" title="OpenVINO"></a>OpenVINO</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python export.py --weights best.pt --include openvino</span><br></pre></td></tr></table></figure><p>其他 <code>--include</code> 格式见：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python export.py --<span class="built_in">help</span></span><br></pre></td></tr></table></figure><h2 id="6-13-ONNX-OpenCV-DNN"><a href="#6-13-ONNX-OpenCV-DNN" class="headerlink" title="6.13 ONNX + OpenCV DNN"></a>6.13 ONNX + OpenCV DNN</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">python detect.py \</span><br><span class="line">  --weights best.onnx \</span><br><span class="line">  --<span class="built_in">source</span> image.jpg \</span><br><span class="line">  --dnn</span><br></pre></td></tr></table></figure><p>这会让 <code>DetectMultiBackend</code> 调用 <code>cv2.dnn.readNetFromONNX()</code>，而不是 ONNX Runtime。</p><h2 id="6-14-常见问题"><a href="#6-14-常见问题" class="headerlink" title="6.14 常见问题"></a>6.14 常见问题</h2><h3 id="yolov5s-pt-不存在"><a href="#yolov5s-pt-不存在" class="headerlink" title="yolov5s.pt 不存在"></a><code>yolov5s.pt</code> 不存在</h3><p>源码没有内置权重。联网时自动下载；离线时手动放到当前目录或传绝对路径。</p><h3 id="CUDA-不可用"><a href="#CUDA-不可用" class="headerlink" title="CUDA 不可用"></a>CUDA 不可用</h3><p>检查：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.cuda.is_available()</span><br></pre></td></tr></table></figure><p>若为 False，通常是安装了 CPU 版 PyTorch、驱动不匹配或容器没挂 GPU。</p><h3 id="标签越界"><a href="#标签越界" class="headerlink" title="标签越界"></a>标签越界</h3><p>日志出现：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Label class X exceeds nc=N</span><br></pre></td></tr></table></figure><p>说明标签类别 ID 大于数据集 YAML 中类别数，或类别不是从 0 开始。</p><h3 id="OOM"><a href="#OOM" class="headerlink" title="OOM"></a>OOM</h3><p>依次尝试：</p><ul><li>减小 <code>--batch-size</code></li><li>减小 <code>--img</code></li><li>使用 <code>--batch-size -1</code></li><li>使用更小模型</li><li>关闭 cache 或改 disk</li></ul><h3 id="框映射不准"><a href="#框映射不准" class="headerlink" title="框映射不准"></a>框映射不准</h3><p>不要直接把网络输入坐标画到原图；必须用 <code>scale_boxes()</code> 消除 Letterbox 的缩放和 padding。</p><h3 id="RK3588-NPU"><a href="#RK3588-NPU" class="headerlink" title="RK3588 NPU"></a>RK3588 NPU</h3><p><code>.pt</code> 默认只能走 PyTorch CPU&#x2F;GPU。RK3588 NPU 通常要：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.pt → ONNX → RKNN → RKNN Runtime</span><br></pre></td></tr></table></figure><p><code>--device</code> 不能让 PyTorch <code>.pt</code> 自动运行在 RK NPU。</p>]]>
    </content>
    <id>http://example.com/n/1225/</id>
    <link href="http://example.com/n/1225/"/>
    <published>2026-09-16T03:05:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="06-配置与使用"><a href="#06-配置与使用" class="headerlink" title="06 配置与使用"></a>06 配置与使用</h1><h2 id="6-1-安装"><a href="#6-1-安装" class="headerli]]>
    </summary>
    <title>YOLOv5 7.0：配置与使用</title>
    <updated>2026-09-16T03:49:31.707Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="OpenCV-4-13-0-HAL-与性能优化"><a href="#OpenCV-4-13-0-HAL-与性能优化" class="headerlink" title="OpenCV 4.13.0 HAL 与性能优化"></a>OpenCV 4.13.0 HAL 与性能优化</h1><p>本文面向需要解释、选择或扩展 OpenCV 加速路径的开发者。内容依据 OpenCV 4.13.0 源码树中的 HAL、CPU 分发、并行、OpenCL 和 DNN 实现核验。文中的路径均相对于 OpenCV 源码根目录。</p><h2 id="1-先建立正确的性能模型"><a href="#1-先建立正确的性能模型" class="headerlink" title="1. 先建立正确的性能模型"></a>1. 先建立正确的性能模型</h2><p>一次公开 API 调用可能依次经过：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">公开 API</span><br><span class="line">  -&gt; 参数检查与输出分配</span><br><span class="line">  -&gt; OpenCL / 专用后端尝试</span><br><span class="line">  -&gt; HAL 替换原语</span><br><span class="line">  -&gt; CPU dispatch 或通用实现</span><br><span class="line">  -&gt; parallel_for_ 分块</span><br><span class="line">  -&gt; SIMD、标量与尾部处理</span><br></pre></td></tr></table></figure><p>这不是所有函数都严格遵循的固定层级。不同模块会按算法、数据类型、尺寸和构建能力选择其中一部分。因此，“启用了某个库”不等于“每次调用都进入该库”。性能判断必须同时核对构建结果、运行时选择和实际输入。<br>HAL、SIMD、线程和异构设备解决的问题不同：</p><ul><li>HAL 替换一组约定好的底层原语；</li><li>CPU dispatch 在同一二进制中选择不同指令集版本；</li><li>通用 intrinsics 帮助源码以统一方式表达 SIMD；</li><li><code>parallel_for_</code> 把独立区间分给多个 CPU 线程；</li><li>T-API 通过 <code>UMat</code> 尝试 OpenCL；</li><li>DNN 后端把网络或网络片段交给专用执行引擎。</li></ul><h2 id="2-HAL-的两层含义"><a href="#2-HAL-的两层含义" class="headerlink" title="2. HAL 的两层含义"></a>2. HAL 的两层含义</h2><p>OpenCV 源码中的 HAL 至少有两层含义，阅读时不能混为一谈。</p><h3 id="2-1-模块内的硬件抽象接口"><a href="#2-1-模块内的硬件抽象接口" class="headerlink" title="2.1 模块内的硬件抽象接口"></a>2.1 模块内的硬件抽象接口</h3><p>主要入口包括：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">modules/core/include/opencv2/core/hal/interface.h</span><br><span class="line">modules/core/include/opencv2/core/hal/hal.hpp</span><br><span class="line">modules/core/include/opencv2/core/hal/intrin.hpp</span><br><span class="line">modules/core/include/opencv2/core/hal/intrin_*.hpp</span><br><span class="line">modules/imgproc/include/opencv2/imgproc/hal/hal.hpp</span><br><span class="line">modules/features2d/include/opencv2/features2d/hal/</span><br></pre></td></tr></table></figure><p><code>interface.h</code> 定义低层 C 风格接口、类型和返回码。接口返回值的三个基本约定是：</p><ul><li><code>CV_HAL_ERROR_OK</code>：实现已完成操作；</li><li><code>CV_HAL_ERROR_NOT_IMPLEMENTED</code>：该输入或操作不支持，应由上层回退；</li><li><code>CV_HAL_ERROR_UNKNOWN</code>：实现发生无法恢复的错误。<br>各模块的 <code>src/hal_replacement.hpp</code> 提供默认替换入口。自定义头通过宏重新绑定 <code>cv_hal_*</code> 名称。例如实现头可先 <code>#undef cv_hal_xxx</code>，再将它定义为供应商函数。这是一种编译期替换机制，不是运行时插件虚函数表。<br><code>intrin.hpp</code> 及架构专用头属于另一类抽象。它们把向量寄存器、加载、存储、算术和归约包装成统一 API。算法可由同一份模板生成 baseline 或多个 dispatch 版本。intrinsics 不是外置 HAL，但两者可以在同一调用链中同时存在。</li></ul><h3 id="2-2-源码根目录中的-HAL-子工程"><a href="#2-2-源码根目录中的-HAL-子工程" class="headerlink" title="2.2 源码根目录中的 HAL 子工程"></a>2.2 源码根目录中的 HAL 子工程</h3><p>源码根目录 <code>hal/</code> 保存树内可选实现：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">hal/carotene/</span><br><span class="line">hal/fastcv/</span><br><span class="line">hal/kleidicv/</span><br><span class="line">hal/ndsrvp/</span><br><span class="line">hal/riscv-rvv/</span><br><span class="line">hal/ipp/</span><br><span class="line">hal/openvx/</span><br></pre></td></tr></table></figure><p>这些目录各自构建静态辅助库或接入外部项目。根 <code>CMakeLists.txt</code> 决定其顺序、头文件注入和链接库收集。目录存在并不表示当前平台一定构建或使用它。</p><h2 id="3-HAL-注册链与优先级"><a href="#3-HAL-注册链与优先级" class="headerlink" title="3. HAL 注册链与优先级"></a>3. HAL 注册链与优先级</h2><h3 id="3-1-CMake-阶段的完整链路"><a href="#3-1-CMake-阶段的完整链路" class="headerlink" title="3.1 CMake 阶段的完整链路"></a>3.1 CMake 阶段的完整链路</h3><p>根构建脚本中的关键流程是：</p><ol><li>平台与依赖探测生成 <code>HAVE_*</code>；</li><li>用户选项和探测结果修改 <code>OpenCV_HAL</code> 列表；</li><li><code>foreach(hal ${OpenCV_HAL})</code> 按列表顺序处理实现；</li><li>树内实现通过 <code>add_subdirectory(hal/...)</code> 构建；</li><li>未识别名称通过 <code>find_package(&lt;name&gt; NO_MODULE QUIET)</code> 查找；</li><li><code>ocv_hal_register()</code> 收集库、头和 include 目录；</li><li><code>custom_hal.hpp.in</code> 被配置成构建目录中的 <code>custom_hal.hpp</code>；</li><li>收集到的库进入 OpenCV 模块链接关系。<br><code>ocv_hal_register()</code> 实际做三件事：</li></ol><ul><li>将实现库追加到 <code>OPENCV_HAL_LINKER_LIBS</code>；</li><li>将实现头变成生成头中的 <code>#include</code>；</li><li>将实现 include 目录加入构建。<br>根脚本默认把 <code>OpenCV_HAL</code> 设为字符串 <code>OpenCV_HAL</code>。这个名称会走 <code>find_package(OpenCV_HAL NO_MODULE QUIET)</code>。因此 <code>OpenCV_HAL_DIR</code> 可指向一个含 <code>OpenCV_HALConfig.cmake</code> 的外置实现构建目录。</li></ul><h3 id="3-2-顺序为什么重要"><a href="#3-2-顺序为什么重要" class="headerlink" title="3.2 顺序为什么重要"></a>3.2 顺序为什么重要</h3><p>IPP、OpenVX、FastCV、KleidiCV、Carotene、NDSRVP 和 RVV 会按条件前插到列表。每个注册头都可能重定义同一个 <code>cv_hal_*</code> 宏。生成的 <code>custom_hal.hpp</code> 按注册顺序包含这些头。后包含且确实重定义某接口的头，可能覆盖先前绑定。没有覆盖的接口继续由前一实现或默认实现提供。<br>不要仅根据“某库排在列表中”推断最终处理者。应检查生成的 <code>custom_hal.hpp</code>、具体实现头和目标链接命令。</p><h3 id="3-3-从公开-API-到回退"><a href="#3-3-从公开-API-到回退" class="headerlink" title="3.3 从公开 API 到回退"></a>3.3 从公开 API 到回退</h3><p>典型路径可以概括为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cv::算法</span><br><span class="line">  -&gt; cv_hal_xxx(...)</span><br><span class="line">     -&gt; 返回 OK：结束</span><br><span class="line">     -&gt; 返回 NOT_IMPLEMENTED：执行 OpenCV 内部实现</span><br><span class="line">     -&gt; 返回 UNKNOWN：按调用点的错误策略处理</span><br></pre></td></tr></table></figure><p>是否允许回退由具体调用点决定。实现必须遵守接口的步长、尺寸、原地操作、边界和数值约定。“不支持此组合”应返回 <code>NOT_IMPLEMENTED</code>，不能悄悄产生近似错误结果。</p><h2 id="4-编写和接入自定义-HAL"><a href="#4-编写和接入自定义-HAL" class="headerlink" title="4. 编写和接入自定义 HAL"></a>4. 编写和接入自定义 HAL</h2><p>源码自带两个教学实现：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">samples/hal/c_hal/</span><br><span class="line">samples/hal/slow_hal/</span><br></pre></td></tr></table></figure><p><code>c_hal</code> 的函数返回错误，用于验证错误处理和回退。<code>slow_hal</code> 替换按位运算，用可观察的慢实现证明绑定已生效。两者都会生成 <code>OpenCV_HALConfig.cmake</code>。</p><h3 id="4-1-最小接入流程"><a href="#4-1-最小接入流程" class="headerlink" title="4.1 最小接入流程"></a>4.1 最小接入流程</h3><p>先单独构建自定义 HAL：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cmake -S /path/to/opencv/samples/hal/slow_hal \</span><br><span class="line">  -B /path/to/build-hal \</span><br><span class="line">  -D CMAKE_BUILD_TYPE=Release</span><br><span class="line">cmake --build /path/to/build-hal -j</span><br></pre></td></tr></table></figure><p>再配置 OpenCV：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cmake -S /path/to/opencv \</span><br><span class="line">  -B /path/to/build-opencv \</span><br><span class="line">  -D CMAKE_BUILD_TYPE=Release \</span><br><span class="line">  -D OpenCV_HAL_DIR=/path/to/build-hal</span><br><span class="line">cmake --build /path/to/build-opencv -j</span><br></pre></td></tr></table></figure><p>外置包至少需要导出：</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">set</span>(OpenCV_HAL_FOUND <span class="keyword">TRUE</span>)</span><br><span class="line"><span class="keyword">set</span>(OpenCV_HAL_VERSION <span class="number">0.1</span>.<span class="number">0</span>)</span><br><span class="line"><span class="keyword">set</span>(OpenCV_HAL_LIBRARIES /path/to/libcustom_hal.a)</span><br><span class="line"><span class="keyword">set</span>(OpenCV_HAL_HEADERS custom_hal_impl.hpp)</span><br><span class="line"><span class="keyword">set</span>(OpenCV_HAL_INCLUDE_DIRS /path/to/<span class="keyword">include</span>)</span><br></pre></td></tr></table></figure><p>生产实现应使用可重定位的导出目标或安装路径。上面的绝对占位仅说明变量语义。</p><h3 id="4-2-实现检查清单"><a href="#4-2-实现检查清单" class="headerlink" title="4.2 实现检查清单"></a>4.2 实现检查清单</h3><ul><li>函数签名必须与当前 4.13.0 接口完全一致；</li><li>只重定义真正实现的接口；</li><li>对不支持的深度、通道或边界模式返回 <code>NOT_IMPLEMENTED</code>；</li><li>正确处理非连续矩阵和字节步长；</li><li>明确是否支持源、目的区域重叠；</li><li>避免越过每行有效宽度；</li><li>保证多线程并发调用安全；</li><li>不把进程级可变状态放进无保护全局变量；</li><li>静态库用于共享 OpenCV 时通常需要位置无关代码；</li><li>用正确性测试覆盖空尺寸、奇数尺寸和尾部元素；</li><li>用性能测试证明收益大于分派与转换成本；</li><li>将支持矩阵、版本和供应商运行库要求写入发布说明。</li></ul><h3 id="4-3-如何确认自定义-HAL-生效"><a href="#4-3-如何确认自定义-HAL-生效" class="headerlink" title="4.3 如何确认自定义 HAL 生效"></a>4.3 如何确认自定义 HAL 生效</h3><p>检查以下证据链：</p><ol><li>CMake 配置日志找到了自定义包；</li><li>生成的 <code>custom_hal.hpp</code> 包含自定义头；</li><li>目标链接命令含自定义 HAL 库；</li><li>针对被替换接口的测试通过；</li><li>通过日志、计数器或调试器确认函数被调用；</li><li>关闭自定义 HAL 后基准结果按预期变化。<br>不要只靠符号出现在静态库中判断生效。链接器可能丢弃未引用对象，宏绑定也可能已被后续头覆盖。</li></ol><h2 id="5-树内-HAL-实现"><a href="#5-树内-HAL-实现" class="headerlink" title="5. 树内 HAL 实现"></a>5. 树内 HAL 实现</h2><h3 id="5-1-Carotene"><a href="#5-1-Carotene" class="headerlink" title="5.1 Carotene"></a>5.1 Carotene</h3><p>选项是 <code>WITH_CAROTENE</code>。根 CMake 仅在 ARM&#x2F;AArch64 的适用平台显示该选项。真正注册前还要求 <code>CPU_BASELINE_FINAL</code> 包含 <code>NEON</code>。接线头是 <code>hal/carotene/hal/tegra_hal.hpp</code>。<br>Carotene 覆盖多种 core 与 imgproc 原语。其对象库会按 <code>WITH_NEON</code> 添加定义，并包含针对内联增长的编译参数。适合已有 NEON baseline 的 ARM 构建。它不是所有 ARM 算法的统一开关，也不等价于 CPU dispatch 中的 NEON。</p><h3 id="5-2-Qualcomm-FastCV"><a href="#5-2-Qualcomm-FastCV" class="headerlink" title="5.2 Qualcomm FastCV"></a>5.2 Qualcomm FastCV</h3><p>选项是 <code>WITH_FASTCV</code>，默认关闭。可见平台为 ARM&#x2F;AArch64 上的 Android 或适用 Unix。依赖探测成功后形成 <code>HAVE_FASTCV</code>。实现位于 <code>hal/fastcv/src/</code>，注册头覆盖 core 和 imgproc 的部分接口。<br><code>hal/fastcv/CMakeLists.txt</code> 将外部 <code>FASTCV_LIBRARY</code> 链接到 <code>fastcv_hal</code>。选项打开但库或头未找到时，HAL 不可用。发布时必须同时考虑 FastCV 二进制、许可、目标 ABI 和运行时装载路径。</p><h3 id="5-3-Arm-KleidiCV"><a href="#5-3-Arm-KleidiCV" class="headerlink" title="5.3 Arm KleidiCV"></a>5.3 Arm KleidiCV</h3><p>选项是 <code>WITH_KLEIDICV</code>。源码将其限制到 AArch64 的 Android 或 Unix 环境。依赖可用时，OpenCV包含 KleidiCV 自带的 <code>adapters/opencv/CMakeLists.txt</code>。适配器负责生成 <code>kleidicv_hal</code> 和对应注册信息。<br>构建中还提供 <code>KLEIDICV_ENABLE_SME2</code>，默认关闭。源码注释指出它与部分 Android NDK Clang 版本不兼容。启用 SME2 前要同时验证编译器、运行设备和部署基线。</p><h3 id="5-4-Andes-NDSRVP"><a href="#5-4-Andes-NDSRVP" class="headerlink" title="5.4 Andes NDSRVP"></a>5.4 Andes NDSRVP</h3><p>选项是 <code>WITH_NDSRVP</code>，仅在 RISC-V 平台可见。注册还要求 C 与 C++ flags 都包含 <code>-mext-dsp</code>。同时要求 baseline 不含 <code>RVV</code>。这体现了 NDSRVP 与 RVV HAL 的选择关系。<br>实现覆盖部分 core、imgproc 和 features2d 接口。构建生成 <code>ndsrvp_hal</code> 静态库。应使用 Andes 对应工具链验证编译选项，不能在普通 RISC-V 工具链上只强开选项。</p><h3 id="5-5-RISC-V-RVV-HAL"><a href="#5-5-RISC-V-RVV-HAL" class="headerlink" title="5.5 RISC-V RVV HAL"></a>5.5 RISC-V RVV HAL</h3><p>选项是 <code>WITH_HAL_RVV</code>，仅在 RISC-V 平台可见。注册要求 <code>CPU_BASELINE_FINAL</code> 含 <code>RVV</code>。构建目标为 <code>rvv_hal</code>。入口头 <code>rvv_hal.hpp</code> 汇集 core、imgproc 和 features2d 替换。<br>源码覆盖矩阵分解、数学、颜色转换、滤波、几何变换、直方图和 FAST 等多类原语。具体接口仍可能因数据类型或参数而回退。RVV HAL 与通用 intrinsics 中的 RVV dispatch 是不同机制。</p><h3 id="5-6-Intel-IPP"><a href="#5-6-Intel-IPP" class="headerlink" title="5.6 Intel IPP"></a>5.6 Intel IPP</h3><p>选项是 <code>WITH_IPP</code>。根 CMake 在 x86&#x2F;x86_64 且适用平台提供该选项，并以 <code>HAVE_IPP</code> 验证探测结果。注册目标 <code>ipphal</code> 覆盖 mean、min&#x2F;max、norm、极坐标转换、变换、warp 和 sum 等接口。<br>OpenCV 其他位置仍保留 IPP 集成。<code>hal/ipp/CMakeLists.txt</code> 的注释明确指出 HAL 尚未成为唯一 IPP 来源。因此分析 IPP 命中时要同时看 HAL 和模块内部 IPP 路径。<code>WITH_IPP_CALLS_ENFORCED</code> 更适合验证和开发，不应在不了解回退影响时用于通用发布。</p><h3 id="5-7-OpenVX"><a href="#5-7-OpenVX" class="headerlink" title="5.7 OpenVX"></a>5.7 OpenVX</h3><p>选项是 <code>WITH_OPENVX</code>，默认关闭。<code>cmake/FindOpenVX.cmake</code> 探测实现并形成 <code>HAVE_OPENVX</code>。只有探测成功才进入 <code>hal/openvx/hal/</code>。源码还包含 <code>ivx.hpp</code> 等 C++ 包装。<br>OpenVX HAL 只覆盖它实现的原语。性能受图构建、数据导入导出、供应商实现和目标设备影响。不能把 <code>WITH_OPENVX=ON</code> 理解为整个 OpenCV 流水线自动转换为 OpenVX 图。</p><h3 id="5-8-选择摘要"><a href="#5-8-选择摘要" class="headerlink" title="5.8 选择摘要"></a>5.8 选择摘要</h3><table><thead><tr><th>平台或依赖</th><th>首先评估</th><th>关键验证</th></tr></thead><tbody><tr><td>x86&#x2F;x86_64</td><td>CPU dispatch、IPP</td><td><code>HAVE_IPP</code>、实际命中、线程数</td></tr><tr><td>通用 ARM&#x2F;AArch64</td><td>NEON、Carotene、KleidiCV</td><td>baseline、编译器、覆盖接口</td></tr><tr><td>Qualcomm ARM</td><td>FastCV</td><td>外部库、许可、ABI、回退</td></tr><tr><td>Andes RISC-V DSP</td><td>NDSRVP</td><td><code>-mext-dsp</code> 且 baseline 非 RVV</td></tr><tr><td>RISC-V Vector</td><td>RVV HAL</td><td><code>CPU_BASELINE_FINAL</code> 含 RVV</td></tr><tr><td>OpenVX 设备</td><td>OpenVX HAL</td><td>实现版本、传输和图开销</td></tr></tbody></table><h2 id="6-CPU-baseline-与-runtime-dispatch"><a href="#6-CPU-baseline-与-runtime-dispatch" class="headerlink" title="6. CPU baseline 与 runtime dispatch"></a>6. CPU baseline 与 runtime dispatch</h2><h3 id="6-1-两类构建结果"><a href="#6-1-两类构建结果" class="headerlink" title="6.1 两类构建结果"></a>6.1 两类构建结果</h3><p><code>CPU_BASELINE</code> 指定库运行所需的最低优化能力。baseline 指令可以出现在通用代码路径中。把 AVX2 设为 baseline 意味着不支持 AVX2 的机器不应运行该二进制。<br><code>CPU_DISPATCH</code> 指定额外编译的优化版本。运行时检测 CPU 后选择可用的最高合适版本。不满足这些额外能力的机器仍可走 baseline。<br>高级约束还有：</p><ul><li><code>CPU_BASELINE_REQUIRE</code>：必须成功启用的 baseline；</li><li><code>CPU_BASELINE_DISABLE</code>：禁止的 baseline；</li><li><code>CPU_DISPATCH_REQUIRE</code>：必须成功生成的 dispatch。<br>最终结果记录在：</li><li><code>CPU_BASELINE_FINAL</code>；</li><li><code>CPU_DISPATCH_FINAL</code>；</li><li>CMake Summary 的 CPU&#x2F;HW features 段。</li></ul><h3 id="6-2-源码组织"><a href="#6-2-源码组织" class="headerlink" title="6.2 源码组织"></a>6.2 源码组织</h3><p>热点实现常使用：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">name.dispatch.cpp</span><br><span class="line">name.simd.hpp</span><br><span class="line">name.avx2.cpp</span><br></pre></td></tr></table></figure><p><code>CV_CPU_DISPATCH</code> 宏按运行时能力调用命名空间中的版本。dispatch 链最终落到 <code>BASELINE</code>。不是每个算法、深度和尺寸都有每种指令集实现。</p><h3 id="6-3-构建与运行时控制"><a href="#6-3-构建与运行时控制" class="headerlink" title="6.3 构建与运行时控制"></a>6.3 构建与运行时控制</h3><p>构建时 <code>CV_DISABLE_OPTIMIZATION=ON</code> 会关闭多类优化，适合建立调试对照。运行时 <code>cv::setUseOptimized(false)</code> 关闭受该全局标志控制的优化分支。它必须在没有其他 OpenCV 调用并发执行的顶层安全位置调用。<br>环境变量 <code>OPENCV_CPU_DISABLE</code> 可禁用以逗号或分号分隔的 dispatch 特性。它适合定位某个指令集实现，不适合作为长期性能配置的替代品。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OPENCV_CPU_DISABLE=AVX2,AVX512-SKX /path/to/app</span><br></pre></td></tr></table></figure><p><code>cv::getCPUFeaturesLine()</code> 的标记含义为：</p><ul><li>无标记：baseline；</li><li>前缀 <code>*</code>：dispatch 中编译的特性；</li><li>后缀 <code>?</code>：已编译但当前硬件不可用。</li></ul><h2 id="7-parallel-for-与线程后端"><a href="#7-parallel-for-与线程后端" class="headerlink" title="7. parallel_for_ 与线程后端"></a>7. <code>parallel_for_</code> 与线程后端</h2><p><code>cv::parallel_for_</code> 接受一个 <code>Range</code> 和并行循环体。它把区间划分为多个 stripe，再交给并行后端。构建可能使用 TBB、OpenMP、平台后端、插件或内置实现。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Body</span> <span class="keyword">final</span> : <span class="keyword">public</span> cv::ParallelLoopBody &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Body</span>(<span class="type">const</span> cv::Mat&amp; src, cv::Mat&amp; dst) : <span class="built_in">src_</span>(src), <span class="built_in">dst_</span>(dst) &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="type">const</span> cv::Range&amp; range)</span> <span class="type">const</span> <span class="keyword">override</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> y = range.start; y &lt; range.end; ++y)</span><br><span class="line">            src_.<span class="built_in">row</span>(y).<span class="built_in">copyTo</span>(dst_.<span class="built_in">row</span>(y));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">const</span> cv::Mat&amp; src_;</span><br><span class="line">    cv::Mat&amp; dst_;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">cv::<span class="built_in">parallel_for_</span>(cv::<span class="built_in">Range</span>(<span class="number">0</span>, src.rows), <span class="built_in">Body</span>(src, dst));</span><br></pre></td></tr></table></figure><p>循环体应满足：</p><ul><li>每个 stripe 写入互不重叠的输出；</li><li>只读共享输入；</li><li>共享统计量使用归约或同步；</li><li>不依赖 stripe 的执行顺序；</li><li>粒度足够大，能覆盖调度开销；</li><li>异常和对象生命周期符合调用线程语义。<br>常用控制 API：</li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cv::<span class="built_in">setNumThreads</span>(<span class="number">1</span>);</span><br><span class="line"><span class="type">int</span> configured = cv::<span class="built_in">getNumThreads</span>();</span><br><span class="line"><span class="type">int</span> cpus = cv::<span class="built_in">getNumberOfCPUs</span>();</span><br></pre></td></tr></table></figure><p><code>setNumThreads(1)</code> 可用于串行对照。传负数恢复系统默认。该函数不是线程安全的，不能在并行区或并发调用中修改。<code>getNumThreads()</code> 的精确语义取决于 TBB、OpenMP 等后端。<br>上层线程池与 OpenCV 内部线程并行叠加会过度订阅。批量处理时常见策略是“外层并行、库内单线程”或反之。应分别测量，不能凭核心数直接决定。</p><h2 id="8-OpenCL-Transparent-API"><a href="#8-OpenCL-Transparent-API" class="headerlink" title="8. OpenCL Transparent API"></a>8. OpenCL Transparent API</h2><p>T-API 使用 <code>cv::UMat</code> 表达可由 OpenCL 管理的数据。支持 OpenCL 的函数会尝试设备实现，不支持时可走 CPU 路径。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cv::UMat src, gray, blurred;</span><br><span class="line">cv::<span class="built_in">imread</span>(<span class="string">&quot;input.jpg&quot;</span>, cv::IMREAD_COLOR).<span class="built_in">copyTo</span>(src);</span><br><span class="line">cv::<span class="built_in">cvtColor</span>(src, gray, cv::COLOR_BGR2GRAY);</span><br><span class="line">cv::<span class="built_in">GaussianBlur</span>(gray, blurred, cv::<span class="built_in">Size</span>(<span class="number">5</span>, <span class="number">5</span>), <span class="number">1.2</span>);</span><br><span class="line">cv::ocl::<span class="built_in">finish</span>();</span><br></pre></td></tr></table></figure><p>诊断 API：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">std::cout &lt;&lt; cv::ocl::<span class="built_in">haveOpenCL</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">std::cout &lt;&lt; cv::ocl::<span class="built_in">useOpenCL</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">cv::ocl::<span class="built_in">setUseOpenCL</span>(<span class="literal">true</span>);</span><br><span class="line"><span class="type">const</span> cv::ocl::Device&amp; dev = cv::ocl::Device::<span class="built_in">getDefault</span>();</span><br><span class="line">std::cout &lt;&lt; dev.<span class="built_in">name</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br></pre></td></tr></table></figure><p>环境变量 <code>OPENCV_OPENCL_DEVICE</code> 可选择设备或设为 <code>disabled</code>。设备选择应在 OpenCL 上下文首次初始化前完成。<br>性能陷阱包括：</p><ul><li>小算子启动成本高于计算收益；</li><li><code>Mat</code> 与 <code>UMat</code> 频繁互转造成上传和下载；</li><li><code>getMat()</code> 可能触发同步；</li><li>只计异步提交而没有 <code>cv::ocl::finish()</code> 会低估时间；</li><li>某一步回退到 CPU 可能打断整条设备流水线；</li><li>首次编译 kernel 与缓存建立不代表稳定态。<br>最佳实践是让尽可能长的支持链保持 <code>UMat</code>。端到端基准必须包含必要的输入传输、最终同步和输出取回。</li></ul><h2 id="9-DNN-后端与目标"><a href="#9-DNN-后端与目标" class="headerlink" title="9. DNN 后端与目标"></a>9. DNN 后端与目标</h2><p>OpenCV 4.13.0 的公开枚举包含：</p><ul><li>后端：Default、Halide、OpenVINO、OpenCV、VkCom、CUDA、WebNN、TIM-VX、CANN；</li><li>目标：CPU、OpenCL、OpenCL FP16、Myriad、Vulkan、FPGA、CUDA、CUDA FP16、HDDL、NPU、ARM CPU FP16。<br>枚举存在不代表当前构建可用。应查询实际组合：</li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span>&amp; item : cv::dnn::<span class="built_in">getAvailableBackends</span>())</span><br><span class="line">    std::cout &lt;&lt; item.first &lt;&lt; <span class="string">&quot; -&gt; &quot;</span> &lt;&lt; item.second &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">auto</span> targets = cv::dnn::<span class="built_in">getAvailableTargets</span>(cv::dnn::DNN_BACKEND_OPENCV);</span><br></pre></td></tr></table></figure><p>显式选择示例：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cv::dnn::Net net = cv::dnn::<span class="built_in">readNet</span>(<span class="string">&quot;/path/to/model.onnx&quot;</span>);</span><br><span class="line">net.<span class="built_in">setPreferableBackend</span>(cv::dnn::DNN_BACKEND_OPENCV);</span><br><span class="line">net.<span class="built_in">setPreferableTarget</span>(cv::dnn::DNN_TARGET_CPU);</span><br></pre></td></tr></table></figure><p>CUDA 后端通常要求构建探测到 CUDA，并按能力使用 cuDNN、cuBLAS 等。OpenVINO、TIM-VX、CANN 等也各有构建和运行时依赖。不支持的层可能回退、重新分区或直接报错，取决于后端。<br>DNN 性能测量应分离：</p><ul><li>模型读取与解析；</li><li>首次网络初始化；</li><li>首次推理和 kernel 编译；</li><li>稳定态推理；</li><li>blob 预处理；</li><li>输出复制与后处理。<br><code>Net::getPerfProfile()</code> 可返回层级时间，但支持范围与后端有关。最终仍要以应用端到端延迟和吞吐为准。</li></ul><h2 id="10-内存、数据布局与缓存"><a href="#10-内存、数据布局与缓存" class="headerlink" title="10. 内存、数据布局与缓存"></a>10. 内存、数据布局与缓存</h2><p>许多“计算优化”最终受内存带宽限制。优先检查：</p><ul><li>是否在循环中反复创建同尺寸输出；</li><li>是否存在无意的 <code>clone()</code>、<code>copyTo()</code> 或类型转换；</li><li>ROI 是否导致非连续步长；</li><li>通道转换能否前移、合并或取消；</li><li>数据类型是否超出精度需求；</li><li>大图处理是否有更好的 tile；</li><li>多线程是否争用同一缓存行；</li><li>NUMA 机器上的分配与执行是否跨节点。<br><code>cv::Mat</code> 是引用计数的浅拷贝头。赋值通常不复制像素，<code>clone()</code> 才执行深拷贝。ROI 可能不连续，底层代码必须尊重 <code>step</code>。可用 <code>isContinuous()</code> 判断能否把多行合并为一个线性区间。<br>OpenCV 提供 <code>fastMalloc()</code> 与 <code>fastFree()</code>。需要特殊分配策略时可研究 <code>MatAllocator</code>，但这是高级扩展点。自定义 allocator 必须处理生命周期、对齐、map&#x2F;unmap 和异常路径。一般应用先复用 <code>Mat::create()</code> 管理的缓冲区即可。<br>减少峰值内存的常用方法：</li><li>原地操作仅在 API 明确支持时使用；</li><li>将中间缓冲区放到循环外复用；</li><li>流式读取视频，不缓存全部帧；</li><li>控制 DNN batch 与输入分辨率；</li><li>对超大图采用分块并处理 halo；</li><li>避免同时保留 <code>Mat</code>、<code>UMat</code> 和设备副本。</li></ul><h2 id="11-可复现-benchmark-方法"><a href="#11-可复现-benchmark-方法" class="headerlink" title="11. 可复现 benchmark 方法"></a>11. 可复现 benchmark 方法</h2><h3 id="11-1-基准骨架"><a href="#11-1-基准骨架" class="headerlink" title="11.1 基准骨架"></a>11.1 基准骨架</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">cv::TickMeter tm;</span><br><span class="line">cv::Mat dst;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; ++i)</span><br><span class="line">    cv::<span class="built_in">GaussianBlur</span>(src, dst, cv::<span class="built_in">Size</span>(<span class="number">5</span>, <span class="number">5</span>), <span class="number">1.2</span>);</span><br><span class="line"></span><br><span class="line">std::vector&lt;<span class="type">double</span>&gt; samples;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; ++i) &#123;</span><br><span class="line">    tm.<span class="built_in">reset</span>();</span><br><span class="line">    tm.<span class="built_in">start</span>();</span><br><span class="line">    cv::<span class="built_in">GaussianBlur</span>(src, dst, cv::<span class="built_in">Size</span>(<span class="number">5</span>, <span class="number">5</span>), <span class="number">1.2</span>);</span><br><span class="line">    tm.<span class="built_in">stop</span>();</span><br><span class="line">    samples.<span class="built_in">push_back</span>(tm.<span class="built_in">getTimeMilli</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>GPU 或 OpenCL 路径要在计时区间末尾同步。异步设备后端也要使用其对应同步机制。不要使用 <code>getCPUTickCount()</code> 直接换算耗时；源码文档建议一般计时使用 <code>getTickCount()</code>。</p><h3 id="11-2-必须固定和记录"><a href="#11-2-必须固定和记录" class="headerlink" title="11.2 必须固定和记录"></a>11.2 必须固定和记录</h3><ul><li>OpenCV 完整版本与源码修订；</li><li>Release、Debug 或 RelWithDebInfo；</li><li>编译器、标准库和关键编译参数；</li><li>baseline、dispatch 与 HAL 列表；</li><li>第三方加速库和驱动版本；</li><li>CPU 型号、频率策略、NUMA 与亲和性；</li><li>GPU&#x2F;NPU 型号、功耗模式与温度；</li><li>输入尺寸、类型、通道、步长和内容分布；</li><li>线程数、并行后端和上层并发；</li><li>预热次数、样本数和同步位置；</li><li>中位数、分位数与离群值规则；</li><li>优化前后的输出误差阈值；</li><li>是否包含 I&#x2F;O、传输、预处理和后处理。</li></ul><h3 id="11-3-OpenCV-自带-perf"><a href="#11-3-OpenCV-自带-perf" class="headerlink" title="11.3 OpenCV 自带 perf"></a>11.3 OpenCV 自带 perf</h3><p>启用 <code>BUILD_PERF_TESTS=ON</code> 后可构建 <code>opencv_perf_&lt;module&gt;</code>。使用 GoogleTest 风格过滤器缩小测试范围：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/path/to/build/bin/opencv_perf_core \</span><br><span class="line">  --gtest_filter=<span class="string">&#x27;*bitwise_and*&#x27;</span></span><br></pre></td></tr></table></figure><p>先运行 <code>--help</code> 查看当前二进制支持的 perf 参数。不同构建和版本的参数集合可能变化。不要把单个微基准直接外推为完整业务收益。</p><h2 id="12-诊断-API-与环境变量"><a href="#12-诊断-API-与环境变量" class="headerlink" title="12. 诊断 API 与环境变量"></a>12. 诊断 API 与环境变量</h2><p>最小诊断程序：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;opencv2/core.hpp&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;opencv2/core/ocl.hpp&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;opencv2/core/utils/logger.hpp&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cv::utils::logging::<span class="built_in">setLogLevel</span>(</span><br><span class="line">        cv::utils::logging::LOG_LEVEL_INFO);</span><br><span class="line">    std::cout &lt;&lt; cv::<span class="built_in">getVersionString</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    std::cout &lt;&lt; cv::<span class="built_in">getBuildInformation</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    std::cout &lt;&lt; cv::<span class="built_in">getCPUFeaturesLine</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;optimized=&quot;</span> &lt;&lt; cv::<span class="built_in">useOptimized</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;threads=&quot;</span> &lt;&lt; cv::<span class="built_in">getNumThreads</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;cpus=&quot;</span> &lt;&lt; cv::<span class="built_in">getNumberOfCPUs</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;opencl=&quot;</span> &lt;&lt; cv::ocl::<span class="built_in">haveOpenCL</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>常用环境变量：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">OPENCV_LOG_LEVEL=DEBUG /path/to/app</span><br><span class="line">OPENCV_CPU_DISABLE=AVX2 /path/to/app</span><br><span class="line">OPENCV_FOR_THREADS_NUM=1 /path/to/app</span><br><span class="line">OPENCV_OPENCL_DEVICE=disabled /path/to/app</span><br></pre></td></tr></table></figure><p>诊断顺序建议：</p><ol><li>打印 <code>getBuildInformation()</code>；</li><li>核对目标模块和第三方依赖确实为 YES；</li><li>打印 CPU features 和线程数；</li><li>开启日志观察后端选择；</li><li>逐个关闭线程、dispatch、OpenCL 或专用后端；</li><li>保持相同输入比较结果和时间；</li><li>用调试器或 profiler 获取最终证据。</li></ol><h2 id="13-平台决策树"><a href="#13-平台决策树" class="headerlink" title="13. 平台决策树"></a>13. 平台决策树</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">先确认热点是否在 OpenCV 内</span><br><span class="line">  |</span><br><span class="line">  +-- 否 -&gt; 优化 I/O、业务逻辑或数据搬运</span><br><span class="line">  |</span><br><span class="line">  +-- 是</span><br><span class="line">      |</span><br><span class="line">      +-- x86/x86_64</span><br><span class="line">      |   -&gt; Release + 合理 baseline/dispatch</span><br><span class="line">      |   -&gt; 检查 IPP、线程和内存带宽</span><br><span class="line">      |</span><br><span class="line">      +-- ARM/AArch64</span><br><span class="line">      |   -&gt; 检查 NEON baseline/dispatch</span><br><span class="line">      |   -&gt; 评估 Carotene / KleidiCV</span><br><span class="line">      |   -&gt; Qualcomm 设备再评估 FastCV</span><br><span class="line">      |</span><br><span class="line">      +-- RISC-V</span><br><span class="line">      |   -&gt; RVV baseline 可用：评估 RVV HAL</span><br><span class="line">      |   -&gt; Andes DSP 工具链：评估 NDSRVP</span><br><span class="line">      |</span><br><span class="line">      +-- 有 OpenCL</span><br><span class="line">      |   -&gt; 流水线可长期保留 UMat：测 T-API</span><br><span class="line">      |   -&gt; 频繁传输或小算子：优先 CPU</span><br><span class="line">      |</span><br><span class="line">      +-- DNN</span><br><span class="line">          -&gt; 查询可用 backend/target</span><br><span class="line">          -&gt; 按模型覆盖率、精度、延迟选择</span><br></pre></td></tr></table></figure><h2 id="14-优化实施顺序"><a href="#14-优化实施顺序" class="headerlink" title="14. 优化实施顺序"></a>14. 优化实施顺序</h2><ol><li>建立正确性基线和误差标准；</li><li>用 profiler 找到真实热点；</li><li>先减少输入量、重复计算和数据搬运；</li><li>确保使用 Release 构建；</li><li>核验已有 SIMD、HAL、IPP 和线程路径；</li><li>调整线程层级和任务粒度；</li><li>评估保持设备驻留的 OpenCL 或 DNN 后端；</li><li>仅对稳定且高占比的底层原语开发自定义 HAL；</li><li>用同一套正确性与性能测试验收；</li><li>在目标设备和热稳态条件下重新测量。<br>最终选择应以目标平台的可重复端到端数据为依据。任何加速路径都必须保留可诊断的回退方案，并验证回退结果正确。</li></ol>]]>
    </content>
    <id>http://example.com/n/1204/</id>
    <link href="http://example.com/n/1204/"/>
    <published>2026-09-16T03:04:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="OpenCV-4-13-0-HAL-与性能优化"><a href="#OpenCV-4-13-0-HAL-与性能优化" class="headerlink" title="OpenCV 4.13.0 HAL 与性能优化"></a>OpenCV 4.13.0 HAL]]>
    </summary>
    <title>OpenCV 4.13.0 HAL 与性能优化</title>
    <updated>2026-09-16T03:49:31.696Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="05-模型损失与数据"><a href="#05-模型损失与数据" class="headerlink" title="05 模型损失与数据"></a>05 模型损失与数据</h1><h2 id="5-1-YOLOv5s-YAML"><a href="#5-1-YOLOv5s-YAML" class="headerlink" title="5.1 YOLOv5s YAML"></a>5.1 YOLOv5s YAML</h2><p><code>models/yolov5s.yaml</code> 的关键配置：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">nc:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">depth_multiple:</span> <span class="number">0.33</span></span><br><span class="line"><span class="attr">width_multiple:</span> <span class="number">0.50</span></span><br><span class="line"><span class="attr">anchors:</span></span><br><span class="line">  <span class="bullet">-</span> [<span class="number">10</span>,<span class="number">13</span>, <span class="number">16</span>,<span class="number">30</span>, <span class="number">33</span>,<span class="number">23</span>]       <span class="comment"># P3/8</span></span><br><span class="line">  <span class="bullet">-</span> [<span class="number">30</span>,<span class="number">61</span>, <span class="number">62</span>,<span class="number">45</span>, <span class="number">59</span>,<span class="number">119</span>]      <span class="comment"># P4/16</span></span><br><span class="line">  <span class="bullet">-</span> [<span class="number">116</span>,<span class="number">90</span>, <span class="number">156</span>,<span class="number">198</span>, <span class="number">373</span>,<span class="number">326</span>]  <span class="comment"># P5/32</span></span><br></pre></td></tr></table></figure><p>模型主干：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Conv(stride=2)</span><br><span class="line">  → Conv+C3</span><br><span class="line">  → P3/8</span><br><span class="line">  → P4/16</span><br><span class="line">  → P5/32</span><br><span class="line">  → SPPF</span><br></pre></td></tr></table></figure><p>Neck 使用上采样与 <code>Concat</code> 构成 FPN&#x2F;PAN，最后把第 17、20、23 层送入 <code>Detect</code>。</p><h2 id="5-2-深度和宽度缩放"><a href="#5-2-深度和宽度缩放" class="headerlink" title="5.2 深度和宽度缩放"></a>5.2 深度和宽度缩放</h2><p><code>parse_model()</code> 的规则：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">实际重复数 = max(round(number × depth_multiple), 1)</span><br><span class="line">实际通道数 = make_divisible(channels × width_multiple, 8)</span><br></pre></td></tr></table></figure><p>因此 n&#x2F;s&#x2F;m&#x2F;l&#x2F;x 可以复用相同类型的拓扑定义，只改变容量。</p><p>输出层通道数不能按普通 width multiple 缩放，因为其维度固定为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">na × (nc + 5)</span><br></pre></td></tr></table></figure><h2 id="5-3-C3-与-SPPF"><a href="#5-3-C3-与-SPPF" class="headerlink" title="5.3 C3 与 SPPF"></a>5.3 C3 与 SPPF</h2><h3 id="C3"><a href="#C3" class="headerlink" title="C3"></a>C3</h3><p>C3 是 CSP 风格模块：</p><ul><li>一支经过若干 Bottleneck</li><li>一支较短旁路</li><li>两支 Concat 后再卷积</li></ul><p>它在控制计算量的同时保留梯度路径，是 YOLOv5 backbone&#x2F;neck 的主体。</p><h3 id="SPPF"><a href="#SPPF" class="headerlink" title="SPPF"></a>SPPF</h3><p>SPPF 用同一个 5×5 MaxPool 串行执行三次，得到等效 5&#x2F;9&#x2F;13 感受野，再拼接。相对传统并行 SPP，结构更简单、速度更快。</p><h2 id="5-4-检测头输出"><a href="#5-4-检测头输出" class="headerlink" title="5.4 检测头输出"></a>5.4 检测头输出</h2><p>P5 模型有三层输出，每层三个 Anchor。训练输出：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">B × 3 × H × W × (nc+5)</span><br></pre></td></tr></table></figure><p>其中：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">0:2  → xy</span><br><span class="line">2:4  → wh</span><br><span class="line">4    → objectness</span><br><span class="line">5:   → class logits</span><br></pre></td></tr></table></figure><p>640 输入、80 类时，三层形状近似：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[B, 3, 80, 80, 85]</span><br><span class="line">[B, 3, 40, 40, 85]</span><br><span class="line">[B, 3, 20, 20, 85]</span><br></pre></td></tr></table></figure><p>候选总数：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">3 × (80² + 40² + 20²) = 25200</span><br></pre></td></tr></table></figure><h2 id="5-5-推理解码"><a href="#5-5-推理解码" class="headerlink" title="5.5 推理解码"></a>5.5 推理解码</h2><p><code>Detect.forward()</code> 对每层：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xy = (sigmoid(xy) * <span class="number">2</span> + grid) * stride</span><br><span class="line">wh = (sigmoid(wh) * <span class="number">2</span>) ** <span class="number">2</span> * anchor_grid</span><br><span class="line">conf = sigmoid(conf)</span><br></pre></td></tr></table></figure><p><code>grid</code> 带 <code>-0.5</code> 偏移，因此中心可预测到相邻网格附近。宽高公式将范围扩大到约 0～4 倍 Anchor。</p><p>解码结果是中心点格式 xywh；NMS 前再转换成 xyxy。</p><h2 id="5-6-Anchor-匹配与目标构建"><a href="#5-6-Anchor-匹配与目标构建" class="headerlink" title="5.6 Anchor 匹配与目标构建"></a>5.6 Anchor 匹配与目标构建</h2><p>入口：<code>utils/loss.py::ComputeLoss.build_targets()</code></p><p>输入目标每行：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[image_index, class, x, y, w, h]</span><br></pre></td></tr></table></figure><p>坐标是相对图片归一化的 xywh。</p><p>目标构建步骤：</p><ol><li>每个目标复制到每个 Anchor</li><li>按当前检测层网格尺寸缩放坐标</li><li>比较目标宽高与 Anchor 宽高比例</li><li>最大正反比例小于 <code>anchor_t</code> 才匹配</li><li>位于网格边缘的目标额外分配到上&#x2F;下&#x2F;左&#x2F;右邻格</li><li>输出类别、回归框、索引和匹配 Anchor</li></ol><p>这种一对多分配提高了正样本数量。</p><h2 id="5-7-检测损失"><a href="#5-7-检测损失" class="headerlink" title="5.7 检测损失"></a>5.7 检测损失</h2><h3 id="Box-Loss"><a href="#Box-Loss" class="headerlink" title="Box Loss"></a>Box Loss</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lbox = mean(1 - CIoU(pred_box, target_box))</span><br></pre></td></tr></table></figure><p>CIoU 同时考虑：</p><ul><li>重叠面积</li><li>中心点距离</li><li>宽高比一致性</li></ul><h3 id="Objectness-Loss"><a href="#Objectness-Loss" class="headerlink" title="Objectness Loss"></a>Objectness Loss</h3><p>每个网格&#x2F;Anchor 都有 Objectness BCE。正样本目标值不是固定 1，而是与匹配框的 IoU 相关：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tobj[b, a, gj, gi] = detached IoU</span><br></pre></td></tr></table></figure><p>P3&#x2F;P4&#x2F;P5 默认 balance 为 <code>[4.0, 1.0, 0.4]</code>，用于平衡不同尺度网格数量。</p><h3 id="Classification-Loss"><a href="#Classification-Loss" class="headerlink" title="Classification Loss"></a>Classification Loss</h3><p>多类别时对类别 logits 使用 <code>BCEWithLogitsLoss</code>。可启用：</p><ul><li><code>label_smoothing</code></li><li><code>fl_gamma &gt; 0</code> 的 Focal Loss</li></ul><h3 id="总损失"><a href="#总损失" class="headerlink" title="总损失"></a>总损失</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">loss = batch_size × (</span><br><span class="line">    box_gain × lbox +</span><br><span class="line">    obj_gain × lobj +</span><br><span class="line">    cls_gain × lcls</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p><code>train.py</code> 还会按检测层数、类别数和图像尺寸调整三项 gain。</p><h2 id="5-8-数据集格式"><a href="#5-8-数据集格式" class="headerlink" title="5.8 数据集格式"></a>5.8 数据集格式</h2><p>数据集 YAML 示例：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">path:</span> <span class="string">../datasets/mydata</span></span><br><span class="line"><span class="attr">train:</span> <span class="string">images/train</span></span><br><span class="line"><span class="attr">val:</span> <span class="string">images/val</span></span><br><span class="line"><span class="attr">test:</span></span><br><span class="line"><span class="attr">names:</span></span><br><span class="line">  <span class="attr">0:</span> <span class="string">person</span></span><br><span class="line">  <span class="attr">1:</span> <span class="string">car</span></span><br></pre></td></tr></table></figure><p>检测标签为每张图片对应的 <code>.txt</code>：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">class x_center y_center width height</span><br></pre></td></tr></table></figure><p>四个坐标均归一化到 0～1。目录通常为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">mydata/</span><br><span class="line">├── images/train</span><br><span class="line">├── images/val</span><br><span class="line">├── labels/train</span><br><span class="line">└── labels/val</span><br></pre></td></tr></table></figure><p><code>img2label_paths()</code> 按 <code>images</code> → <code>labels</code>、扩展名 → <code>.txt</code> 自动映射。</p><h2 id="5-9-数据加载与缓存"><a href="#5-9-数据加载与缓存" class="headerlink" title="5.9 数据加载与缓存"></a>5.9 数据加载与缓存</h2><p><code>LoadImagesAndLabels</code>：</p><ul><li>扫描目录或图片清单</li><li>校验图像和标签</li><li>把标签、尺寸、分割多边形写入 <code>.cache</code></li><li>用文件 hash 和 cache version 判断缓存是否失效</li><li>可把图片缓存到 RAM 或 <code>.npy</code></li><li>矩形训练时按宽高比排序，降低 padding</li></ul><h2 id="5-10-数据增强"><a href="#5-10-数据增强" class="headerlink" title="5.10 数据增强"></a>5.10 数据增强</h2><p>增强分为两条互斥主路径：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">  I[&quot;读取图像&quot;] --&gt; CH&#123;&quot;本次使用 Mosaic?&quot;&#125;</span><br><span class="line">  CH --&gt;|是| M[&quot;load_mosaic: 4图拼接&quot;]</span><br><span class="line">  M --&gt; CP[&quot;Copy-Paste + 随机透视&quot;]</span><br><span class="line">  CP --&gt; MX[&quot;可选 MixUp（再加载一组 Mosaic）&quot;]</span><br><span class="line">  CH --&gt;|否| LB[&quot;Letterbox&quot;]</span><br><span class="line">  LB --&gt; RP[&quot;随机透视/旋转/平移/缩放/剪切&quot;]</span><br><span class="line">  MX --&gt; AL[&quot;可选 Albumentations&quot;]</span><br><span class="line">  RP --&gt; AL</span><br><span class="line">  AL --&gt; HSV[&quot;HSV&quot;]</span><br><span class="line">  HSV --&gt; FLIP[&quot;上下/左右翻转&quot;]</span><br><span class="line">  FLIP --&gt; RGB[&quot;BGR→RGB, HWC→CHW&quot;]</span><br></pre></td></tr></table></figure><h3 id="Mosaic"><a href="#Mosaic" class="headerlink" title="Mosaic"></a>Mosaic</h3><p>把当前图片和三张随机图放入 2×2 大画布；<code>load_mosaic()</code> 内部完成 Copy-Paste（启用时）和随机透视。返回 <code>__getitem__()</code> 后还可与另一组 Mosaic 做 MixUp。优点：</p><ul><li>一次看到更多物体</li><li>小目标更丰富</li><li>减少对大 batch 的依赖</li></ul><h3 id="Rectangular-Training"><a href="#Rectangular-Training" class="headerlink" title="Rectangular Training"></a>Rectangular Training</h3><p>按宽高比排序，同一 batch 使用接近的矩形尺寸，可减少灰边，但会禁用 Mosaic。</p><p>DDP 下，标签缓存的首次扫描通过 <code>torch_distributed_zero_first()</code> 让本地 Rank 0 优先完成，其他进程随后复用，避免同时重复构建 <code>.cache</code>。</p><h2 id="5-11-超参数"><a href="#5-11-超参数" class="headerlink" title="5.11 超参数"></a>5.11 超参数</h2><p><code>data/hyps/hyp.scratch-low.yaml</code> 分四组：</p><ul><li>优化：<code>lr0/lrf/momentum/weight_decay/warmup_*</code></li><li>损失：<code>box/cls/obj/*_pw/fl_gamma</code></li><li>匹配：<code>iou_t/anchor_t</code></li><li>增强：<code>hsv_* / degrees / translate / scale / shear / perspective / flip* / mosaic / mixup</code></li></ul><p><code>anchor_t</code> 太小会减少正样本；太大会让不合适的 Anchor 也参与训练。<code>mosaic</code> 和 <code>scale</code> 对小数据集帮助大，但过强会造成训练分布与真实场景不一致。</p><h2 id="5-12-AutoAnchor"><a href="#5-12-AutoAnchor" class="headerlink" title="5.12 AutoAnchor"></a>5.12 AutoAnchor</h2><p>训练前 <code>check_anchors()</code> 比较数据集目标宽高和模型 Anchor。适配度差时会重新聚类&#x2F;进化 Anchor。</p><p>修改输入尺寸或目标尺度分布后，应重新检查 Anchor；加载预训练权重但自定义了模型 Anchor 时，训练代码会避免迁移不兼容的 Anchor 状态。</p>]]>
    </content>
    <id>http://example.com/n/1224/</id>
    <link href="http://example.com/n/1224/"/>
    <published>2026-09-16T03:04:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="05-模型损失与数据"><a href="#05-模型损失与数据" class="headerlink" title="05 模型损失与数据"></a>05 模型损失与数据</h1><h2 id="5-1-YOLOv5s-YAML"><a href="#5-1-Y]]>
    </summary>
    <title>YOLOv5 7.0：模型损失与数据</title>
    <updated>2026-09-16T03:49:31.706Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="04-OpenCV-4-13-0-算法流水线"><a href="#04-OpenCV-4-13-0-算法流水线" class="headerlink" title="04 OpenCV 4.13.0 算法流水线"></a>04 OpenCV 4.13.0 算法流水线</h1><p>本章面向需要把“单个 API 示例”组装成可验证视觉系统的开发者。内容以 OpenCV 4.13.0 的公开 API 和源码头文件为准，统一按“输入 → 处理 → 输出 → 失败诊断 → 参数调整 → 验证”描述。示例默认使用 Python 接口 <code>cv2</code>；C++ 中对应类型通常为 <code>cv::Mat</code>、<code>cv::Point2f</code>、<code>cv::KeyPoint</code> 等。</p><p>本章只讨论算法流水线。模块边界、构建方式、HAL 优化和完整源码目录分别由其他章节负责。</p><h2 id="4-1-流水线设计与输入契约"><a href="#4-1-流水线设计与输入契约" class="headerlink" title="4.1 流水线设计与输入契约"></a>4.1 流水线设计与输入契约</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;采集或解码&quot;] --&gt; B&#123;&quot;输入有效?&quot;&#125;</span><br><span class="line">    B --&gt;|否| X[&quot;记录并拒绝处理&quot;]</span><br><span class="line">    B --&gt;|是| C[&quot;颜色/位深/尺寸归一化&quot;]</span><br><span class="line">    C --&gt; D[&quot;主算法&quot;]</span><br><span class="line">    D --&gt; E[&quot;几何或语义后处理&quot;]</span><br><span class="line">    E --&gt; F[&quot;定量验证&quot;]</span><br><span class="line">    F --&gt; G[&quot;结果与中间产物&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-1-1-类型、范围与坐标"><a href="#4-1-1-类型、范围与坐标" class="headerlink" title="4.1.1 类型、范围与坐标"></a>4.1.1 类型、范围与坐标</h3><table><thead><tr><th>数据</th><th>常见类型</th><th>数值范围</th><th>典型用途</th></tr></thead><tbody><tr><td>彩色图</td><td><code>uint8</code>, <code>H×W×3</code>，BGR</td><td><code>[0,255]</code></td><td>显示、传统视觉</td></tr><tr><td>灰度图</td><td><code>uint8</code>, <code>H×W</code></td><td><code>[0,255]</code></td><td>阈值、边缘、角点</td></tr><tr><td>浮点图</td><td><code>float32</code>, <code>H×W</code> 或 <code>H×W×C</code></td><td>常见 <code>[0,1]</code>，也可无界</td><td>卷积、梯度、DNN</td></tr><tr><td>二值掩膜</td><td><code>uint8</code>, <code>H×W</code></td><td>推荐 <code>{0,255}</code></td><td>形态学、轮廓、逻辑运算</td></tr><tr><td>标签图</td><td><code>int32</code>, <code>H×W</code></td><td><code>0...N</code>，特殊算法可有负值</td><td>连通域、Watershed</td></tr><tr><td>点集</td><td><code>float32/float64</code>, <code>N×2</code> 或 <code>N×1×2</code></td><td>像素坐标</td><td>几何估计</td></tr></tbody></table><p>OpenCV 图像坐标原点在左上角，<code>x</code> 向右、<code>y</code> 向下；数组索引则写作 <code>image[y, x]</code>。裁剪 ROI 后得到的坐标相对 ROI 原点，回写原图必须加偏移。几何估计宜使用浮点坐标，标签和类别掩膜的缩放必须使用 <code>INTER_NEAREST</code>。</p><p>最小输入守卫：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line">image = cv.imread(<span class="string">&quot;input.png&quot;</span>, cv.IMREAD_COLOR)</span><br><span class="line"><span class="keyword">if</span> image <span class="keyword">is</span> <span class="literal">None</span> <span class="keyword">or</span> image.size == <span class="number">0</span>:</span><br><span class="line">    <span class="keyword">raise</span> ValueError(<span class="string">&quot;图像读取失败或为空&quot;</span>)</span><br><span class="line"><span class="keyword">if</span> image.dtype != np.uint8 <span class="keyword">or</span> image.ndim != <span class="number">3</span> <span class="keyword">or</span> image.shape[<span class="number">2</span>] != <span class="number">3</span>:</span><br><span class="line">    <span class="keyword">raise</span> TypeError(<span class="string">f&quot;期望 uint8 BGR，实际为 <span class="subst">&#123;image.dtype&#125;</span>, <span class="subst">&#123;image.shape&#125;</span>&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="4-1-2-可复现验证"><a href="#4-1-2-可复现验证" class="headerlink" title="4.1.2 可复现验证"></a>4.1.2 可复现验证</h3><p>每一级至少记录输入类型、关键参数、有效像素比例、候选数、内点率、误差分位数及耗时。调参时先固定数据、随机种子、尺寸和指标，再确认颜色、位深、范围与坐标映射；从前往后一次只调一层，先提高召回率，最后优化速度。不要只保存最终叠加图，中间掩膜、边缘、内点和重投影结果更能定位失败阶段。</p><h2 id="4-2-图像预处理"><a href="#4-2-图像预处理" class="headerlink" title="4.2 图像预处理"></a>4.2 图像预处理</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;BGR/灰度原图&quot;] --&gt; B[&quot;裁剪 ROI&quot;]</span><br><span class="line">    B --&gt; C[&quot;cvtColor&quot;]</span><br><span class="line">    C --&gt; D[&quot;resize&quot;]</span><br><span class="line">    D --&gt; E[&quot;convertTo/normalize&quot;]</span><br><span class="line">    E --&gt; F[&quot;连续且语义明确的输入&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-2-1-API、参数和输入输出"><a href="#4-2-1-API、参数和输入输出" class="headerlink" title="4.2.1 API、参数和输入输出"></a>4.2.1 API、参数和输入输出</h3><ul><li><code>cv.cvtColor(src, code)</code>：<code>COLOR_BGR2GRAY</code>、<code>COLOR_BGR2HSV</code>、<code>COLOR_BGR2Lab</code> 等；输出通道数由转换码决定。</li><li><code>cv.resize(src, dsize, fx, fy, interpolation)</code>：缩小优先 <code>INTER_AREA</code>，普通放大优先 <code>INTER_LINEAR</code>，离散标签使用 <code>INTER_NEAREST</code>。</li><li><code>cv.normalize(src, dst, alpha, beta, norm_type)</code>：可做 <code>NORM_MINMAX</code> 或范数归一化，不等同于神经网络的均值方差标准化。</li><li><code>cv.copyMakeBorder</code>：补边方式包括 <code>BORDER_CONSTANT</code>、<code>REPLICATE</code>、<code>REFLECT_101</code>。</li><li><code>cv.remap(src, map1, map2, interpolation)</code>：输入映射表常为 <code>CV_32FC1/2</code> 或转换后的定点格式，输出尺寸由映射表决定。</li></ul><p>保持宽高比缩放并补边时，设原尺寸为 <code>(W,H)</code>、目标尺寸为 <code>(W_t,H_t)</code>：</p><p>[<br>s&#x3D;\min(W_t&#x2F;W,\ H_t&#x2F;H),\quad W’&#x3D;sW,\quad H’&#x3D;sH<br>]</p><p>左右和上下总补边分别是 <code>W_t-W&#39;</code>、<code>H_t-H&#39;</code>。后续坐标映射必须执行 <code>x=(x_t-p_x)/s</code>、<code>y=(y_t-p_y)/s</code>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">letterbox</span>(<span class="params">bgr, size=(<span class="params"><span class="number">640</span>, <span class="number">640</span></span>), value=(<span class="params"><span class="number">114</span>, <span class="number">114</span>, <span class="number">114</span></span>)</span>):</span><br><span class="line">    tw, th = size</span><br><span class="line">    h, w = bgr.shape[:<span class="number">2</span>]</span><br><span class="line">    scale = <span class="built_in">min</span>(tw / w, th / h)</span><br><span class="line">    nw, nh = <span class="built_in">round</span>(w * scale), <span class="built_in">round</span>(h * scale)</span><br><span class="line">    resized = cv.resize(bgr, (nw, nh), interpolation=cv.INTER_LINEAR)</span><br><span class="line">    left, top = (tw - nw) // <span class="number">2</span>, (th - nh) // <span class="number">2</span></span><br><span class="line">    right, bottom = tw - nw - left, th - nh - top</span><br><span class="line">    out = cv.copyMakeBorder(resized, top, bottom, left, right,</span><br><span class="line">                            cv.BORDER_CONSTANT, value=value)</span><br><span class="line">    <span class="keyword">return</span> out, scale, (left, top)</span><br></pre></td></tr></table></figure><h3 id="4-2-2-失败、调参和验证"><a href="#4-2-2-失败、调参和验证" class="headerlink" title="4.2.2 失败、调参和验证"></a>4.2.2 失败、调参和验证</h3><ul><li>失败原因：把 RGB 模型输入当 BGR；整数除法导致归一化全零；宽高顺序写反；ROI 越界；重复压缩造成细节丢失。</li><li>调参顺序：先定颜色空间和范围，再定目标尺寸及插值，最后选择补边和归一化。</li><li>验证方法：检查通道均值、直方图、角点坐标回映射误差；对掩膜确认缩放后类别集合没有新增值。</li></ul><h2 id="4-3-滤波、增强与二值化"><a href="#4-3-滤波、增强与二值化" class="headerlink" title="4.3 滤波、增强与二值化"></a>4.3 滤波、增强与二值化</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;灰度或彩色图&quot;] --&gt; B[&quot;噪声模型判断&quot;]</span><br><span class="line">    B --&gt; C[&quot;Gaussian/Median/Bilateral&quot;]</span><br><span class="line">    C --&gt; D[&quot;CLAHE/直方图均衡&quot;]</span><br><span class="line">    D --&gt; E[&quot;固定/Otsu/自适应阈值&quot;]</span><br><span class="line">    E --&gt; F[&quot;uint8 二值掩膜&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-3-1-滤波与增强"><a href="#4-3-1-滤波与增强" class="headerlink" title="4.3.1 滤波与增强"></a>4.3.1 滤波与增强</h3><ul><li><code>GaussianBlur(src, ksize, sigmaX, sigmaY=0)</code>：核尺寸通常为正奇数；适合近似高斯噪声。</li><li><code>medianBlur(src, ksize)</code>：<code>ksize</code> 为大于 1 的奇数；对椒盐噪声稳健。</li><li><code>bilateralFilter(src, d, sigmaColor, sigmaSpace)</code>：同时按空间距离和颜色差加权，保边但较慢。</li><li><code>equalizeHist(src)</code>：只接受 8 位单通道图；彩色图宜仅均衡亮度通道。</li><li><code>createCLAHE(clipLimit, tileGridSize)</code>：限制局部对比度，降低全局均衡放大噪声的风险。</li></ul><p>高斯滤波可写为：</p><p>[<br>G(x,y)&#x3D;\frac{1}{2\pi\sigma^2}\exp\left(-\frac{x^2+y^2}{2\sigma^2}\right),\quad I’&#x3D;G*I<br>]</p><p>双边滤波的权重同时包含空间项与强度项：</p><p>[<br>w(p,q)\propto \exp(-|p-q|^2&#x2F;2\sigma_s^2)\exp(-|I_p-I_q|^2&#x2F;2\sigma_r^2)<br>]</p><h3 id="4-3-2-二值化"><a href="#4-3-2-二值化" class="headerlink" title="4.3.2 二值化"></a>4.3.2 二值化</h3><ul><li><code>threshold(src, thresh, maxval, type)</code>：输入通常为单通道；返回实际阈值和输出图。</li><li><code>THRESH_OTSU</code> 自动寻找类间方差最大的阈值，应与 <code>THRESH_BINARY</code> 或反相模式组合。</li><li><code>adaptiveThreshold</code> 要求 8 位单通道输入；<code>blockSize</code> 必须为大于 1 的奇数，<code>C</code> 从局部均值或高斯加权均值中扣除。</li><li>目标比背景暗时，优先考虑 <code>THRESH_BINARY_INV</code>，避免后续把背景当作前景。</li></ul><p>Otsu 最大化类间方差：</p><p>[<br>\sigma_b^2(t)&#x3D;\omega_0(t)\omega_1(t)\left[\mu_0(t)-\mu_1(t)\right]^2<br>]</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)</span><br><span class="line">gray = cv.GaussianBlur(gray, (<span class="number">5</span>, <span class="number">5</span>), <span class="number">0</span>)</span><br><span class="line">clahe = cv.createCLAHE(clipLimit=<span class="number">2.0</span>, tileGridSize=(<span class="number">8</span>, <span class="number">8</span>))</span><br><span class="line">enhanced = clahe.apply(gray)</span><br><span class="line">otsu_t, mask = cv.threshold(</span><br><span class="line">    enhanced, <span class="number">0</span>, <span class="number">255</span>, cv.THRESH_BINARY + cv.THRESH_OTSU</span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="4-3-3-失败、调参和验证"><a href="#4-3-3-失败、调参和验证" class="headerlink" title="4.3.3 失败、调参和验证"></a>4.3.3 失败、调参和验证</h3><ul><li>失败原因：光照梯度破坏全局阈值双峰假设；核过大吞掉细线；CLAHE 放大纹理和噪声；前景极少时 Otsu 偏向背景。</li><li>调参顺序：先决定灰度&#x2F;亮度通道和前景极性；再按噪声选滤波器；随后调增强；最后调阈值、<code>blockSize</code> 和 <code>C</code>。</li><li>验证方法：画灰度直方图；统计前景比例；在标注集上计算 Precision、Recall、IoU；用不同曝光和噪声级别做扰动测试。</li></ul><h2 id="4-4-形态学处理"><a href="#4-4-形态学处理" class="headerlink" title="4.4 形态学处理"></a>4.4 形态学处理</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;二值图/灰度图&quot;] --&gt; B[&quot;getStructuringElement&quot;]</span><br><span class="line">    B --&gt; C&#123;&quot;缺陷类型&quot;&#125;</span><br><span class="line">    C --&gt;|白点| D[&quot;Opening&quot;]</span><br><span class="line">    C --&gt;|黑洞| E[&quot;Closing&quot;]</span><br><span class="line">    C --&gt;|收缩/分离| F[&quot;Erode&quot;]</span><br><span class="line">    C --&gt;|扩张/连接| G[&quot;Dilate&quot;]</span><br><span class="line">    D --&gt; H[&quot;清理后掩膜&quot;]</span><br><span class="line">    E --&gt; H</span><br><span class="line">    F --&gt; H</span><br><span class="line">    G --&gt; H</span><br></pre></td></tr></table></figure><p>结构元素可由 <code>getStructuringElement(MORPH_RECT/MORPH_ELLIPSE/MORPH_CROSS, ksize)</code> 构造。<code>erode</code>、<code>dilate</code> 和 <code>morphologyEx</code> 接受灰度或多通道图，但语义最清晰的输入通常是 <code>{0,255}</code> 二值图；输出尺寸和类型默认不变。</p><p>集合意义下，腐蚀与膨胀为：</p><p>[<br>A\ominus B&#x3D;{z\mid B_z\subseteq A},\qquad<br>A\oplus B&#x3D;{z\mid (\hat B)_z\cap A\neq\varnothing}<br>]</p><p>开运算是 <code>(A⊖B)⊕B</code>，闭运算是 <code>(A⊕B)⊖B</code>。<code>MORPH_GRADIENT</code> 近似膨胀减腐蚀，<code>MORPH_TOPHAT</code> 提取比结构元素小的亮结构，<code>MORPH_BLACKHAT</code> 提取暗结构。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (<span class="number">5</span>, <span class="number">5</span>))</span><br><span class="line">opened = cv.morphologyEx(mask, cv.MORPH_OPEN, kernel, iterations=<span class="number">1</span>)</span><br><span class="line">clean = cv.morphologyEx(opened, cv.MORPH_CLOSE, kernel, iterations=<span class="number">2</span>)</span><br></pre></td></tr></table></figure><ul><li>失败原因：结构元素大于目标最窄部分；迭代过多合并相邻目标；前景极性颠倒；边界补值引入伪结构。</li><li>调参顺序：先确认白色代表前景，再按缺陷方向选操作，随后选形状，再从小核、单次迭代开始。</li><li>验证方法：比较连通域数量、面积分布、孔洞数和细线保留率；用异或图显示处理前后改变的像素。</li></ul><h2 id="4-5-Canny-与梯度"><a href="#4-5-Canny-与梯度" class="headerlink" title="4.5 Canny 与梯度"></a>4.5 Canny 与梯度</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;uint8 灰度图&quot;] --&gt; B[&quot;平滑&quot;]</span><br><span class="line">    B --&gt; C[&quot;Sobel/Scharr 梯度&quot;]</span><br><span class="line">    C --&gt; D[&quot;幅值与方向&quot;]</span><br><span class="line">    D --&gt; E[&quot;非极大值抑制&quot;]</span><br><span class="line">    E --&gt; F[&quot;双阈值与滞后连接&quot;]</span><br><span class="line">    F --&gt; G[&quot;单像素边缘&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-5-1-梯度-API-与原理"><a href="#4-5-1-梯度-API-与原理" class="headerlink" title="4.5.1 梯度 API 与原理"></a>4.5.1 梯度 API 与原理</h3><p><code>Sobel(src, ddepth, dx, dy, ksize, scale, delta)</code> 输出导数图；对 8 位输入常用 <code>CV_16S</code> 或 <code>CV_32F</code>，不能直接用 <code>CV_8U</code> 保存带符号梯度。<code>Scharr</code> 使用固定高精度 3×3 核，适合小核一阶导。<code>magnitude</code> 和 <code>phase</code> 可由 <code>Gx/Gy</code> 得到幅值与方向。</p><p>[<br>G&#x3D;\sqrt{G_x^2+G_y^2},\qquad \theta&#x3D;\operatorname{atan2}(G_y,G_x)<br>]</p><p><code>Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)</code> 接受 8 位图；低阈值以下丢弃，高阈值以上保留，中间像素仅在连接强边缘时保留。<code>L2gradient=False</code> 使用 <code>|Gx|+|Gy|</code> 近似幅值，设为 <code>True</code> 使用欧氏幅值。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)</span><br><span class="line">blur = cv.GaussianBlur(gray, (<span class="number">5</span>, <span class="number">5</span>), <span class="number">1.2</span>)</span><br><span class="line">gx = cv.Scharr(blur, cv.CV_32F, <span class="number">1</span>, <span class="number">0</span>)</span><br><span class="line">gy = cv.Scharr(blur, cv.CV_32F, <span class="number">0</span>, <span class="number">1</span>)</span><br><span class="line">mag = cv.magnitude(gx, gy)</span><br><span class="line">edges = cv.Canny(blur, <span class="number">50</span>, <span class="number">150</span>, apertureSize=<span class="number">3</span>, L2gradient=<span class="literal">True</span>)</span><br></pre></td></tr></table></figure><h3 id="4-5-2-失败、调参和验证"><a href="#4-5-2-失败、调参和验证" class="headerlink" title="4.5.2 失败、调参和验证"></a>4.5.2 失败、调参和验证</h3><ul><li>失败原因：低阈值太低导致纹理泛滥；高阈值太高造成断边；平滑过强令弱边缘消失；图像动态范围变化使固定阈值失效。</li><li>调参顺序：先控制输入尺度和降噪，再看梯度幅值分布，先调高阈值定位强边，再调低阈值连接，最后考虑形态学闭合。</li><li>验证方法：边缘像素比例、与标注边缘的容差匹配 F1、轮廓闭合率；同时检查 <code>Gx</code>、<code>Gy</code>，避免只看最终 Canny 图。</li></ul><h2 id="4-6-轮廓与形状分析"><a href="#4-6-轮廓与形状分析" class="headerlink" title="4.6 轮廓与形状分析"></a>4.6 轮廓与形状分析</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;单通道二值图&quot;] --&gt; B[&quot;findContours&quot;]</span><br><span class="line">    B --&gt; C[&quot;层级/面积/周长过滤&quot;]</span><br><span class="line">    C --&gt; D[&quot;approxPolyDP/convexHull&quot;]</span><br><span class="line">    D --&gt; E[&quot;矩/外接框/圆/椭圆&quot;]</span><br><span class="line">    E --&gt; F[&quot;形状与几何量&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-6-1-API-和类型"><a href="#4-6-1-API-和类型" class="headerlink" title="4.6.1 API 和类型"></a>4.6.1 API 和类型</h3><ul><li><code>findContours(image, mode, method)</code>：输入为 8 位单通道二值图；<code>RETR_EXTERNAL</code> 仅取外轮廓，<code>RETR_TREE</code> 建立完整嵌套层级。</li><li><code>CHAIN_APPROX_SIMPLE</code> 压缩水平、垂直和斜线共线点；需要全部边界点时用 <code>CHAIN_APPROX_NONE</code>。</li><li><code>contourArea(contour, oriented=False)</code> 返回面积；<code>arcLength(contour, closed)</code> 返回周长。</li><li><code>approxPolyDP(curve, epsilon, closed)</code> 使用 Douglas–Peucker 近似；常设 <code>epsilon=k×周长</code>。</li><li><code>boundingRect</code> 返回轴对齐整数框；<code>minAreaRect</code> 返回旋转矩形；<code>fitEllipse</code> 至少需要 5 个点。</li><li><code>moments</code> 给出空间矩；当 <code>m00 != 0</code> 时质心为 <code>(m10/m00, m01/m00)</code>。</li></ul><p>圆度常定义为：</p><p>[<br>C&#x3D;\frac{4\pi A}{P^2}<br>]</p><p>理想圆接近 1；像素化和轮廓噪声会使其下降。矩形填充率可取 <code>A/(w·h)</code>，凸度可取 <code>A/A_hull</code>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">contours, hierarchy = cv.findContours(</span><br><span class="line">    mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE</span><br><span class="line">)</span><br><span class="line">shapes = []</span><br><span class="line"><span class="keyword">for</span> cnt <span class="keyword">in</span> contours:</span><br><span class="line">    area = cv.contourArea(cnt)</span><br><span class="line">    <span class="keyword">if</span> area &lt; <span class="number">200</span>:</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">    perimeter = cv.arcLength(cnt, <span class="literal">True</span>)</span><br><span class="line">    polygon = cv.approxPolyDP(cnt, <span class="number">0.02</span> * perimeter, <span class="literal">True</span>)</span><br><span class="line">    shapes.append((cnt, polygon, area))</span><br></pre></td></tr></table></figure><h3 id="4-6-2-失败、调参和验证"><a href="#4-6-2-失败、调参和验证" class="headerlink" title="4.6.2 失败、调参和验证"></a>4.6.2 失败、调参和验证</h3><ul><li>失败原因：轮廓断裂；噪声产生大量小轮廓；ROI 偏移未还原；用像素面积固定阈值处理多分辨率数据；忽略层级导致孔洞误计。</li><li>调参顺序：先改善掩膜闭合性，再选检索模式，然后按相对面积过滤，最后调近似误差和形状指标。</li><li>验证方法：把轮廓、顶点编号和层级叠加到原图；检查面积守恒；对旋转、缩放样本验证归一化指标稳定性。</li></ul><h2 id="4-7-几何变换与文档扫描"><a href="#4-7-几何变换与文档扫描" class="headerlink" title="4.7 几何变换与文档扫描"></a>4.7 几何变换与文档扫描</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;文档图像&quot;] --&gt; B[&quot;灰度/边缘/形态学&quot;]</span><br><span class="line">    B --&gt; C[&quot;四边形候选&quot;]</span><br><span class="line">    C --&gt; D[&quot;四角点稳定排序&quot;]</span><br><span class="line">    D --&gt; E[&quot;getPerspectiveTransform&quot;]</span><br><span class="line">    E --&gt; F[&quot;warpPerspective&quot;]</span><br><span class="line">    F --&gt; G[&quot;光照校正/二值化&quot;]</span><br><span class="line">    G --&gt; H[&quot;正视文档&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-7-1-变换模型"><a href="#4-7-1-变换模型" class="headerlink" title="4.7.1 变换模型"></a>4.7.1 变换模型</h3><p>仿射变换用 2×3 矩阵，保持平行关系；透视变换用单应矩阵：</p><p>[<br>s\begin{bmatrix}x’\y’\1\end{bmatrix}<br>&#x3D;H\begin{bmatrix}x\y\1\end{bmatrix},\quad H\in\mathbb{R}^{3\times3}<br>]</p><p><code>getAffineTransform</code> 需要三对点，<code>getPerspectiveTransform</code> 需要四对对应点。<code>warpAffine</code>&#x2F;<code>warpPerspective</code> 的 <code>dsize</code> 是输出 <code>(width,height)</code>。<code>perspectiveTransform</code> 用于变换点集，不用于重采样整幅图。<code>remap</code> 适合相机去畸变或任意稠密映射。</p><p>四点排序不能仅在所有视角下机械依赖坐标和差；更稳妥的做法是先取凸包、验证四边形非自交，再按质心极角排序并统一起点和方向。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">src = np.array([[<span class="number">120</span>, <span class="number">80</span>], [<span class="number">920</span>, <span class="number">110</span>], [<span class="number">890</span>, <span class="number">680</span>], [<span class="number">90</span>, <span class="number">650</span>]],</span><br><span class="line">               dtype=np.float32)</span><br><span class="line">dst = np.array([[<span class="number">0</span>, <span class="number">0</span>], [<span class="number">799</span>, <span class="number">0</span>], [<span class="number">799</span>, <span class="number">599</span>], [<span class="number">0</span>, <span class="number">599</span>]],</span><br><span class="line">               dtype=np.float32)</span><br><span class="line">H = cv.getPerspectiveTransform(src, dst)</span><br><span class="line">scan = cv.warpPerspective(image, H, (<span class="number">800</span>, <span class="number">600</span>),</span><br><span class="line">                          flags=cv.INTER_LINEAR,</span><br><span class="line">                          borderMode=cv.BORDER_REPLICATE)</span><br></pre></td></tr></table></figure><h3 id="4-7-2-失败、调参和验证"><a href="#4-7-2-失败、调参和验证" class="headerlink" title="4.7.2 失败、调参和验证"></a>4.7.2 失败、调参和验证</h3><ul><li>失败原因：四角顺序不一致导致翻转；候选不是凸四边形；文档边缘出画；镜头畸变未校正；纸张弯曲却使用平面单应。</li><li>调参顺序：先去畸变，再提高边缘召回，按面积&#x2F;凸性&#x2F;角度筛四边形，最后确定输出比例与插值。</li><li>验证方法：将目标四角通过逆单应投回原图；计算边线直线度、相邻边夹角、文字行水平度和正反向变换误差。</li></ul><h2 id="4-8-特征匹配与几何验证"><a href="#4-8-特征匹配与几何验证" class="headerlink" title="4.8 特征匹配与几何验证"></a>4.8 特征匹配与几何验证</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">    A[&quot;图像 A&quot;] --&gt; C[&quot;detectAndCompute&quot;]</span><br><span class="line">    B[&quot;图像 B&quot;] --&gt; D[&quot;detectAndCompute&quot;]</span><br><span class="line">    C --&gt; E[&quot;KNN 匹配&quot;]</span><br><span class="line">    D --&gt; E</span><br><span class="line">    E --&gt; F[&quot;Lowe ratio/互检&quot;]</span><br><span class="line">    F --&gt; G[&quot;RANSAC/USAC&quot;]</span><br><span class="line">    G --&gt; H[&quot;H/F/E 与内点掩膜&quot;]</span><br><span class="line">    H --&gt; I[&quot;重投影或极线验证&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-8-1-描述子与匹配器"><a href="#4-8-1-描述子与匹配器" class="headerlink" title="4.8.1 描述子与匹配器"></a>4.8.1 描述子与匹配器</h3><p><code>SIFT_create</code> 生成 <code>CV_32F</code> 浮点描述子，常用 L2 距离；<code>ORB_create</code> 生成 <code>CV_8U</code> 二进制描述子，使用 <code>NORM_HAMMING</code>。<code>BFMatcher.knnMatch(k=2)</code> 可做比率测试；<code>crossCheck=True</code> 只适用于一一最近邻匹配，不与 KNN 比率测试同时使用。</p><p>Lowe 比率判据为：</p><p>[<br>d_1 &lt; r d_2<br>]</p><p>其中 <code>d1,d2</code> 是最近与次近距离，<code>r</code> 常从 <code>0.7~0.8</code> 起试。它只衡量描述子歧义，不能代替几何验证。</p><ul><li>平面场景或纯旋转：<code>findHomography(..., RANSAC/USAC_MAGSAC, ransacReprojThreshold)</code>。</li><li>未标定一般双视图：<code>findFundamentalMat</code>，满足 <code>x_2^T F x_1=0</code>。</li><li>已知相机内参：<code>findEssentialMat</code> 与 <code>recoverPose</code>，满足 <code>x_2^T E x_1=0</code>。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">gray1 = cv.cvtColor(image1, cv.COLOR_BGR2GRAY)</span><br><span class="line">gray2 = cv.cvtColor(image2, cv.COLOR_BGR2GRAY)</span><br><span class="line">orb = cv.ORB_create(nfeatures=<span class="number">2000</span>)</span><br><span class="line">kp1, des1 = orb.detectAndCompute(gray1, <span class="literal">None</span>)</span><br><span class="line">kp2, des2 = orb.detectAndCompute(gray2, <span class="literal">None</span>)</span><br><span class="line"><span class="keyword">if</span> des1 <span class="keyword">is</span> <span class="literal">None</span> <span class="keyword">or</span> des2 <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">    <span class="keyword">raise</span> RuntimeError(<span class="string">&quot;描述子为空&quot;</span>)</span><br><span class="line">knn = cv.BFMatcher(cv.NORM_HAMMING).knnMatch(des1, des2, k=<span class="number">2</span>)</span><br><span class="line">good = [m <span class="keyword">for</span> pair <span class="keyword">in</span> knn <span class="keyword">if</span> <span class="built_in">len</span>(pair) == <span class="number">2</span></span><br><span class="line">        <span class="keyword">for</span> m, n <span class="keyword">in</span> [pair] <span class="keyword">if</span> m.distance &lt; <span class="number">0.75</span> * n.distance]</span><br><span class="line">pts1 = np.float32([kp1[m.queryIdx].pt <span class="keyword">for</span> m <span class="keyword">in</span> good])</span><br><span class="line">pts2 = np.float32([kp2[m.trainIdx].pt <span class="keyword">for</span> m <span class="keyword">in</span> good])</span><br><span class="line">H, inliers = cv.findHomography(pts1, pts2, cv.USAC_MAGSAC, <span class="number">3.0</span>)</span><br></pre></td></tr></table></figure><h3 id="4-8-2-失败、调参和验证"><a href="#4-8-2-失败、调参和验证" class="headerlink" title="4.8.2 失败、调参和验证"></a>4.8.2 失败、调参和验证</h3><ul><li>失败原因：纹理重复；关键点过少或集中在小区域；运动模糊；误用距离范数；动态物体主导；平面模型用于强视差场景。</li><li>调参顺序：先确认描述子类型与范数，再增加特征覆盖；随后调比率阈值；最后按图像噪声调 RANSAC 阈值和置信度。</li><li>验证方法：报告原始匹配数、筛后匹配数、内点数和内点率；画内点空间分布；计算对称传输误差或极线距离的中位数和 95 分位数。</li></ul><h2 id="4-9-相机标定、PnP-与双目"><a href="#4-9-相机标定、PnP-与双目" class="headerlink" title="4.9 相机标定、PnP 与双目"></a>4.9 相机标定、PnP 与双目</h2><h3 id="4-9-1-单目标定"><a href="#4-9-1-单目标定" class="headerlink" title="4.9.1 单目标定"></a>4.9.1 单目标定</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;多姿态标定图&quot;] --&gt; B[&quot;棋盘/圆点/ChArUco 检测&quot;]</span><br><span class="line">    B --&gt; C[&quot;亚像素优化&quot;]</span><br><span class="line">    C --&gt; D[&quot;calibrateCamera&quot;]</span><br><span class="line">    D --&gt; E[&quot;逐帧重投影误差&quot;]</span><br><span class="line">    E --&gt; F[&quot;K、D、图像尺寸&quot;]</span><br></pre></td></tr></table></figure><p>针孔模型为：</p><p>[<br>s\begin{bmatrix}u\v\1\end{bmatrix}<br>&#x3D;K[R|t]\begin{bmatrix}X\Y\Z\1\end{bmatrix},\quad<br>K&#x3D;\begin{bmatrix}f_x&amp;0&amp;c_x\0&amp;f_y&amp;c_y\0&amp;0&amp;1\end{bmatrix}<br>]</p><p><code>findChessboardCorners</code> 的 <code>patternSize</code> 是每行、每列的内角点数，不是方格数。<code>cornerSubPix</code> 输入灰度图和初始角点。<code>calibrateCamera</code> 输入每帧 <code>N×3</code> 物点与对应 <code>N×2</code> 像点，输出 RMS、内参、畸变、每帧外参。鱼眼模型应使用 <code>cv.fisheye</code> API，不能混用普通畸变系数语义。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">ok, corners = cv.findChessboardCorners(gray, (<span class="number">9</span>, <span class="number">6</span>))</span><br><span class="line"><span class="keyword">if</span> ok:</span><br><span class="line">    term = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_COUNT, <span class="number">30</span>, <span class="number">1e-3</span>)</span><br><span class="line">    corners = cv.cornerSubPix(gray, corners, (<span class="number">11</span>, <span class="number">11</span>), (-<span class="number">1</span>, -<span class="number">1</span>), term)</span><br><span class="line">    image_points.append(corners)</span><br><span class="line">    object_points.append(board_points.copy())</span><br><span class="line">rms, K, dist, rvecs, tvecs = cv.calibrateCamera(</span><br><span class="line">    object_points, image_points, gray.shape[::-<span class="number">1</span>], <span class="literal">None</span>, <span class="literal">None</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>失败原因包括姿态单一、标定板仅居中、覆盖深度不足、运动模糊、打印比例不准和运行分辨率变化。调参先改善采集覆盖，再剔除检测错误帧，最后谨慎固定高阶畸变参数。验证时必须用 <code>projectPoints</code> 计算逐帧误差，而不只看总体 RMS，并检查 <code>fx/fy</code>、主点及畸变曲线是否合理。</p><h3 id="4-9-2-PnP-位姿"><a href="#4-9-2-PnP-位姿" class="headerlink" title="4.9.2 PnP 位姿"></a>4.9.2 PnP 位姿</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;N 个 3D 物点&quot;] --&gt; C[&quot;solvePnP/Ransac&quot;]</span><br><span class="line">    B[&quot;对应 2D 像点 + K,D&quot;] --&gt; C</span><br><span class="line">    C --&gt; D[&quot;rvec,tvec&quot;]</span><br><span class="line">    D --&gt; E[&quot;projectPoints&quot;]</span><br><span class="line">    E --&gt; F[&quot;重投影误差/坐标轴&quot;]</span><br></pre></td></tr></table></figure><p><code>solvePnP</code> 的物点和像点必须一一对应。通用情况可从 <code>SOLVEPNP_ITERATIVE</code> 开始；平面方形标记可考虑 <code>SOLVEPNP_IPPE_SQUARE</code>，其四个物点有规定顺序；存在离群点时使用 <code>solvePnPRansac</code>，再以内点调用 <code>solvePnPRefineLM</code>。</p><p>失败原因：单位不一致；点顺序错误；点近共线；平面解歧义；错误内参；把相机到物体变换与物体到相机变换混淆。调参先核对坐标系和单位，再选求解器，再调 RANSAC 重投影阈值，最后细化。验证应检查正深度、重投影误差以及时序位姿连续性。</p><h3 id="4-9-3-双目标定与深度"><a href="#4-9-3-双目标定与深度" class="headerlink" title="4.9.3 双目标定与深度"></a>4.9.3 双目标定与深度</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;同步左右图&quot;] --&gt; B[&quot;stereoCalibrate&quot;]</span><br><span class="line">    B --&gt; C[&quot;stereoRectify&quot;]</span><br><span class="line">    C --&gt; D[&quot;initUndistortRectifyMap/remap&quot;]</span><br><span class="line">    D --&gt; E[&quot;StereoBM/SGBM&quot;]</span><br><span class="line">    E --&gt; F[&quot;disparity&quot;]</span><br><span class="line">    F --&gt; G[&quot;reprojectImageTo3D&quot;]</span><br></pre></td></tr></table></figure><p>校正后对应点应位于同一水平扫描线。若焦距为 <code>f</code>、基线为 <code>B</code>、视差为 <code>d</code>，则：</p><p>[<br>Z&#x3D;\frac{fB}{d}<br>]</p><p><code>StereoSGBM_create</code> 的 <code>numDisparities</code> 必须为 16 的倍数，<code>blockSize</code> 为正奇数；常用平滑罚项起点为 <code>P1=8·C·b^2</code>、<code>P2=32·C·b^2</code>。输出视差通常带 4 位小数定标，转浮点时除以 16。</p><p>失败原因：左右不同步、曝光差、垂直视差、弱纹理、重复纹理和遮挡。调参先验证校正，再定最小&#x2F;最大视差范围，然后调窗口与 <code>P1/P2</code>，最后做左右一致性和 speckle 清理。验证用极线纵向误差、有效视差比例和已知距离平面的深度误差。</p><h2 id="4-10-光流、背景建模与跟踪"><a href="#4-10-光流、背景建模与跟踪" class="headerlink" title="4.10 光流、背景建模与跟踪"></a>4.10 光流、背景建模与跟踪</h2><h3 id="4-10-1-光流"><a href="#4-10-1-光流" class="headerlink" title="4.10.1 光流"></a>4.10.1 光流</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;前一灰度帧&quot;] --&gt; C[&quot;LK/Farneback&quot;]</span><br><span class="line">    B[&quot;当前灰度帧&quot;] --&gt; C</span><br><span class="line">    D[&quot;前帧特征点&quot;] --&gt; C</span><br><span class="line">    C --&gt; E[&quot;位移/稠密 flow&quot;]</span><br><span class="line">    E --&gt; F[&quot;状态过滤与重检测&quot;]</span><br></pre></td></tr></table></figure><p>亮度恒常和小运动假设给出光流约束：</p><p>[<br>I_xu+I_yv+I_t&#x3D;0<br>]</p><p>Lucas–Kanade 在局部窗口内联合求解，<code>calcOpticalFlowPyrLK</code> 输入前后帧及 <code>N×1×2 float32</code> 点，输出新点、<code>status</code> 和误差。<code>winSize</code> 控制局部窗口，<code>maxLevel</code> 控制金字塔层数。<code>calcOpticalFlowFarneback</code> 输出 <code>H×W×2 float32</code> 稠密流。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">p0 = cv.goodFeaturesToTrack(prev_gray, <span class="number">500</span>, <span class="number">0.01</span>, <span class="number">8</span>)</span><br><span class="line">p1, status, err = cv.calcOpticalFlowPyrLK(</span><br><span class="line">    prev_gray, gray, p0, <span class="literal">None</span>,</span><br><span class="line">    winSize=(<span class="number">21</span>, <span class="number">21</span>), maxLevel=<span class="number">3</span>,</span><br><span class="line">    criteria=(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, <span class="number">30</span>, <span class="number">0.01</span>)</span><br><span class="line">)</span><br><span class="line">good0 = p0[status.ravel() == <span class="number">1</span>]</span><br><span class="line">good1 = p1[status.ravel() == <span class="number">1</span>]</span><br></pre></td></tr></table></figure><p>失败原因：快速运动超出金字塔搜索；遮挡；无纹理区域；曝光突变；点漂移。调参先改善帧间隔和角点质量，再增大金字塔层级，随后调窗口，最后加前后向一致性并周期性重检测。验证可将点正向追踪后反向追踪，统计往返误差和有效点寿命。</p><h3 id="4-10-2-背景建模"><a href="#4-10-2-背景建模" class="headerlink" title="4.10.2 背景建模"></a>4.10.2 背景建模</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;视频帧&quot;] --&gt; B[&quot;MOG2/KNN apply&quot;]</span><br><span class="line">    B --&gt; C[&quot;前景掩膜&quot;]</span><br><span class="line">    C --&gt; D[&quot;去阴影/形态学&quot;]</span><br><span class="line">    D --&gt; E[&quot;连通域/检测框&quot;]</span><br></pre></td></tr></table></figure><p><code>createBackgroundSubtractorMOG2(history=500, varThreshold=16, detectShadows=True)</code> 适合较稳定相机；阴影通常标为 127，前景为 255，不能直接把所有非零值视为目标。<code>learningRate=0</code> 冻结模型，负值让算法自动选择，较大值适应更快但会吞掉慢速目标。</p><p>失败原因：相机抖动、周期背景、自动曝光、目标长时间静止。调参先固定相机和曝光，再设置学习率与历史长度，然后调判定阈值，最后清理阴影和小区域。验证使用前景 IoU、误警面积、目标进入&#x2F;离开后的适应时间。</p><h3 id="4-10-3-状态跟踪"><a href="#4-10-3-状态跟踪" class="headerlink" title="4.10.3 状态跟踪"></a>4.10.3 状态跟踪</h3><p>Kalman Filter 只估计状态，不负责目标检测或多目标关联。线性模型为：</p><p>[<br>x_k&#x3D;Ax_{k-1}+Bu_k+w_k,\qquad z_k&#x3D;Hx_k+v_k<br>]</p><p><code>cv.KalmanFilter(dynamParams, measureParams)</code> 的 <code>transitionMatrix</code>、<code>measurementMatrix</code>、过程噪声 <code>Q</code>、测量噪声 <code>R</code> 必须与状态定义一致。失败通常来自时间步长错误、噪声协方差不合理和关联错配。先验证检测，再验证关联门限，随后调 <code>R</code>，最后调 <code>Q</code>；以轨迹 RMSE、ID 切换、丢失恢复时间验证。</p><h2 id="4-11-图像分割"><a href="#4-11-图像分割" class="headerlink" title="4.11 图像分割"></a>4.11 图像分割</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;图像/二值先验&quot;] --&gt; B&#123;&quot;任务&quot;&#125;</span><br><span class="line">    B --&gt;|连通区域| C[&quot;connectedComponentsWithStats&quot;]</span><br><span class="line">    B --&gt;|接触目标| D[&quot;distanceTransform + watershed&quot;]</span><br><span class="line">    B --&gt;|交互抠图| E[&quot;grabCut&quot;]</span><br><span class="line">    B --&gt;|种子扩张| F[&quot;floodFill&quot;]</span><br><span class="line">    C --&gt; G[&quot;标签/统计量&quot;]</span><br><span class="line">    D --&gt; G</span><br><span class="line">    E --&gt; G</span><br><span class="line">    F --&gt; G</span><br></pre></td></tr></table></figure><h3 id="4-11-1-连通域与-Watershed"><a href="#4-11-1-连通域与-Watershed" class="headerlink" title="4.11.1 连通域与 Watershed"></a>4.11.1 连通域与 Watershed</h3><p><code>connectedComponentsWithStats</code> 接受 8 位单通道图，返回 <code>int32</code> 标签、包围框&#x2F;面积统计和质心。<code>connectivity=4</code> 不连接对角像素，<code>8</code> 会连接。</p><p>Watershed 把梯度图看作地形，从 marker 指定的种子扩张。<code>watershed(image, markers)</code> 的图像是 8 位三通道，marker 是 <code>int32</code> 单通道；处理后分水岭边界标为 <code>-1</code>。未知区域必须为 0，已知前景实例使用不同正整数标签。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">dist = cv.distanceTransform(mask, cv.DIST_L2, <span class="number">5</span>)</span><br><span class="line">_, sure_fg = cv.threshold(dist, <span class="number">0.45</span> * dist.<span class="built_in">max</span>(), <span class="number">255</span>, <span class="number">0</span>)</span><br><span class="line">sure_fg = sure_fg.astype(np.uint8)</span><br><span class="line">sure_bg = cv.dilate(mask, np.ones((<span class="number">3</span>, <span class="number">3</span>), np.uint8), iterations=<span class="number">3</span>)</span><br><span class="line">unknown = cv.subtract(sure_bg, sure_fg)</span><br><span class="line">count, markers = cv.connectedComponents(sure_fg)</span><br><span class="line">markers = markers + <span class="number">1</span></span><br><span class="line">markers[unknown == <span class="number">255</span>] = <span class="number">0</span></span><br><span class="line">markers = cv.watershed(image.copy(), markers.astype(np.int32))</span><br></pre></td></tr></table></figure><h3 id="4-11-2-GrabCut、Flood-Fill-与聚类"><a href="#4-11-2-GrabCut、Flood-Fill-与聚类" class="headerlink" title="4.11.2 GrabCut、Flood Fill 与聚类"></a>4.11.2 GrabCut、Flood Fill 与聚类</h3><p><code>grabCut</code> 输入 BGR 图、<code>uint8</code> 掩膜、矩形、背景&#x2F;前景模型和迭代数；掩膜值是 <code>GC_BGD/FGD/PR_BGD/PR_FGD</code>。矩形初始化要求目标大体位于框内，精细边界应再用掩膜初始化。<code>floodFill</code> 从种子按颜色差扩张，需谨慎选择 <code>loDiff/upDiff</code>。颜色聚类可把像素转为 <code>float32 N×C</code> 后调用 <code>kmeans</code>，但空间不连续且类别编号无语义。</p><ul><li>失败原因：marker 粘连或缺失导致 Watershed 欠分&#x2F;过分；GrabCut 框包含太多背景或目标触边；聚类只看颜色忽略空间。</li><li>调参顺序：先确认任务线索，再优化前景&#x2F;背景种子；Watershed 调距离阈值，GrabCut 调初始化和迭代，最后做区域过滤。</li><li>验证方法：IoU、Dice、边界 F1、实例计数误差；将每个标签随机着色，检查标签泄漏和碎片。</li></ul><h2 id="4-12-图像拼接"><a href="#4-12-图像拼接" class="headerlink" title="4.12 图像拼接"></a>4.12 图像拼接</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;有重叠的多图&quot;] --&gt; B[&quot;特征与成对匹配&quot;]</span><br><span class="line">    B --&gt; C[&quot;相机/单应估计&quot;]</span><br><span class="line">    C --&gt; D[&quot;Bundle Adjustment&quot;]</span><br><span class="line">    D --&gt; E[&quot;投影与曝光补偿&quot;]</span><br><span class="line">    E --&gt; F[&quot;接缝搜索&quot;]</span><br><span class="line">    F --&gt; G[&quot;羽化/多频段融合&quot;]</span><br><span class="line">    G --&gt; H[&quot;全景图&quot;]</span><br></pre></td></tr></table></figure><p><code>cv.Stitcher.create(mode)</code> 提供完整封装：<code>PANORAMA</code> 假设相机旋转为主，<code>SCANS</code> 更适合仿射扫描件。<code>stitch(images)</code> 返回状态码和结果，不应只捕获异常。状态包括成功、需要更多图像、单应估计失败和相机参数调整失败。</p><p>高级流水线位于 <code>cv::detail</code>：特征寻找、最佳匹配图、运动估计、Bundle Adjustment、球面&#x2F;柱面 warper、曝光补偿、接缝寻找及 blender 可独立替换。多频段融合减少低频曝光缝，羽化融合开销较小但不能修复错位。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">stitcher = cv.Stitcher.create(cv.Stitcher_PANORAMA)</span><br><span class="line">status, panorama = stitcher.stitch(images)</span><br><span class="line"><span class="keyword">if</span> status != cv.Stitcher_OK:</span><br><span class="line">    <span class="keyword">raise</span> RuntimeError(<span class="string">f&quot;拼接失败，状态码=<span class="subst">&#123;status&#125;</span>&quot;</span>)</span><br></pre></td></tr></table></figure><ul><li>失败原因：重叠不足；纹理单一；视差显著；滚动快门；移动物体；输入顺序或尺度跨度过大。</li><li>调参顺序：先检查相邻图重叠和匹配内点，再选 <code>PANORAMA/SCANS</code>；随后调匹配置信度与投影模型，最后才调曝光、接缝和融合。</li><li>验证方法：匹配图连通性、边缘重影宽度、接缝两侧亮度差、直线弯曲程度和有效画布比例；不要仅凭“能输出图”判定成功。</li></ul><h2 id="4-13-DNN-推理"><a href="#4-13-DNN-推理" class="headerlink" title="4.13 DNN 推理"></a>4.13 DNN 推理</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;readNet/ONNX&quot;] --&gt; B[&quot;Net&quot;]</span><br><span class="line">    C[&quot;原图&quot;] --&gt; D[&quot;resize/letterbox&quot;]</span><br><span class="line">    D --&gt; E[&quot;blobFromImage&quot;]</span><br><span class="line">    E --&gt; F[&quot;setInput&quot;]</span><br><span class="line">    B --&gt; F</span><br><span class="line">    F --&gt; G[&quot;forward&quot;]</span><br><span class="line">    G --&gt; H[&quot;按模型解码&quot;]</span><br><span class="line">    H --&gt; I[&quot;阈值/NMS&quot;]</span><br><span class="line">    I --&gt; J[&quot;坐标回映射&quot;]</span><br></pre></td></tr></table></figure><h3 id="4-13-1-输入、执行和输出"><a href="#4-13-1-输入、执行和输出" class="headerlink" title="4.13.1 输入、执行和输出"></a>4.13.1 输入、执行和输出</h3><p><code>readNet</code>&#x2F;<code>readNetFromONNX</code> 返回 <code>cv.dnn.Net</code>。<code>blobFromImage(image, scalefactor, size, mean, swapRB, crop, ddepth)</code> 通常输出 NCHW 四维 blob。实际预处理由模型训练配置决定，OpenCV 不会自动推断 letterbox、均值、标准差或输出布局。</p><p>常见标准化为：</p><p>[<br>x’&#x3D;(x-\mu)\cdot s<br>]</p><p>注意 <code>blobFromImage</code> 的顺序是先减 <code>mean</code> 再乘 <code>scalefactor</code>；<code>swapRB=True</code> 会交换红蓝通道。若模型要求逐通道标准差，通常需自行构造浮点输入。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">net = cv.dnn.readNetFromONNX(<span class="string">&quot;model.onnx&quot;</span>)</span><br><span class="line">inp, scale, (pad_x, pad_y) = letterbox(image, (<span class="number">640</span>, <span class="number">640</span>))</span><br><span class="line">blob = cv.dnn.blobFromImage(</span><br><span class="line">    inp, scalefactor=<span class="number">1.0</span> / <span class="number">255.0</span>, size=(<span class="number">640</span>, <span class="number">640</span>),</span><br><span class="line">    mean=(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>), swapRB=<span class="literal">True</span>, crop=<span class="literal">False</span></span><br><span class="line">)</span><br><span class="line">net.setInput(blob)</span><br><span class="line">outputs = net.forward(net.getUnconnectedOutLayersNames())</span><br></pre></td></tr></table></figure><p><code>setPreferableBackend</code> 和 <code>setPreferableTarget</code> 只表达偏好；部署前应通过构建信息、运行日志和基准确认实际后端。动态形状、量化模型和自定义算子必须做兼容性测试。</p><h3 id="4-13-2-后处理、失败与验证"><a href="#4-13-2-后处理、失败与验证" class="headerlink" title="4.13.2 后处理、失败与验证"></a>4.13.2 后处理、失败与验证</h3><p>检测后处理通常先按置信度筛选，再调用 <code>NMSBoxes(bboxes, scores, score_threshold, nms_threshold)</code>。IoU 为：</p><p>[<br>\operatorname{IoU}(A,B)&#x3D;\frac{|A\cap B|}{|A\cup B|}<br>]</p><p>失败原因：BGR&#x2F;RGB 错；拉伸与 letterbox 混用；输出维度按错误模型版本解释；置信度定义错误；坐标忘记减 padding；类别索引偏移；NMS 跨类别误抑制。</p><p>调参顺序：先用已知输入对齐训练框架的预处理和原始张量，再实现解码与坐标回映射，随后调置信度和 NMS，最后选择后端和批量。验证应比较参考框架逐层或最终输出、固定样本数值误差、mAP&#x2F;IoU，以及预热后的端到端延迟和峰值内存。</p><h2 id="4-14-模板、霍夫与-ArUco"><a href="#4-14-模板、霍夫与-ArUco" class="headerlink" title="4.14 模板、霍夫与 ArUco"></a>4.14 模板、霍夫与 ArUco</h2><h3 id="4-14-1-模板匹配"><a href="#4-14-1-模板匹配" class="headerlink" title="4.14.1 模板匹配"></a>4.14.1 模板匹配</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;搜索图&quot;] --&gt; C[&quot;matchTemplate&quot;]</span><br><span class="line">    B[&quot;模板&quot;] --&gt; C</span><br><span class="line">    C --&gt; D[&quot;响应图&quot;]</span><br><span class="line">    D --&gt; E[&quot;minMaxLoc/局部峰值&quot;]</span><br><span class="line">    E --&gt; F[&quot;阈值与 NMS&quot;]</span><br></pre></td></tr></table></figure><p><code>matchTemplate(image, templ, method, mask)</code> 输出尺寸为 <code>(W-w+1, H-h+1)</code> 的浮点响应图。<code>TM_SQDIFF</code> 系列越小越好，相关系数系列越大越好。归一化相关系数可理解为对均值和能量归一化后的相似度。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">response = cv.matchTemplate(gray, templ, cv.TM_CCOEFF_NORMED)</span><br><span class="line">_, score, _, location = cv.minMaxLoc(response)</span><br><span class="line"><span class="keyword">if</span> score &gt;= <span class="number">0.85</span>:</span><br><span class="line">    x, y = location</span><br></pre></td></tr></table></figure><p>失败原因是尺度、旋转、透视和光照差异，以及低纹理模板。先固定尺度搜索，再设置分数阈值和峰值抑制，最后才扩展图像金字塔或角度搜索。用正负样本分数分布、定位误差和重复检测率验证。</p><h3 id="4-14-2-霍夫直线与圆"><a href="#4-14-2-霍夫直线与圆" class="headerlink" title="4.14.2 霍夫直线与圆"></a>4.14.2 霍夫直线与圆</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;灰度图&quot;] --&gt; B[&quot;Canny&quot;]</span><br><span class="line">    B --&gt; C[&quot;HoughLinesP/HoughCircles&quot;]</span><br><span class="line">    C --&gt; D[&quot;长度/角度/半径筛选&quot;]</span><br><span class="line">    D --&gt; E[&quot;几何对象&quot;]</span><br></pre></td></tr></table></figure><p>直线法式为：</p><p>[<br>\rho&#x3D;x\cos\theta+y\sin\theta<br>]</p><p><code>HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap)</code> 输入 8 位二值边缘图，输出线段端点。<code>HoughCircles</code> 常用 <code>HOUGH_GRADIENT</code>；<code>dp</code> 是累加器与图像分辨率反比，<code>minDist</code> 抑制相邻圆，<code>param1</code> 通常是内部 Canny 高阈值，<code>param2</code> 是圆心累加阈值。</p><p>失败原因：边缘太碎、纹理伪线、<code>maxLineGap</code> 连接无关边、半径范围过宽。调参先稳定边缘，再限定 ROI 和角度&#x2F;半径范围，随后调投票阈值，最后调线长或圆间距。验证用端点到标注线距离、角度误差、圆心误差和半径误差。</p><h3 id="4-14-3-ArUco-与-ChArUco"><a href="#4-14-3-ArUco-与-ChArUco" class="headerlink" title="4.14.3 ArUco 与 ChArUco"></a>4.14.3 ArUco 与 ChArUco</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">    A[&quot;去畸变或原始图&quot;] --&gt; B[&quot;ArucoDetector.detectMarkers&quot;]</span><br><span class="line">    B --&gt; C[&quot;角点 + IDs + rejected&quot;]</span><br><span class="line">    C --&gt; D[&quot;板级匹配/角点细化&quot;]</span><br><span class="line">    D --&gt; E[&quot;solvePnP&quot;]</span><br><span class="line">    E --&gt; F[&quot;projectPoints/drawFrameAxes&quot;]</span><br></pre></td></tr></table></figure><p>OpenCV 4.13.0 使用 <code>cv.aruco.ArucoDetector(dictionary, detectorParams)</code> 检测标记，输出每个标记的四角、ID 和拒绝候选。字典必须与打印标记一致。姿态估计可将已知标记或 Board 的三维角点与检测二维角点交给 <code>solvePnP</code>；单个方形标记适合 IPPE 方形模型。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250)</span><br><span class="line">params = cv.aruco.DetectorParameters()</span><br><span class="line">detector = cv.aruco.ArucoDetector(dictionary, params)</span><br><span class="line">corners, ids, rejected = detector.detectMarkers(image)</span><br><span class="line"><span class="keyword">if</span> ids <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span>:</span><br><span class="line">    cv.aruco.drawDetectedMarkers(image, corners, ids)</span><br></pre></td></tr></table></figure><p>失败原因：字典错误；打印边框不足；标记像素过少；反光、模糊或遮挡；角点顺序与三维点不一致；未考虑镜头畸变。调参先保证打印质量和像素尺寸，再选角点细化方式，随后调整自适应阈值窗口和候选周长范围，最后估计位姿。验证 marker 检出率、ID 混淆、角点重投影误差、姿态抖动和不同距离下的稳定性。</p><h2 id="4-15-验收与源码核验"><a href="#4-15-验收与源码核验" class="headerlink" title="4.15 验收与源码核验"></a>4.15 验收与源码核验</h2><p>验收至少覆盖：输入类型契约；中间结果留存；独立验证集阈值；重投影、极线或逆变换误差；空图与无候选分支；噪声、模糊、曝光、尺度、旋转、遮挡扰动；视频延迟和丢帧；DNN 与参考框架数值对齐。</p><p>本章 API 与主要参数已按仓库内 <code>opencv-4.13.0/modules/</code> 下的 <code>imgproc</code>、<code>features2d</code>、<code>calib3d</code>、<code>video</code>、<code>stitching</code>、<code>dnn</code>、<code>objdetect</code> 公开头文件核验，其中 ArUco 类声明位于 <code>objdetect/include/opencv2/objdetect/aruco_detector.hpp</code>。版本升级时仍须复查函数重载、枚举、默认参数、模型导入兼容性和 Python 绑定。</p><p>源码&#x2F;API 核验不能替代任务数据上的定量验证；只有指标、失败样本和中间产物都可复现，流水线才算完成。</p>]]>
    </content>
    <id>http://example.com/n/1203/</id>
    <link href="http://example.com/n/1203/"/>
    <published>2026-09-16T03:03:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="04-OpenCV-4-13-0-算法流水线"><a href="#04-OpenCV-4-13-0-算法流水线" class="headerlink" title="04 OpenCV 4.13.0 算法流水线"></a>04 OpenCV 4.13.0 算法流]]>
    </summary>
    <title>04 OpenCV 4.13.0 算法流水线</title>
    <updated>2026-09-16T03:49:31.696Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="04-算法流水线"><a href="#04-算法流水线" class="headerlink" title="04 算法流水线"></a>04 算法流水线</h1><h2 id="4-1-检测训练"><a href="#4-1-检测训练" class="headerlink" title="4.1 检测训练"></a>4.1 检测训练</h2><p>入口：<code>train.py::main()</code> → <code>train()</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">  OPT[&quot;parse_opt&quot;] --&gt; DATA[&quot;check_dataset&quot;]</span><br><span class="line">  DATA --&gt; MODEL[&quot;加载权重/按 YAML 创建模型&quot;]</span><br><span class="line">  MODEL --&gt; FREEZE[&quot;可选冻结层&quot;]</span><br><span class="line">  FREEZE --&gt; DL[&quot;创建 train/val DataLoader&quot;]</span><br><span class="line">  DL --&gt; AA[&quot;AutoAnchor&quot;]</span><br><span class="line">  AA --&gt; LOOP[&quot;Epoch/Batch 循环&quot;]</span><br><span class="line">  LOOP --&gt; FW[&quot;forward&quot;]</span><br><span class="line">  FW --&gt; LOSS[&quot;ComputeLoss&quot;]</span><br><span class="line">  LOSS --&gt; AMP[&quot;AMP backward + 梯度裁剪&quot;]</span><br><span class="line">  AMP --&gt; STEP[&quot;梯度累积 + optimizer.step&quot;]</span><br><span class="line">  STEP --&gt; EMA[&quot;ModelEMA&quot;]</span><br><span class="line">  EMA --&gt; VAL[&quot;val.run&quot;]</span><br><span class="line">  VAL --&gt; SAVE[&quot;last.pt / best.pt / EarlyStopping&quot;]</span><br></pre></td></tr></table></figure><h3 id="初始化阶段"><a href="#初始化阶段" class="headerlink" title="初始化阶段"></a>初始化阶段</h3><ol><li>解析超参数并保存 <code>hyp.yaml</code>、<code>opt.yaml</code></li><li>检查数据集 YAML</li><li>加载预训练 checkpoint，或按 YAML 从零创建</li><li>通过 state_dict 交集迁移可匹配权重</li><li>配置冻结层、AMP、图像尺寸</li><li>创建优化器、学习率调度器、EMA</li><li>创建训练&#x2F;验证 DataLoader</li><li>非恢复训练时执行 AutoAnchor</li></ol><h3 id="Batch-阶段"><a href="#Batch-阶段" class="headerlink" title="Batch 阶段"></a>Batch 阶段</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">uint8 图片 → GPU → float → /255</span><br><span class="line">  → Warmup 学习率和 momentum</span><br><span class="line">  → 可选 Multi-scale</span><br><span class="line">  → model(imgs)</span><br><span class="line">  → ComputeLoss(pred, targets)</span><br><span class="line">  → GradScaler.backward()</span><br><span class="line">  → 累积到 nominal batch size 64</span><br><span class="line">  → unscale + clip_grad_norm_(10)</span><br><span class="line">  → optimizer.step()</span><br><span class="line">  → EMA.update()</span><br></pre></td></tr></table></figure><h3 id="Epoch-结束"><a href="#Epoch-结束" class="headerlink" title="Epoch 结束"></a>Epoch 结束</h3><ul><li>更新 LR scheduler</li><li>使用 EMA 模型验证</li><li>用 P&#x2F;R&#x2F;mAP 组合计算 fitness</li><li>EarlyStopping</li><li>保存 <code>last.pt</code>、<code>best.pt</code>、可选周期 checkpoint</li></ul><p>checkpoint 不只是权重，还保存 epoch、best fitness、EMA、optimizer、运行参数、Git 信息和时间。</p><h2 id="4-2-验证"><a href="#4-2-验证" class="headerlink" title="4.2 验证"></a>4.2 验证</h2><p>入口：<code>val.py::run()</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  M[&quot;加载 DetectMultiBackend 或接收训练模型&quot;] --&gt; D[&quot;create_dataloader&quot;]</span><br><span class="line">  D --&gt; F[&quot;forward&quot;]</span><br><span class="line">  F --&gt; N[&quot;NMS&quot;]</span><br><span class="line">  N --&gt; S[&quot;scale_boxes&quot;]</span><br><span class="line">  S --&gt; I[&quot;与 GT 按 IoU 0.50:0.95 匹配&quot;]</span><br><span class="line">  I --&gt; AP[&quot;ap_per_class&quot;]</span><br><span class="line">  AP --&gt; R[&quot;P / R / mAP50 / mAP50-95&quot;]</span><br></pre></td></tr></table></figure><p>验证脚本可独立运行，也可由 <code>train.py</code> 传入模型与 DataLoader。核心函数：</p><ul><li><code>process_batch()</code>：按类别和 IoU 判断检测是否正确</li><li><code>ConfusionMatrix.process_batch()</code>：构建混淆矩阵</li><li><code>ap_per_class()</code>：计算 PR 曲线与 AP</li><li>可选保存 TXT、JSON、混淆矩阵和样本图</li></ul><p>COCO 数据可输出 JSON 并调用 pycocotools 做官方评估。</p><h2 id="4-3-检测推理"><a href="#4-3-检测推理" class="headerlink" title="4.3 检测推理"></a>4.3 检测推理</h2><p>入口：<code>detect.py::run()</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  SRC[&quot;source&quot;] --&gt; KIND[&quot;判断图片/视频/流/屏幕&quot;]</span><br><span class="line">  KIND --&gt; LOAD[&quot;LoadImages / LoadStreams / LoadScreenshots&quot;]</span><br><span class="line">  LOAD --&gt; PRE[&quot;Letterbox + RGB CHW + /255&quot;]</span><br><span class="line">  PRE --&gt; F[&quot;DetectMultiBackend.forward&quot;]</span><br><span class="line">  F --&gt; NMS[&quot;NMS&quot;]</span><br><span class="line">  NMS --&gt; RES[&quot;scale_boxes 回原图&quot;]</span><br><span class="line">  RES --&gt; DRAW[&quot;绘制框/标签/裁剪&quot;]</span><br><span class="line">  DRAW --&gt; SAVE[&quot;图片/MP4/TXT&quot;]</span><br></pre></td></tr></table></figure><p>关键逻辑：</p><ol><li>URL 文件先下载，实时 URL 走流加载器</li><li>根据 stride 修正 <code>imgsz</code></li><li>模型 warmup</li><li>每帧预处理、前向、NMS</li><li>把网络坐标映射回 <code>im0</code></li><li>输出 YOLO TXT、Crop、图片或视频</li><li>打印预处理、推理、NMS 的独立耗时</li></ol><h2 id="4-4-Letterbox-与坐标还原"><a href="#4-4-Letterbox-与坐标还原" class="headerlink" title="4.4 Letterbox 与坐标还原"></a>4.4 Letterbox 与坐标还原</h2><p>Letterbox 不强行把原图拉伸成正方形：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">原图 H×W</span><br><span class="line">  → 按比例缩放</span><br><span class="line">  → 两边填 114</span><br><span class="line">  → 输出尺寸对齐 stride</span><br></pre></td></tr></table></figure><p>优点是物体几何比例不变。缺点是预测框坐标处于「缩放+padding」后的坐标系，所以必须调用：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">det[:, :<span class="number">4</span>] = scale_boxes(network_shape, det[:, :<span class="number">4</span>], original_shape)</span><br></pre></td></tr></table></figure><h2 id="4-5-NMS"><a href="#4-5-NMS" class="headerlink" title="4.5 NMS"></a>4.5 NMS</h2><p><code>utils/general.py::non_max_suppression()</code>：</p><ol><li>用 Objectness 预筛选</li><li>计算 <code>confidence = objectness × class_probability</code></li><li>从 xywh 转为 xyxy</li><li>可筛类别、支持 multi-label</li><li>按类别偏移框，或执行 class-agnostic NMS</li><li>调用 <code>torchvision.ops.nms</code></li><li>限制 <code>max_det</code></li></ol><p><code>conf_thres</code> 控制候选置信度，<code>iou_thres</code> 控制重叠框压制强度。</p><h2 id="4-6-分割流水线"><a href="#4-6-分割流水线" class="headerlink" title="4.6 分割流水线"></a>4.6 分割流水线</h2><h3 id="训练"><a href="#训练" class="headerlink" title="训练"></a>训练</h3><p><code>segment/train.py</code> 大体复用检测训练框架，但使用：</p><ul><li>分割 DataLoader</li><li><code>ComputeLoss</code>（<code>utils/segment/loss.py</code>）</li><li>mask&#x2F;segment 标注</li><li>检测损失 + mask 损失</li></ul><h3 id="推理"><a href="#推理" class="headerlink" title="推理"></a>推理</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Segment head</span><br><span class="line">  → 检测预测 + prototype masks</span><br><span class="line">  → NMS</span><br><span class="line">  → 候选 mask 系数 × prototype</span><br><span class="line">  → 上采样/裁框</span><br><span class="line">  → 绘制实例 mask 和 box</span><br></pre></td></tr></table></figure><h2 id="4-7-分类流水线"><a href="#4-7-分类流水线" class="headerlink" title="4.7 分类流水线"></a>4.7 分类流水线</h2><p>分类任务在 <code>classify/</code>：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ImageFolder</span><br><span class="line">  → 分类增强</span><br><span class="line">  → ClassificationModel</span><br><span class="line">  → CrossEntropy</span><br><span class="line">  → top-1 / top-5</span><br></pre></td></tr></table></figure><p>可从 YOLOv5 检测模型 backbone 构造分类模型。</p><h2 id="4-8-导出流水线"><a href="#4-8-导出流水线" class="headerlink" title="4.8 导出流水线"></a>4.8 导出流水线</h2><p>入口：<code>export.py::run()</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">  PT[&quot;.pt checkpoint&quot;] --&gt; LOAD[&quot;attempt_load + fuse&quot;]</span><br><span class="line">  LOAD --&gt; DRY[&quot;构造假输入并前向&quot;]</span><br><span class="line">  DRY --&gt; TS[&quot;TorchScript&quot;]</span><br><span class="line">  DRY --&gt; ONNX[&quot;ONNX&quot;]</span><br><span class="line">  ONNX --&gt; OV[&quot;OpenVINO&quot;]</span><br><span class="line">  ONNX --&gt; TRT[&quot;TensorRT&quot;]</span><br><span class="line">  DRY --&gt; CML[&quot;CoreML&quot;]</span><br><span class="line">  DRY --&gt; TF[&quot;SavedModel&quot;]</span><br><span class="line">  TF --&gt; PB[&quot;GraphDef&quot;]</span><br><span class="line">  TF --&gt; TFL[&quot;TFLite&quot;]</span><br><span class="line">  TFL --&gt; EDGE[&quot;Edge TPU&quot;]</span><br><span class="line">  DRY --&gt; PD[&quot;Paddle&quot;]</span><br></pre></td></tr></table></figure><p>每种导出器由 <code>@try_export</code> 包装：自动记录耗时、捕获异常并返回产物。<code>dynamic</code>、<code>half</code>、<code>int8</code>、<code>opset</code>、<code>simplify</code> 等参数只对相应格式生效。</p><h2 id="4-9-PyTorch-Hub-流程"><a href="#4-9-PyTorch-Hub-流程" class="headerlink" title="4.9 PyTorch Hub 流程"></a>4.9 PyTorch Hub 流程</h2><p><code>hubconf.py</code> 提供 <code>yolov5n/s/m/l/x</code> 和 <code>custom</code>：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">model = torch.hub.load(<span class="string">&quot;ultralytics/yolov5&quot;</span>, <span class="string">&quot;custom&quot;</span>, <span class="string">&quot;best.pt&quot;</span>)</span><br><span class="line">results = model(images)</span><br></pre></td></tr></table></figure><p>Hub 默认用 <code>AutoShape</code> 包装，因此把预处理、NMS 和结果封装隐藏起来；追踪性能或排查坐标问题时，应回到 <code>detect.py</code> 的显式流程。</p>]]>
    </content>
    <id>http://example.com/n/1223/</id>
    <link href="http://example.com/n/1223/"/>
    <published>2026-09-16T03:03:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="04-算法流水线"><a href="#04-算法流水线" class="headerlink" title="04 算法流水线"></a>04 算法流水线</h1><h2 id="4-1-检测训练"><a href="#4-1-检测训练" class="head]]>
    </summary>
    <title>YOLOv5 7.0：算法流水线</title>
    <updated>2026-09-16T03:49:31.703Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="OpenCV-4-13-0-核心模块手册"><a href="#OpenCV-4-13-0-核心模块手册" class="headerlink" title="OpenCV 4.13.0 核心模块手册"></a>OpenCV 4.13.0 核心模块手册</h1><h2 id="1-手册范围与源码阅读约定"><a href="#1-手册范围与源码阅读约定" class="headerlink" title="1. 手册范围与源码阅读约定"></a>1. 手册范围与源码阅读约定</h2><p>本文面向使用、调试和二次开发 OpenCV 4.13.0 的工程人员。<br>内容以 OpenCV 4.13.0 主仓库源码为准，不把 <code>opencv_contrib</code> 中的扩展模块混入主库能力。<br>文中路径均相对于 OpenCV 源码根目录。<br>17 个模块按同一组问题展开：模块解决什么问题、公开接口在哪里、内部怎样分层、数据怎样进入和离开、性能由谁决定，以及应从哪些文件开始阅读。</p><p>源码阅读建议遵循以下顺序：</p><ol><li>阅读 <code>modules/&lt;module&gt;/CMakeLists.txt</code>，确认强依赖、可选依赖和条件编译项。</li><li>阅读 <code>modules/&lt;module&gt;/include/opencv2/</code>，公开头文件才是稳定使用边界。</li><li>从公开 API 名称反查 <code>modules/&lt;module&gt;/src/</code>，定位调度层和通用实现。</li><li>检查 <code>modules/&lt;module&gt;/test/</code>，测试比注释更能说明空输入、类型和边界行为。</li><li>检查 <code>modules/&lt;module&gt;/perf/</code>，理解热点参数、基准尺寸和优化目标。</li><li>遇到 <code>.dispatch.cpp</code>、<code>.simd.hpp</code>、OpenCL 或 CUDA 文件时，先区分基线实现与加速实现。</li><li>不要把“头文件中存在”理解为“当前构建一定可用”；很多后端受 CMake 配置和外部库影响。</li></ol><p>常见数据约定：</p><ul><li><code>InputArray</code>、<code>OutputArray</code> 是适配层，可接收 <code>Mat</code>、部分 <code>UMat</code>、向量或数组集合。</li><li><code>Mat</code> 是带步长的引用计数视图；ROI 通常不连续，不能默认 <code>step == cols * elemSize()</code>。</li><li><code>UMat</code> 允许透明 API 走 OpenCL，但并不保证每个算子都留在设备端。</li><li>默认彩色图像通常采用 BGR 通道顺序，而不是 RGB。</li><li>许多几何 API 接受 <code>float</code> 或 <code>double</code>；整数点会丢失亚像素精度。</li><li>Python 绑定由头文件注解生成，但某些 C++ 重载、模板和内部类不会原样暴露。</li></ul><h2 id="2-core：数据结构、运行时与数值基础"><a href="#2-core：数据结构、运行时与数值基础" class="headerlink" title="2. core：数据结构、运行时与数值基础"></a>2. core：数据结构、运行时与数值基础</h2><h3 id="2-1-定位"><a href="#2-1-定位" class="headerlink" title="2.1 定位"></a>2.1 定位</h3><p><code>core</code> 是几乎所有 OpenCV 模块的基础依赖。<br>它提供矩阵容器、数组适配、标量与几何类型、内存管理、数值运算、并行框架、硬件能力检测、持久化和透明加速基础。<br>如果算法问题最终表现为类型、步长、引用计数、线程或分发问题，应先回到 <code>core</code>。</p><h3 id="2-2-关键公开类与-API"><a href="#2-2-关键公开类与-API" class="headerlink" title="2.2 关键公开类与 API"></a>2.2 关键公开类与 API</h3><ul><li>数据对象：<code>cv::Mat</code>、<code>cv::UMat</code>、<code>cv::SparseMat</code>、<code>cv::MatExpr</code>。</li><li>类型与容器：<code>Scalar</code>、<code>Point_</code>、<code>Size_</code>、<code>Rect_</code>、<code>Vec</code>、<code>Matx</code>、<code>Range</code>。</li><li>抽象参数：<code>InputArray</code>、<code>OutputArray</code>、<code>InputOutputArray</code> 及数组集合版本。</li><li>生命周期与扩展：<code>Algorithm</code>、<code>Ptr</code>、<code>MatAllocator</code>。</li><li>线性代数：<code>gemm</code>、<code>solve</code>、<code>invert</code>、<code>eigen</code>、<code>SVDecomp</code>、<code>PCA</code>、<code>SVD</code>。</li><li>数组运算：<code>add</code>、<code>multiply</code>、<code>normalize</code>、<code>reduce</code>、<code>split</code>、<code>merge</code>、<code>LUT</code>、<code>minMaxLoc</code>。</li><li>频域与随机：<code>dft</code>、<code>dct</code>、<code>RNG</code>、<code>randu</code>、<code>randn</code>、<code>kmeans</code>。</li><li>运行时：<code>parallel_for_</code>、<code>setNumThreads</code>、<code>getBuildInformation</code>、<code>checkHardwareSupport</code>。</li><li>持久化：<code>FileStorage</code>、<code>FileNode</code>，支持 XML、YAML 和 JSON。</li></ul><h3 id="2-3-内部子系统与主要源码"><a href="#2-3-内部子系统与主要源码" class="headerlink" title="2.3 内部子系统与主要源码"></a>2.3 内部子系统与主要源码</h3><ul><li><code>modules/core/src/matrix.cpp</code>、<code>matrix_operations.cpp</code>：<code>Mat</code> 分配、复制、表达式和常见操作。</li><li><code>modules/core/src/umatrix.cpp</code>：<code>UMat</code> 生命周期、映射和设备&#x2F;主机同步。</li><li><code>modules/core/src/arithm.dispatch.cpp</code>：算术运算及运行时 CPU 分发。</li><li><code>modules/core/src/matmul.dispatch.cpp</code>、<code>matrix_decomp.cpp</code>：矩阵乘法与分解。</li><li><code>modules/core/src/alloc.cpp</code>：对齐分配与内存接口。</li><li><code>modules/core/src/system.cpp</code>：构建信息、硬件检测、错误和时间工具。</li><li><code>modules/core/src/parallel.cpp</code>、<code>parallel_impl.cpp</code>：并行循环与后端适配。</li><li><code>modules/core/src/ocl.cpp</code>、<code>opencl/</code>：OpenCL 上下文、程序缓存和内核。</li><li><code>modules/core/src/persistence*.cpp</code>：配置序列化与格式解析。</li><li><code>modules/core/include/opencv2/core/hal/</code>：供上层算子调用的 HAL 契约。</li></ul><h3 id="2-4-输入输出约束"><a href="#2-4-输入输出约束" class="headerlink" title="2.4 输入输出约束"></a>2.4 输入输出约束</h3><ul><li><code>Mat::type()</code> 同时编码深度与通道数；<code>CV_8UC3</code> 不是三个独立矩阵。</li><li>浅拷贝只增加引用计数；需要独立数据时使用 <code>clone()</code> 或 <code>copyTo()</code>。</li><li><code>reshape()</code> 通常只改头信息，不重排元素；总元素标量数必须保持一致。</li><li>原地运算是否安全取决于具体 API，不能由 <code>InputOutputArray</code> 名称之外自行推断。</li><li>掩码一般要求 <code>CV_8U</code> 单通道，并与被处理数组的空间尺寸一致。</li><li><code>solve</code>、<code>invert</code> 的数值可靠性依赖分解方法、条件数和输入深度。</li></ul><h3 id="2-5-执行与后端特点"><a href="#2-5-执行与后端特点" class="headerlink" title="2.5 执行与后端特点"></a>2.5 执行与后端特点</h3><ul><li>CPU 路径可能经过编译期优化、运行时 SIMD 分发、IPP、HAL 或第三方线性代数库。</li><li><code>setUseOptimized(false)</code> 可辅助对比基线实现，但不等于关闭所有外部后端。</li><li><code>parallel_for_</code> 的具体实现可能是内置线程池、TBB、OpenMP 或平台框架。</li><li><code>UMat</code> 只有在 OpenCL 可用且算子实现支持时才有收益；频繁 <code>getMat()</code> 会触发同步。</li><li>小矩阵上调度、分配和同步成本可能高于加速收益。</li></ul><h3 id="2-6-常见误区与阅读入口"><a href="#2-6-常见误区与阅读入口" class="headerlink" title="2.6 常见误区与阅读入口"></a>2.6 常见误区与阅读入口</h3><ul><li>误区：把 ROI 当连续内存；应检查 <code>isContinuous()</code> 并尊重 <code>step</code>。</li><li>误区：依赖 <code>Mat</code> 离开作用域后仍保留外部裸指针；引用关系必须清晰。</li><li>误区：认为多线程设置会让每个算法线性加速；内存带宽和算法内部并行度会限制收益。</li><li>推荐先读 <code>modules/core/include/opencv2/core/mat.hpp</code> 和 <code>modules/core/include/opencv2/core.hpp</code>。</li><li>再沿 <code>matrix.cpp</code>、<code>arithm.dispatch.cpp</code>、<code>system.cpp</code>、<code>parallel_impl.cpp</code> 阅读一次完整调用链。</li></ul><h2 id="3-imgproc：二维图像处理主体"><a href="#3-imgproc：二维图像处理主体" class="headerlink" title="3. imgproc：二维图像处理主体"></a>3. imgproc：二维图像处理主体</h2><h3 id="3-1-定位"><a href="#3-1-定位" class="headerlink" title="3.1 定位"></a>3.1 定位</h3><p><code>imgproc</code> 覆盖颜色转换、滤波、几何变换、形态学、边缘、轮廓、直方图、分割和绘制。<br>它处在解码、视频采集之后，也常处在特征、标定、检测和 DNN 之前。</p><h3 id="3-2-关键公开类与-API"><a href="#3-2-关键公开类与-API" class="headerlink" title="3.2 关键公开类与 API"></a>3.2 关键公开类与 API</h3><ul><li>颜色：<code>cvtColor</code>、<code>cvtColorTwoPlane</code>、<code>demosaicing</code>、<code>applyColorMap</code>。</li><li>滤波：<code>filter2D</code>、<code>sepFilter2D</code>、<code>GaussianBlur</code>、<code>medianBlur</code>、<code>bilateralFilter</code>。</li><li>梯度与边缘：<code>Sobel</code>、<code>Scharr</code>、<code>Laplacian</code>、<code>Canny</code>。</li><li>几何：<code>resize</code>、<code>warpAffine</code>、<code>warpPerspective</code>、<code>remap</code>、<code>warpPolar</code>。</li><li>形态学：<code>erode</code>、<code>dilate</code>、<code>morphologyEx</code>、<code>getStructuringElement</code>。</li><li>二值与区域：<code>threshold</code>、<code>adaptiveThreshold</code>、<code>floodFill</code>、<code>connectedComponentsWithStats</code>。</li><li>形状：<code>findContours</code>、<code>approxPolyDP</code>、<code>convexHull</code>、<code>moments</code>、<code>fitEllipse</code>。</li><li>检测与分割：<code>HoughLinesP</code>、<code>HoughCircles</code>、<code>matchTemplate</code>、<code>watershed</code>、<code>grabCut</code>。</li><li>直方图：<code>calcHist</code>、<code>calcBackProject</code>、<code>equalizeHist</code>、<code>CLAHE</code>。</li></ul><h3 id="3-3-内部子系统与主要源码"><a href="#3-3-内部子系统与主要源码" class="headerlink" title="3.3 内部子系统与主要源码"></a>3.3 内部子系统与主要源码</h3><ul><li><code>modules/imgproc/src/color.cpp</code> 及 <code>color_*.dispatch.cpp</code>：颜色空间调度与实现。</li><li><code>modules/imgproc/src/filter.dispatch.cpp</code>、<code>box_filter.dispatch.cpp</code>：卷积和可分离滤波。</li><li><code>modules/imgproc/src/imgwarp.cpp</code>：缩放、仿射、透视和重映射。</li><li><code>modules/imgproc/src/morph.dispatch.cpp</code>：腐蚀、膨胀及形态学组合。</li><li><code>modules/imgproc/src/canny.cpp</code>、<code>hough.cpp</code>：边缘和霍夫变换。</li><li><code>modules/imgproc/src/thresh.cpp</code>、<code>histogram.cpp</code>：阈值与直方图。</li><li><code>modules/imgproc/src/contours_new.cpp</code>、<code>convhull.cpp</code>：轮廓和几何形状。</li><li><code>modules/imgproc/src/connectedcomponents.cpp</code>：连通域标记。</li><li><code>modules/imgproc/src/segmentation.cpp</code>、<code>grabcut.cpp</code>：分割算法。</li><li><code>modules/imgproc/src/opencl/</code>：部分透明 API 的 OpenCL 内核。</li></ul><h3 id="3-4-输入输出约束"><a href="#3-4-输入输出约束" class="headerlink" title="3.4 输入输出约束"></a>3.4 输入输出约束</h3><ul><li>颜色转换必须明确源格式；相同的三通道字节可被解释为 BGR、RGB、HSV 或 YUV。</li><li>几何变换的 <code>dsize</code> 顺序是宽、高；矩阵坐标按列为 x、行为 y。</li><li>插值适用于连续值，标签图和掩码通常应使用 <code>INTER_NEAREST</code>。</li><li><code>findContours</code> 主要接收 8 位单通道二值图；层级结构由检索模式决定。</li><li><code>watershed</code> 的标记图要求 <code>CV_32S</code>，并会原地写回边界标记。</li><li><code>filter2D</code> 的 <code>ddepth=-1</code> 保持源深度，可能出现饱和截断。</li></ul><h3 id="3-5-执行与后端特点"><a href="#3-5-执行与后端特点" class="headerlink" title="3.5 执行与后端特点"></a>3.5 执行与后端特点</h3><ul><li>热点算子常通过 HAL、IPP、SIMD、OpenCL 或特定库分发。</li><li>固定小核、可分离核和通用卷积走的路径可能不同。</li><li><code>remap</code> 可用 <code>convertMaps</code> 预转换映射，适合重复处理同一几何关系。</li><li>边界模式直接影响数值结果，<code>BORDER_DEFAULT</code> 不是所有算子的同一种数学外延。</li><li>大图流水线应尽量复用输出缓冲，避免每步重新分配。</li></ul><h3 id="3-6-常见误区与阅读入口"><a href="#3-6-常见误区与阅读入口" class="headerlink" title="3.6 常见误区与阅读入口"></a>3.6 常见误区与阅读入口</h3><ul><li>误区：对深度图、类别图使用普通线性缩放，造成无意义中间值。</li><li>误区：混淆阈值返回值与输出图；<code>threshold</code> 返回实际使用的阈值。</li><li>误区：轮廓坐标忽略 ROI 偏移；应使用 <code>offset</code> 或恢复全图坐标。</li><li>推荐从 <code>modules/imgproc/include/opencv2/imgproc.hpp</code> 按功能组阅读。</li><li>性能排查优先查看对应 <code>.dispatch.cpp</code>、<code>opencl/</code> 和 <code>perf/</code> 用例。</li></ul><h2 id="4-imgcodecs：静态图像编解码"><a href="#4-imgcodecs：静态图像编解码" class="headerlink" title="4. imgcodecs：静态图像编解码"></a>4. imgcodecs：静态图像编解码</h2><h3 id="4-1-定位与公开-API"><a href="#4-1-定位与公开-API" class="headerlink" title="4.1 定位与公开 API"></a>4.1 定位与公开 API</h3><p><code>imgcodecs</code> 将文件或内存字节流转换为像素矩阵，也负责反向编码。<br>主要 API 是 <code>imread</code>、<code>imreadmulti</code>、<code>imdecode</code>、<code>imwrite</code>、<code>imwritemulti</code>、<code>imencode</code>。<br>辅助 API 包括 <code>haveImageReader</code>、<code>haveImageWriter</code>、<code>imcount</code>、<code>ImageCollection</code>。<br>读取标志控制灰度&#x2F;彩色、原深度、方向处理和缩放版本。<br>写入参数使用成对整数序列，参数语义由格式决定。</p><h3 id="4-2-内部子系统与主要源码"><a href="#4-2-内部子系统与主要源码" class="headerlink" title="4.2 内部子系统与主要源码"></a>4.2 内部子系统与主要源码</h3><ul><li><code>modules/imgcodecs/src/loadsave.cpp</code>：统一入口、编解码器选择、文件和内存适配。</li><li><code>modules/imgcodecs/src/grfmt_base.*</code>、<code>grfmts.hpp</code>：编解码器基类与注册集合。</li><li><code>modules/imgcodecs/src/grfmt_jpeg.cpp</code>、<code>grfmt_png.cpp</code>、<code>grfmt_tiff.cpp</code>：常用格式。</li><li><code>modules/imgcodecs/src/grfmt_webp.cpp</code>、<code>grfmt_avif.cpp</code>、<code>grfmt_jpegxl.cpp</code>：现代格式适配。</li><li><code>modules/imgcodecs/src/grfmt_exr.cpp</code>、<code>grfmt_hdr.cpp</code>：高动态范围格式。</li><li><code>modules/imgcodecs/src/exif.cpp</code>：EXIF 方向等元数据处理。</li></ul><h3 id="4-3-约束、后端与误区"><a href="#4-3-约束、后端与误区" class="headerlink" title="4.3 约束、后端与误区"></a>4.3 约束、后端与误区</h3><ul><li><code>imread</code> 失败返回空 <code>Mat</code>，调用方必须检查 <code>empty()</code>。</li><li>解码结果通常是 BGR&#x2F;BGRA；位深和通道还受读取标志及编解码器能力影响。</li><li><code>imdecode</code> 输入是连续字节缓冲，不是已解压像素。</li><li>编解码能力取决于构建时发现的 JPEG、PNG、TIFF、OpenEXR、WebP 等库。</li><li>扩展名常用于写入格式选择；读取侧还会检查签名字节。</li><li>超大或恶意图片可能引发高内存占用，外部输入应设置尺寸和资源限制。</li><li>误区：以为写入浮点矩阵到任意格式都能保留浮点精度；应核对目标格式。</li><li>误区：忽略 EXIF 方向导致宽高和像素朝向与原始存储不一致。</li><li>推荐入口：公开头 <code>modules/imgcodecs/include/opencv2/imgcodecs.hpp</code>，实现入口 <code>loadsave.cpp</code>。</li></ul><h2 id="5-videoio：视频、相机与媒体后端统一层"><a href="#5-videoio：视频、相机与媒体后端统一层" class="headerlink" title="5. videoio：视频、相机与媒体后端统一层"></a>5. videoio：视频、相机与媒体后端统一层</h2><h3 id="5-1-定位与公开-API"><a href="#5-1-定位与公开-API" class="headerlink" title="5.1 定位与公开 API"></a>5.1 定位与公开 API</h3><p><code>videoio</code> 统一视频文件、图像序列、相机、网络流和视频写出。<br>核心类是 <code>VideoCapture</code>、<code>VideoWriter</code> 和自定义流接口 <code>IStreamReader</code>。<br>常用操作包括 <code>open</code>、<code>isOpened</code>、<code>read</code>、<code>grab</code>、<code>retrieve</code>、<code>get</code>、<code>set</code>、<code>write</code>。<br><code>videoio_registry</code> 命名空间可查询已注册后端、相机后端和流后端。<br><code>CAP_PROP_*</code>、<code>VIDEOWRITER_PROP_*</code> 和 <code>VideoAccelerationType</code> 描述跨后端属性。</p><h3 id="5-2-内部子系统与主要源码"><a href="#5-2-内部子系统与主要源码" class="headerlink" title="5.2 内部子系统与主要源码"></a>5.2 内部子系统与主要源码</h3><ul><li><code>modules/videoio/src/cap.cpp</code>：<code>VideoCapture</code>、<code>VideoWriter</code> 门面和后端选择。</li><li><code>modules/videoio/src/videoio_registry.cpp</code>：后端注册、优先级与能力查询。</li><li><code>modules/videoio/src/backend_plugin.cpp</code>：插件后端装载。</li><li><code>modules/videoio/src/cap_ffmpeg.cpp</code>、<code>cap_ffmpeg_impl.hpp</code>：FFmpeg 适配。</li><li><code>modules/videoio/src/cap_gstreamer.cpp</code>：GStreamer 管线适配。</li><li><code>modules/videoio/src/cap_v4l.cpp</code>、<code>cap_msmf.cpp</code>、<code>cap_avfoundation.mm</code>：平台采集。</li><li><code>modules/videoio/src/cap_images.cpp</code>：图像序列后端。</li><li><code>modules/videoio/src/cap_mjpeg_decoder.cpp</code>、<code>cap_mjpeg_encoder.cpp</code>：内置 Motion JPEG 路径。</li></ul><h3 id="5-3-约束、后端与误区"><a href="#5-3-约束、后端与误区" class="headerlink" title="5.3 约束、后端与误区"></a>5.3 约束、后端与误区</h3><ul><li><code>read</code> 合并 <code>grab</code> 与 <code>retrieve</code>；多相机同步时可先分别 <code>grab</code> 再 <code>retrieve</code>。</li><li>属性是后端能力请求，不保证 <code>set</code> 成功，也不保证读取值等于请求值。</li><li>帧通常输出 BGR，但原始模式、深度相机和硬件解码可能返回其他布局。</li><li>FPS、帧号和时间戳在可变帧率、实时流及某些容器上可能不精确。</li><li><code>fourcc</code>、封装格式、编码器和像素格式是不同概念。</li><li>FFmpeg、GStreamer、V4L2、MSMF、AVFoundation 等是否可用由构建和运行环境共同决定。</li><li>硬件加速需要后端、设备和编解码器三方同时支持，不能只设置一个属性。</li><li>误区：用无限阻塞的 <code>read</code> 充当可靠超时机制；实时系统应设计中断与重连。</li><li>推荐入口：<code>modules/videoio/include/opencv2/videoio.hpp</code>、<code>cap.cpp</code>、<code>videoio_registry.cpp</code>。</li></ul><h2 id="6-highgui：窗口、事件与轻量交互"><a href="#6-highgui：窗口、事件与轻量交互" class="headerlink" title="6. highgui：窗口、事件与轻量交互"></a>6. highgui：窗口、事件与轻量交互</h2><h3 id="6-1-定位与公开-API"><a href="#6-1-定位与公开-API" class="headerlink" title="6.1 定位与公开 API"></a>6.1 定位与公开 API</h3><p><code>highgui</code> 提供调试和轻量工具所需的窗口、键鼠事件、轨迹条和按钮接口。<br>主要 API 是 <code>namedWindow</code>、<code>imshow</code>、<code>waitKey</code>、<code>waitKeyEx</code>、<code>pollKey</code>、<code>destroyWindow</code>。<br>交互 API 包括 <code>setMouseCallback</code>、<code>createTrackbar</code>、<code>setTrackbarPos</code>、<code>selectROI</code>。<br>它不是完整 GUI 应用框架，也不负责图像编解码。</p><h3 id="6-2-内部子系统与主要源码"><a href="#6-2-内部子系统与主要源码" class="headerlink" title="6.2 内部子系统与主要源码"></a>6.2 内部子系统与主要源码</h3><ul><li><code>modules/highgui/src/window.cpp</code>：公共窗口 API 与兼容逻辑。</li><li><code>modules/highgui/src/backend.cpp</code>：现代 UI 后端抽象和选择。</li><li><code>modules/highgui/src/window_gtk.cpp</code>、<code>window_QT.cpp</code>：GTK 与 Qt 实现。</li><li><code>modules/highgui/src/window_w32.cpp</code>、<code>window_wayland.cpp</code>：Windows 与 Wayland 实现。</li><li><code>modules/highgui/src/window_cocoa.mm</code>：macOS Cocoa 实现。</li></ul><h3 id="6-3-约束、执行与误区"><a href="#6-3-约束、执行与误区" class="headerlink" title="6.3 约束、执行与误区"></a>6.3 约束、执行与误区</h3><ul><li><code>imshow</code> 负责显示转换，但不同深度的映射规则不同；定量检查前应显式归一化。</li><li><code>waitKey</code> 不只是等待按键，也驱动多数后端的事件处理。</li><li>键码高位具有后端差异；需要完整键码时使用 <code>waitKeyEx</code>。</li><li>GUI API 通常要求在主线程或固定 UI 线程调用，跨线程行为依平台而异。</li><li>无显示服务器、容器或精简构建中，窗口后端可能不可用。</li><li>OpenGL 窗口能力受构建选项和上下文支持影响。</li><li>误区：在生产服务端依赖 <code>imshow</code>；应把可视化与核心计算解耦。</li><li>误区：在回调中做长耗时计算，阻塞整个事件循环。</li><li>推荐入口：<code>modules/highgui/include/opencv2/highgui.hpp</code>、<code>window.cpp</code>、<code>backend.cpp</code>。</li></ul><h2 id="7-features2d：局部特征检测、描述与匹配"><a href="#7-features2d：局部特征检测、描述与匹配" class="headerlink" title="7. features2d：局部特征检测、描述与匹配"></a>7. features2d：局部特征检测、描述与匹配</h2><h3 id="7-1-定位与关键-API"><a href="#7-1-定位与关键-API" class="headerlink" title="7.1 定位与关键 API"></a>7.1 定位与关键 API</h3><p><code>features2d</code> 统一二维关键点、描述子及匹配器，是配准、检索、SLAM 前端和拼接的基础。<br>抽象基类 <code>Feature2D</code> 提供 <code>detect</code>、<code>compute</code>、<code>detectAndCompute</code>。<br>检测与描述实现包括 <code>SIFT</code>、<code>ORB</code>、<code>BRISK</code>、<code>KAZE</code>、<code>AKAZE</code>。<br>检测器还包括 <code>FastFeatureDetector</code>、<code>AgastFeatureDetector</code>、<code>GFTTDetector</code>、<code>MSER</code>、<code>SimpleBlobDetector</code>。<br>匹配抽象为 <code>DescriptorMatcher</code>，常用实现是 <code>BFMatcher</code> 和 <code>FlannBasedMatcher</code>。<br>辅助接口包括 <code>KeyPoint</code>、<code>DMatch</code>、<code>drawKeypoints</code>、<code>drawMatches</code>、<code>KeyPointsFilter</code>。<br>词袋接口包括 <code>BOWTrainer</code>、<code>BOWKMeansTrainer</code>、<code>BOWImgDescriptorExtractor</code>。</p><h3 id="7-2-内部子系统与主要源码"><a href="#7-2-内部子系统与主要源码" class="headerlink" title="7.2 内部子系统与主要源码"></a>7.2 内部子系统与主要源码</h3><ul><li><code>modules/features2d/src/feature2d.cpp</code>：统一接口、序列化和工厂相关逻辑。</li><li><code>modules/features2d/src/sift.dispatch.cpp</code>、<code>orb.cpp</code>、<code>brisk.cpp</code>：主要特征实现。</li><li><code>modules/features2d/src/kaze/</code>、<code>akaze.cpp</code>：非线性尺度空间特征。</li><li><code>modules/features2d/src/fast.cpp</code>、<code>agast.cpp</code>、<code>gftt.cpp</code>：角点检测。</li><li><code>modules/features2d/src/matchers.cpp</code>：暴力与 FLANN 匹配适配。</li><li><code>modules/features2d/src/draw.cpp</code>：关键点和匹配可视化。</li><li><code>modules/features2d/src/bagofwords.cpp</code>：视觉词袋。</li></ul><h3 id="7-3-输入输出约束与执行特点"><a href="#7-3-输入输出约束与执行特点" class="headerlink" title="7.3 输入输出约束与执行特点"></a>7.3 输入输出约束与执行特点</h3><ul><li>输入图像通常应为单通道 8 位；部分实现会接受彩色后内部转换，但不应依赖隐式行为。</li><li>掩码应为与图像同尺寸的 8 位单通道矩阵。</li><li>SIFT、KAZE 描述子通常为浮点向量，适配 L2 距离。</li><li>ORB、BRISK、AKAZE 的二进制描述子通常适配 Hamming 距离。</li><li><code>KeyPoint::size</code> 是特征尺度直径，不是半径；<code>angle=-1</code> 表示未计算方向。</li><li><code>knnMatch</code> 可能为某些查询返回少于 k 个候选，使用 Lowe 比率前必须检查长度。</li><li><code>crossCheck</code> 与 KNN 比率测试是不同筛选策略。</li><li>特征提取常受图像金字塔、阈值、最大特征数和边缘区域配置影响。</li></ul><h3 id="7-4-常见误区与阅读入口"><a href="#7-4-常见误区与阅读入口" class="headerlink" title="7.4 常见误区与阅读入口"></a>7.4 常见误区与阅读入口</h3><ul><li>误区：把二进制描述子转换为 <code>CV_32F</code> 后用 KD-Tree，语义已被破坏。</li><li>误区：仅凭描述子距离接受匹配；几何任务还应使用单应或基础矩阵做鲁棒验证。</li><li>误区：把关键点顺序当作跨帧稳定 ID；检测结果没有这种保证。</li><li>推荐入口：<code>modules/features2d/include/opencv2/features2d.hpp</code>。</li><li>实现阅读可从 <code>feature2d.cpp</code>、具体算法文件、<code>matchers.cpp</code> 串联。</li></ul><h2 id="8-flann：近似最近邻索引"><a href="#8-flann：近似最近邻索引" class="headerlink" title="8. flann：近似最近邻索引"></a>8. flann：近似最近邻索引</h2><h3 id="8-1-定位与关键-API"><a href="#8-1-定位与关键-API" class="headerlink" title="8.1 定位与关键 API"></a>8.1 定位与关键 API</h3><p><code>flann</code> 提供高维数据近似最近邻搜索，既可直接使用，也被 <code>FlannBasedMatcher</code> 调用。<br>公开门面是 <code>cv::flann::Index</code>。<br>索引参数包括 <code>KDTreeIndexParams</code>、<code>KMeansIndexParams</code>、<code>CompositeIndexParams</code>、<code>LshIndexParams</code>。<br>搜索参数由 <code>SearchParams</code> 控制检查次数、近似精度和排序行为。<br>核心操作是 <code>build</code>、<code>knnSearch</code>、<code>radiusSearch</code>、<code>save</code>、<code>load</code>。</p><h3 id="8-2-内部子系统与主要源码"><a href="#8-2-内部子系统与主要源码" class="headerlink" title="8.2 内部子系统与主要源码"></a>8.2 内部子系统与主要源码</h3><ul><li><code>modules/flann/include/opencv2/flann/miniflann.hpp</code>：OpenCV 风格的公开包装。</li><li><code>modules/flann/include/opencv2/flann/</code>：索引、距离、矩阵和序列化模板实现。</li><li><code>modules/flann/src/miniflann.cpp</code>：<code>Mat</code> 与模板 FLANN 的桥接。</li><li><code>modules/flann/src/flann.cpp</code>：C 接口和公共实现汇集。</li></ul><h3 id="8-3-约束、执行与误区"><a href="#8-3-约束、执行与误区" class="headerlink" title="8.3 约束、执行与误区"></a>8.3 约束、执行与误区</h3><ul><li>KD-Tree 等常规索引主要面向 <code>CV_32F</code> 特征和欧氏类距离。</li><li>LSH 面向二进制描述子；距离和索引类型必须与描述子语义一致。</li><li>近似搜索以速度换召回率，<code>checks</code> 越大通常越接近精确结果。</li><li>建索引有时间和内存成本，适合被多次查询的数据集。</li><li>被索引数据的生命周期和连续性必须满足包装层要求，修改数据后应重建索引。</li><li>误区：把 FLANN 结果当确定性全排序；近似算法、随机种子和并行可能影响候选。</li><li>推荐入口：<code>miniflann.hpp</code>、<code>miniflann.cpp</code>，再进入对应索引模板头。</li></ul><h2 id="9-calib3d：相机标定与多视图几何"><a href="#9-calib3d：相机标定与多视图几何" class="headerlink" title="9. calib3d：相机标定与多视图几何"></a>9. calib3d：相机标定与多视图几何</h2><h3 id="9-1-定位与关键-API"><a href="#9-1-定位与关键-API" class="headerlink" title="9.1 定位与关键 API"></a>9.1 定位与关键 API</h3><p><code>calib3d</code> 处理三维视觉中的相机模型、位姿、极几何、三角化和立体匹配。<br>标定 API 包括 <code>calibrateCamera</code>、<code>calibrateCameraRO</code>、<code>stereoCalibrate</code> 和 <code>fisheye</code> 命名空间。<br>位姿 API 包括 <code>solvePnP</code>、<code>solvePnPRansac</code>、<code>solvePnPGeneric</code>、<code>recoverPose</code>。<br>几何估计包括 <code>findHomography</code>、<code>findFundamentalMat</code>、<code>findEssentialMat</code>。<br>校正与投影包括 <code>undistort</code>、<code>initUndistortRectifyMap</code>、<code>stereoRectify</code>、<code>triangulatePoints</code>。<br>立体匹配类包括 <code>StereoMatcher</code>、<code>StereoBM</code>、<code>StereoSGBM</code>。<br>标定靶检测包括 <code>findChessboardCorners</code>、<code>findChessboardCornersSB</code> 和圆点阵接口。</p><h3 id="9-2-内部子系统与主要源码"><a href="#9-2-内部子系统与主要源码" class="headerlink" title="9.2 内部子系统与主要源码"></a>9.2 内部子系统与主要源码</h3><ul><li><code>modules/calib3d/src/calibration.cpp</code>：针孔相机标定与优化。</li><li><code>modules/calib3d/src/fisheye.cpp</code>：鱼眼模型。</li><li><code>modules/calib3d/src/solvepnp.cpp</code>、<code>p3p.cpp</code>、<code>ap3p.cpp</code>、<code>sqpnp.cpp</code>：PnP 算法族。</li><li><code>modules/calib3d/src/fundam.cpp</code>：单应、基础矩阵和本质矩阵入口。</li><li><code>modules/calib3d/src/usac/</code>：USAC 鲁棒估计框架。</li><li><code>modules/calib3d/src/stereo_geom.cpp</code>、<code>stereosgbm.cpp</code>、<code>stereobm.cpp</code>：双目几何与匹配。</li><li><code>modules/calib3d/src/undistort.dispatch.cpp</code>：去畸变映射。</li><li><code>modules/calib3d/src/triangulate.cpp</code>：三角化。</li><li><code>modules/calib3d/src/chessboard.cpp</code>：棋盘格检测。</li></ul><h3 id="9-3-输入输出约束"><a href="#9-3-输入输出约束" class="headerlink" title="9.3 输入输出约束"></a>9.3 输入输出约束</h3><ul><li>世界点与图像点必须一一对应；单位可自定，但平移向量继承同一单位。</li><li>相机矩阵通常为 3×3 浮点矩阵，畸变系数长度由模型和标志决定。</li><li><code>rvec</code> 是 Rodrigues 旋转向量，不是欧拉角；可用 <code>Rodrigues</code> 转换。</li><li><code>solvePnP</code> 不同方法对点数、共面性和初值有不同要求。</li><li><code>findEssentialMat</code>、<code>recoverPose</code> 要求相机归一化关系一致。</li><li><code>StereoBM</code>、<code>StereoSGBM</code> 的视差通常为定点缩放值，解释前应查看输出类型和比例。</li><li>三角化输出是齐次坐标，必须除以最后一维并检查数值稳定性。</li></ul><h3 id="9-4-执行特点、误区与阅读入口"><a href="#9-4-执行特点、误区与阅读入口" class="headerlink" title="9.4 执行特点、误区与阅读入口"></a>9.4 执行特点、误区与阅读入口</h3><ul><li>RANSAC&#x2F;USAC 的阈值处于输入坐标单位中；缩放图像后阈值也应调整。</li><li>标定是非线性优化，初值、姿态覆盖、观测噪声和参数约束决定可观测性。</li><li>误区：仅看整体重投影 RMS 判断标定质量；还应检查每视图误差和参数合理性。</li><li>误区：混淆相机到世界与世界到相机变换，导致旋转和平移方向颠倒。</li><li>误区：用单应矩阵解释有明显视差的非平面场景。</li><li>推荐入口：<code>modules/calib3d/include/opencv2/calib3d.hpp</code>、<code>calibration.cpp</code>、<code>fundam.cpp</code>。</li></ul><h2 id="10-video：跨帧运动分析与跟踪"><a href="#10-video：跨帧运动分析与跟踪" class="headerlink" title="10. video：跨帧运动分析与跟踪"></a>10. video：跨帧运动分析与跟踪</h2><h3 id="10-1-定位与关键-API"><a href="#10-1-定位与关键-API" class="headerlink" title="10.1 定位与关键 API"></a>10.1 定位与关键 API</h3><p><code>video</code> 负责跨帧算法，不负责读取和写入媒体。<br>光流 API 包括 <code>calcOpticalFlowPyrLK</code>、<code>calcOpticalFlowFarneback</code> 和 <code>readOpticalFlow</code>。<br>抽象与实现包括 <code>SparseOpticalFlow</code>、<code>DenseOpticalFlow</code>、<code>FarnebackOpticalFlow</code>、<code>DISOpticalFlow</code>。<br>背景建模包括 <code>BackgroundSubtractorMOG2</code>、<code>BackgroundSubtractorKNN</code> 及创建函数。<br>状态估计使用 <code>KalmanFilter</code>。<br>目标跟踪包括 <code>Tracker</code>、<code>TrackerMIL</code>、<code>TrackerGOTURN</code>、<code>TrackerDaSiamRPN</code>、<code>TrackerNano</code>、<code>TrackerVit</code>。<br>区域跟踪还包括 <code>meanShift</code>、<code>CamShift</code>。</p><h3 id="10-2-内部子系统与主要源码"><a href="#10-2-内部子系统与主要源码" class="headerlink" title="10.2 内部子系统与主要源码"></a>10.2 内部子系统与主要源码</h3><ul><li><code>modules/video/src/lkpyramid.cpp</code>：金字塔 Lucas–Kanade 稀疏光流。</li><li><code>modules/video/src/optflowgf.cpp</code>、<code>dis_flow.cpp</code>：Farneback 与 DIS 稠密光流。</li><li><code>modules/video/src/bgfg_gaussmix2.cpp</code>、<code>bgfg_KNN.cpp</code>：背景模型。</li><li><code>modules/video/src/kalman.cpp</code>：卡尔曼滤波。</li><li><code>modules/video/src/camshift.cpp</code>：MeanShift 与 CamShift。</li><li><code>modules/video/src/tracking/</code>：统一 Tracker 及具体实现。</li><li><code>modules/video/src/optical_flow_io.cpp</code>：<code>.flo</code> 光流文件读写。</li></ul><h3 id="10-3-约束、执行与误区"><a href="#10-3-约束、执行与误区" class="headerlink" title="10.3 约束、执行与误区"></a>10.3 约束、执行与误区</h3><ul><li>LK 光流输入点通常是 <code>Point2f</code>，状态向量标识每个点是否成功。</li><li>前后向一致性检查可剔除遮挡、越界和不稳定轨迹。</li><li>稠密光流输出通常为双通道 <code>CV_32F</code>，分别表示 x、y 位移。</li><li>背景减除器是有状态对象，学习率和历史长度会改变适应速度。</li><li>Kalman 状态、观测和控制矩阵的维度必须由调用方正确建模。</li><li>深度跟踪器可能依赖外部模型文件，且预处理尺寸和模型结构固定。</li><li>误区：把 <code>videoio</code> 的丢帧归因于光流；采集和分析应分别测量。</li><li>推荐入口：<code>modules/video/include/opencv2/video/tracking.hpp</code>、<code>background_segm.hpp</code>。</li></ul><h2 id="11-dnn：深度神经网络推理"><a href="#11-dnn：深度神经网络推理" class="headerlink" title="11. dnn：深度神经网络推理"></a>11. dnn：深度神经网络推理</h2><h3 id="11-1-定位与关键-API"><a href="#11-1-定位与关键-API" class="headerlink" title="11.1 定位与关键 API"></a>11.1 定位与关键 API</h3><p><code>dnn</code> 导入训练好的网络并执行推理，不提供通用训练框架。<br>核心对象是 <code>cv::dnn::Net</code>、<code>Layer</code>、<code>LayerParams</code> 和 <code>LayerFactory</code>。<br>模型导入入口包括 <code>readNet</code>、<code>readNetFromONNX</code>、<code>readNetFromTensorflow</code>、<code>readNetFromDarknet</code>。<br>预处理包括 <code>blobFromImage</code>、<code>blobFromImages</code>、<code>Image2BlobParams</code>。<br>执行包括 <code>setInput</code>、<code>forward</code>、<code>forwardAsync</code>、<code>getUnconnectedOutLayersNames</code>。<br>部署配置包括 <code>setPreferableBackend</code>、<code>setPreferableTarget</code>。<br>后处理包括 <code>NMSBoxes</code>、<code>NMSBoxesBatched</code>、<code>softNMSBoxes</code>。<br>高层包装包括 <code>Model</code>、<code>ClassificationModel</code>、<code>DetectionModel</code>、<code>SegmentationModel</code>、<code>KeypointsModel</code>。</p><h3 id="11-2-内部子系统与主要源码"><a href="#11-2-内部子系统与主要源码" class="headerlink" title="11.2 内部子系统与主要源码"></a>11.2 内部子系统与主要源码</h3><ul><li><code>modules/dnn/src/net.cpp</code>、<code>net_impl.cpp</code>：公开门面、网络状态和执行计划。</li><li><code>modules/dnn/src/net_impl_fuse.cpp</code>：层融合与图优化。</li><li><code>modules/dnn/src/net_impl_backend.cpp</code>：后端初始化和节点映射。</li><li><code>modules/dnn/src/layers/</code>：卷积、池化、激活、注意力等 CPU 层实现。</li><li><code>modules/dnn/src/onnx/</code>、<code>tensorflow/</code>、<code>darknet/</code>：模型解析与图转换。</li><li><code>modules/dnn/src/ocl4dnn/</code>、<code>opencl/</code>：OpenCL 加速。</li><li><code>modules/dnn/src/cuda4dnn/</code>、<code>cuda/</code>：CUDA 后端。</li><li><code>modules/dnn/src/net_openvino.cpp</code>、<code>op_vkcom.cpp</code>、<code>op_webnn.cpp</code>：可选后端桥接。</li><li><code>modules/dnn/src/nms.cpp</code>：检测框抑制。</li></ul><h3 id="11-3-输入输出约束"><a href="#11-3-输入输出约束" class="headerlink" title="11.3 输入输出约束"></a>11.3 输入输出约束</h3><ul><li>blob 常为 NCHW，但实际输入名、维度、动态形状和数据类型由模型决定。</li><li><code>blobFromImage</code> 的缩放、均值、通道交换和裁剪顺序必须匹配训练预处理。</li><li>检测输出布局不是统一标准，高层 <code>DetectionModel</code> 也不能覆盖所有自定义模型。</li><li><code>Net</code> 的输入缓冲和执行状态不应在无同步保护下被多个线程共享修改。</li><li>动态形状、量化算子和控制流支持取决于导入器和目标后端。</li><li><code>forward</code> 返回的数据只代表指定输出层；多输出网络应显式请求输出名称。</li></ul><h3 id="11-4-执行特点、误区与阅读入口"><a href="#11-4-执行特点、误区与阅读入口" class="headerlink" title="11.4 执行特点、误区与阅读入口"></a>11.4 执行特点、误区与阅读入口</h3><ul><li>可选后端包括 OpenCV CPU、OpenCL、CUDA、OpenVINO 等，实际集合由构建决定。</li><li>后端不支持的层可能回退、拒绝执行或导致分图，必须通过日志和性能剖析确认。</li><li>FP16、INT8 能否生效取决于模型、设备、目标和层覆盖率。</li><li>首次推理可能包含图初始化、权重转换和内核编译，不宜直接作为稳态延迟。</li><li>误区：只改 <code>swapRB</code> 便认为预处理正确；还需核对 resize、letterbox、归一化和布局。</li><li>误区：把 NMS 阈值与分类置信阈值混为一谈。</li><li>推荐入口：<code>modules/dnn/include/opencv2/dnn/dnn.hpp</code>、<code>net_impl.cpp</code>、对应导入器目录。</li></ul><h2 id="12-stitching：全景拼接流水线"><a href="#12-stitching：全景拼接流水线" class="headerlink" title="12. stitching：全景拼接流水线"></a>12. stitching：全景拼接流水线</h2><h3 id="12-1-定位与关键-API"><a href="#12-1-定位与关键-API" class="headerlink" title="12.1 定位与关键 API"></a>12.1 定位与关键 API</h3><p><code>stitching</code> 将特征、几何估计、投影、曝光、接缝和融合组织为完整全景管线。<br>高层入口是 <code>Stitcher::create</code>、<code>estimateTransform</code>、<code>composePanorama</code>、<code>stitch</code>。<br>模式包括面向旋转相机的 <code>PANORAMA</code> 和面向扫描件的 <code>SCANS</code>。<br>细节层公开 <code>ImageFeatures</code>、<code>MatchesInfo</code>、<code>CameraParams</code>。<br>匹配器包括 <code>FeaturesMatcher</code>、<code>BestOf2NearestMatcher</code>。<br>运动估计包括 <code>HomographyBasedEstimator</code>、<code>AffineBasedEstimator</code> 和多种 <code>BundleAdjuster</code>。<br>投影、曝光、接缝、融合分别由 <code>RotationWarper</code>、<code>ExposureCompensator</code>、<code>SeamFinder</code>、<code>Blender</code> 抽象。</p><h3 id="12-2-内部子系统与主要源码"><a href="#12-2-内部子系统与主要源码" class="headerlink" title="12.2 内部子系统与主要源码"></a>12.2 内部子系统与主要源码</h3><ul><li><code>modules/stitching/src/stitcher.cpp</code>：高层状态机和阶段编排。</li><li><code>modules/stitching/src/matchers.cpp</code>：图像对匹配和置信度。</li><li><code>modules/stitching/src/motion_estimators.cpp</code>：相机估计与光束法平差。</li><li><code>modules/stitching/src/warpers.cpp</code>：平面、柱面、球面等投影。</li><li><code>modules/stitching/src/exposure_compensate.cpp</code>：增益和分块曝光补偿。</li><li><code>modules/stitching/src/seam_finders.cpp</code>：动态规划、图割等接缝。</li><li><code>modules/stitching/src/blenders.cpp</code>：羽化和多频带融合。</li><li><code>modules/stitching/src/autocalib.cpp</code>：波形校正与自动标定辅助。</li></ul><h3 id="12-3-约束、执行与误区"><a href="#12-3-约束、执行与误区" class="headerlink" title="12.3 约束、执行与误区"></a>12.3 约束、执行与误区</h3><ul><li>输入图像需要足够重叠和可重复纹理；纯色、重复纹理和运动物体会降低可靠性。</li><li>工作分辨率、接缝分辨率和合成分辨率是三套尺度，应保持坐标换算一致。</li><li><code>PANORAMA</code> 主要假设相机绕光心旋转；明显平移和近景视差会破坏单应模型。</li><li>多频带融合质量较高但内存和时间开销大。</li><li>CUDA&#x2F;OpenCL 只覆盖部分投影或融合路径，不能假定整条流水线都在设备端。</li><li>误区：增加所有图像总能改善结果；错误边会污染匹配图和相机估计。</li><li>误区：只调整融合器掩盖几何错位；应先检查匹配内点与相机参数。</li><li>推荐入口：<code>modules/stitching/include/opencv2/stitching.hpp</code>、<code>stitcher.cpp</code>，再深入 <code>detail/</code>。</li></ul><h2 id="13-ml：传统机器学习"><a href="#13-ml：传统机器学习" class="headerlink" title="13. ml：传统机器学习"></a>13. ml：传统机器学习</h2><h3 id="13-1-定位与关键-API"><a href="#13-1-定位与关键-API" class="headerlink" title="13.1 定位与关键 API"></a>13.1 定位与关键 API</h3><p><code>ml</code> 提供基于 <code>Mat</code> 的传统监督与无监督学习，适合中小规模结构化特征。<br>统一基类是 <code>StatModel</code>，数据包装为 <code>TrainData</code>，超参数搜索辅助为 <code>ParamGrid</code>。<br>算法包括 <code>NormalBayesClassifier</code>、<code>KNearest</code>、<code>SVM</code>、<code>EM</code>。<br>树模型包括 <code>DTrees</code>、<code>RTrees</code>、<code>Boost</code>。<br>神经与线性模型包括 <code>ANN_MLP</code>、<code>LogisticRegression</code>、<code>SVMSGD</code>。<br>通用接口为 <code>train</code>、<code>predict</code>、<code>save</code>、<code>load</code>、<code>isTrained</code>。</p><h3 id="13-2-内部子系统与主要源码"><a href="#13-2-内部子系统与主要源码" class="headerlink" title="13.2 内部子系统与主要源码"></a>13.2 内部子系统与主要源码</h3><ul><li><code>modules/ml/src/data.cpp</code>：样本布局、训练&#x2F;测试划分与变量类型。</li><li><code>modules/ml/src/svm.cpp</code>、<code>svmsgd.cpp</code>：核 SVM 与随机梯度版本。</li><li><code>modules/ml/src/tree.cpp</code>、<code>rtrees.cpp</code>、<code>boost.cpp</code>：树模型族。</li><li><code>modules/ml/src/knearest.cpp</code>、<code>nbayes.cpp</code>、<code>em.cpp</code>：经典统计模型。</li><li><code>modules/ml/src/ann_mlp.cpp</code>、<code>lr.cpp</code>：多层感知机和逻辑回归。</li><li><code>modules/ml/src/inner_functions.cpp</code>：共享数值辅助。</li></ul><h3 id="13-3-约束、执行与误区"><a href="#13-3-约束、执行与误区" class="headerlink" title="13.3 约束、执行与误区"></a>13.3 约束、执行与误区</h3><ul><li>默认样本布局常为每行一个样本；必须用 <code>ROW_SAMPLE</code> 或 <code>COL_SAMPLE</code> 明确表达。</li><li>特征通常需转换为 <code>CV_32F</code>；类别标签和回归响应的类型、形状要匹配算法。</li><li>类别变量必须通过 <code>TrainData</code> 的变量类型正确标记。</li><li>缺失值、类别编码、归一化和特征缩放不会自动按业务语义处理。</li><li>训练多在 CPU 完成，并非 <code>UMat</code> 或 GPU 训练框架。</li><li>模型文件应与 OpenCV 版本和算法参数共同纳入部署验证。</li><li>误区：在全量数据上调参后报告同一数据的准确率；必须保留独立验证集。</li><li>推荐入口：<code>modules/ml/include/opencv2/ml.hpp</code>、<code>data.cpp</code> 和目标算法实现文件。</li></ul><h2 id="14-gapi：图计算与流式执行"><a href="#14-gapi：图计算与流式执行" class="headerlink" title="14. gapi：图计算与流式执行"></a>14. gapi：图计算与流式执行</h2><h3 id="14-1-定位与关键-API"><a href="#14-1-定位与关键-API" class="headerlink" title="14.1 定位与关键 API"></a>14.1 定位与关键 API</h3><p><code>gapi</code> 用声明式图描述计算，再将图编译到一个或多个执行后端。<br>图数据类型包括 <code>GMat</code>、<code>GScalar</code>、<code>GArray</code>、<code>GOpaque</code>、<code>GFrame</code>。<br><code>GComputation</code> 表示输入到输出的计算图，可通过 <code>compile</code> 或 <code>apply</code> 执行。<br><code>GCompiled</code> 是普通编译结果，<code>GStreamingCompiled</code> 面向持续数据源。<br>算子元信息由 <code>GMetaArg</code>、<code>GMatDesc</code> 等描述。<br>自定义算子使用 <code>G_API_OP</code>，实现通过 CPU、Fluid、OpenCL 等 kernel package 提供。<br>编译参数可组合 kernel、网络推理参数、队列和流式策略。</p><h3 id="14-2-内部子系统与主要源码"><a href="#14-2-内部子系统与主要源码" class="headerlink" title="14.2 内部子系统与主要源码"></a>14.2 内部子系统与主要源码</h3><ul><li><code>modules/gapi/src/api/</code>：图节点、调用、数据对象和 <code>GComputation</code> 公共实现。</li><li><code>modules/gapi/src/compiler/</code>：图模型构建、元信息传播、岛划分和编译 Pass。</li><li><code>modules/gapi/src/executor/</code>：普通与流式执行器、队列和线程调度。</li><li><code>modules/gapi/src/backends/cpu/</code>：基于 OpenCV CPU 函数的 kernel。</li><li><code>modules/gapi/src/backends/fluid/</code>：面向缓存行和低内存占用的 Fluid 后端。</li><li><code>modules/gapi/src/backends/ocl/</code>：OpenCL kernel。</li><li><code>modules/gapi/src/backends/streaming/</code>：流式 kernel 支持。</li><li><code>modules/gapi/src/streaming/</code>：媒体源、GStreamer、oneVPL 等接入。</li><li><code>modules/gapi/src/backends/ov/</code>、<code>onnx/</code>：推理后端桥接。</li></ul><h3 id="14-3-约束、执行与误区"><a href="#14-3-约束、执行与误区" class="headerlink" title="14.3 约束、执行与误区"></a>14.3 约束、执行与误区</h3><ul><li>构图阶段操作的是符号对象，不会立即处理像素。</li><li>编译需要输入元信息；尺寸、类型变化超出已编译描述时通常需要重新编译。</li><li>每个图算子都必须在提供的 kernel package 中有可用实现。</li><li>后端划分按“岛”执行，跨岛可能发生数据适配和同步。</li><li>Fluid 优势来自流水化和缓存局部性，不等价于一般 CPU kernel 的逐算子加速。</li><li>流式模式需要管理启动、拉取、停止和背压，不是简单的循环 <code>apply</code>。</li><li>误区：认为任意现有 <code>cv::</code> 函数会自动进入 G-API 图；必须有对应 G-API 操作与 kernel。</li><li>推荐入口：<code>modules/gapi/include/opencv2/gapi.hpp</code>、<code>src/api/gcomputation.cpp</code>、<code>src/compiler/</code>。</li></ul><h2 id="15-ts：OpenCV-自身测试基础设施"><a href="#15-ts：OpenCV-自身测试基础设施" class="headerlink" title="15. ts：OpenCV 自身测试基础设施"></a>15. ts：OpenCV 自身测试基础设施</h2><h3 id="15-1-定位与关键-API"><a href="#15-1-定位与关键-API" class="headerlink" title="15.1 定位与关键 API"></a>15.1 定位与关键 API</h3><p><code>ts</code> 是 OpenCV 模块测试和性能测试的公共支撑，不是业务算法库。<br>公开头聚合在 <code>modules/ts/include/opencv2/ts.hpp</code>。<br>它提供测试基类、随机数据生成、矩阵比较、测试数据路径、标签和性能计时工具。<br>功能测试依赖 GoogleTest 风格基础设施，性能测试使用 OpenCV 的 perf 宏和运行器。</p><h3 id="15-2-内部子系统与主要源码"><a href="#15-2-内部子系统与主要源码" class="headerlink" title="15.2 内部子系统与主要源码"></a>15.2 内部子系统与主要源码</h3><ul><li><code>modules/ts/src/ts.cpp</code>、<code>ts_func.cpp</code>：测试上下文与通用辅助。</li><li><code>modules/ts/src/ts_arrtest.cpp</code>：数组算法测试基类和误差验证。</li><li><code>modules/ts/src/ts_gtest.cpp</code>：测试框架集成。</li><li><code>modules/ts/src/ts_perf.cpp</code>：性能测试运行与统计。</li><li><code>modules/ts/src/ts_tags.cpp</code>：测试标签过滤。</li><li><code>modules/ts/src/ocl_test.cpp</code>、<code>cuda_test.cpp</code>：设备测试辅助。</li></ul><h3 id="15-3-约束、误区与阅读入口"><a href="#15-3-约束、误区与阅读入口" class="headerlink" title="15.3 约束、误区与阅读入口"></a>15.3 约束、误区与阅读入口</h3><ul><li>测试数据根目录需要显式配置，不能依赖开发机的绝对路径。</li><li>数值比较应根据算法、深度和后端选择绝对或相对误差。</li><li>性能用例应预热并由框架控制迭代，避免把初始化成本混入稳态数据。</li><li>误区：应用程序链接 <code>ts</code> 来获得通用工具；这些接口主要服务源码树内测试。</li><li>推荐入口：目标模块 <code>test/</code>、<code>perf/</code> 与 <code>modules/ts/include/opencv2/ts/</code> 对照阅读。</li></ul><h2 id="16-world：单库聚合目标"><a href="#16-world：单库聚合目标" class="headerlink" title="16. world：单库聚合目标"></a>16. world：单库聚合目标</h2><h3 id="16-1-定位与实现方式"><a href="#16-1-定位与实现方式" class="headerlink" title="16.1 定位与实现方式"></a>16.1 定位与实现方式</h3><p><code>world</code> 不是算法模块，而是把当前构建中启用的 OpenCV 模块聚合为单个 <code>opencv_world</code> 库。<br>它的价值是简化部署和链接参数，不改变 API 命名空间、模块语义或运行时后端。<br><code>modules/world/CMakeLists.txt</code> 负责聚合逻辑。<br><code>modules/world/include/opencv2/world.hpp</code> 提供聚合头入口。<br><code>modules/world/src/world_init.cpp</code> 承担生成目标所需的初始化单元。</p><h3 id="16-2-约束、误区与阅读入口"><a href="#16-2-约束、误区与阅读入口" class="headerlink" title="16.2 约束、误区与阅读入口"></a>16.2 约束、误区与阅读入口</h3><ul><li>单库只包含本次构建实际启用且允许聚合的模块。</li><li>外部第三方动态库、插件、模型和系统媒体组件不会因 <code>world</code> 自动静态封装。</li><li>使用单库可能增大链接和发布单元，也可能降低按模块裁剪的清晰度。</li><li>误区：认为 <code>opencv_world</code> 提供额外算法或自动启用所有后端。</li><li>推荐入口：<code>modules/world/CMakeLists.txt</code>，并结合顶层构建生成的模块清单核对。</li></ul><h2 id="17-objdetect：目标、图形码与标记检测"><a href="#17-objdetect：目标、图形码与标记检测" class="headerlink" title="17. objdetect：目标、图形码与标记检测"></a>17. objdetect：目标、图形码与标记检测</h2><h3 id="17-1-定位与关键-API"><a href="#17-1-定位与关键-API" class="headerlink" title="17.1 定位与关键 API"></a>17.1 定位与关键 API</h3><p><code>objdetect</code> 汇集经典目标检测、图形码、ArUco&#x2F;ChArUco 和部分 DNN 模型包装。<br>经典检测包括 <code>CascadeClassifier</code>、<code>HOGDescriptor</code>、<code>groupRectangles</code>。<br>图形码抽象为 <code>GraphicalCodeDetector</code>。<br>二维码接口包括 <code>QRCodeDetector</code>、<code>QRCodeDetectorAruco</code>、<code>QRCodeEncoder</code>。<br>条码接口位于 <code>cv::barcode::BarcodeDetector</code>。<br>标记接口包括 <code>aruco::Dictionary</code>、<code>ArucoDetector</code>、<code>Board</code>、<code>GridBoard</code>。<br>混合标定板使用 <code>CharucoBoard</code> 和 <code>CharucoDetector</code>。<br>人脸 DNN 包装包括 <code>FaceDetectorYN</code> 和 <code>FaceRecognizerSF</code>。</p><h3 id="17-2-内部子系统与主要源码"><a href="#17-2-内部子系统与主要源码" class="headerlink" title="17.2 内部子系统与主要源码"></a>17.2 内部子系统与主要源码</h3><ul><li><code>modules/objdetect/src/cascadedetect.cpp</code>、<code>cascadedetect_convert.cpp</code>：级联检测和旧格式转换。</li><li><code>modules/objdetect/src/hog.cpp</code>：HOG 特征与滑窗检测。</li><li><code>modules/objdetect/src/qrcode.cpp</code>、<code>qrcode_encoder.cpp</code>：二维码检测、解码和编码。</li><li><code>modules/objdetect/src/graphical_code_detector.cpp</code>：图形码公共门面。</li><li><code>modules/objdetect/src/barcode.cpp</code>、<code>barcode_detector/</code>、<code>barcode_decoder/</code>：条码管线。</li><li><code>modules/objdetect/src/aruco/</code>：字典、检测、板和 ChArUco。</li><li><code>modules/objdetect/src/face_detect.cpp</code>、<code>face_recognize.cpp</code>：人脸模型包装。</li><li><code>modules/objdetect/src/opencl/</code>：HOG 和级联检测的部分 OpenCL 内核。</li></ul><h3 id="17-3-约束、执行与误区"><a href="#17-3-约束、执行与误区" class="headerlink" title="17.3 约束、执行与误区"></a>17.3 约束、执行与误区</h3><ul><li>级联分类器必须先成功 <code>load</code>；空分类器不会产生有效检测。</li><li>HOG 的窗口、块、步长和描述子维度必须与检测器权重匹配。</li><li>二维码和条码检测可接受常见灰度或 BGR 图，但清晰度、静区和尺度决定解码率。</li><li>ArUco 字典、标记边长和坐标系定义必须在生成、检测和位姿阶段一致。</li><li><code>FaceDetectorYN</code>、<code>FaceRecognizerSF</code> 依赖外部模型，输入尺寸与归一化由包装接口约束。</li><li>检测结果坐标位于输入图像坐标系，预缩放后需正确映射回原图。</li><li>误区：把人脸相似度阈值跨模型、跨度量直接复用。</li><li>推荐入口：<code>modules/objdetect/include/opencv2/objdetect.hpp</code> 和对应子头，再查同名源码。</li></ul><h2 id="18-photo：计算摄影与图像修复"><a href="#18-photo：计算摄影与图像修复" class="headerlink" title="18. photo：计算摄影与图像修复"></a>18. photo：计算摄影与图像修复</h2><h3 id="18-1-定位与关键-API"><a href="#18-1-定位与关键-API" class="headerlink" title="18.1 定位与关键 API"></a>18.1 定位与关键 API</h3><p><code>photo</code> 提供去噪、修复、HDR、曝光融合、无缝克隆和风格化处理。<br>去噪包括 <code>fastNlMeansDenoising</code>、<code>fastNlMeansDenoisingColored</code>、多帧版本和 <code>denoise_TVL1</code>。<br>修复使用 <code>inpaint</code>，算法标志包括 Telea 与 Navier–Stokes 路径。<br>无缝克隆包括 <code>seamlessClone</code>、<code>colorChange</code>、<code>illuminationChange</code>、<code>textureFlattening</code>。<br>HDR 对齐使用 <code>AlignMTB</code>。<br>相机响应标定使用 <code>CalibrateDebevec</code>、<code>CalibrateRobertson</code>。<br>HDR 合并与曝光融合使用 <code>MergeDebevec</code>、<code>MergeRobertson</code>、<code>MergeMertens</code>。<br>色调映射包括 <code>Tonemap</code>、<code>TonemapDrago</code>、<code>TonemapReinhard</code>、<code>TonemapMantiuk</code>。<br>非真实感渲染包括 <code>edgePreservingFilter</code>、<code>detailEnhance</code>、<code>pencilSketch</code>、<code>stylization</code>。</p><h3 id="18-2-内部子系统与主要源码"><a href="#18-2-内部子系统与主要源码" class="headerlink" title="18.2 内部子系统与主要源码"></a>18.2 内部子系统与主要源码</h3><ul><li><code>modules/photo/src/denoising.cpp</code>、<code>denoise_tvl1.cpp</code>：单帧、多帧去噪。</li><li><code>modules/photo/src/inpaint.cpp</code>：图像修复。</li><li><code>modules/photo/src/seamless_cloning.cpp</code>、<code>seamless_cloning_impl.cpp</code>：泊松融合。</li><li><code>modules/photo/src/align.cpp</code>、<code>calibrate.cpp</code>、<code>merge.cpp</code>：HDR 管线。</li><li><code>modules/photo/src/tonemap.cpp</code>：色调映射。</li><li><code>modules/photo/src/npr.cpp</code>：风格化与细节增强。</li><li><code>modules/photo/src/opencl/nlmeans.cl</code>、<code>cuda/nlm.cu</code>：部分去噪加速。</li></ul><h3 id="18-3-约束、执行与误区"><a href="#18-3-约束、执行与误区" class="headerlink" title="18.3 约束、执行与误区"></a>18.3 约束、执行与误区</h3><ul><li>NLM 参数以像素噪声与搜索窗口为尺度，窗口增大将显著提高计算量。</li><li>多帧去噪要求相邻帧已大致对齐，并正确指定目标帧索引和时间窗口。</li><li><code>inpaint</code> 掩码应为 8 位单通道，非零区域表示待修复像素。</li><li>HDR 辐照度合并通常接收同尺寸曝光序列和对应曝光时间。</li><li><code>MergeMertens</code> 输出融合图而非物理辐照度图，不要求曝光时间。</li><li>色调映射把 HDR 映射到显示范围，输出仍应按目标显示&#x2F;编码格式转换。</li><li>误区：把无缝克隆当通用几何对齐；源图、掩码和目标位置必须先合理配准。</li><li>推荐入口：<code>modules/photo/include/opencv2/photo.hpp</code>，按任务进入 <code>denoising.cpp</code>、<code>merge.cpp</code> 等。</li></ul><h2 id="19-跨模块典型调用链"><a href="#19-跨模块典型调用链" class="headerlink" title="19. 跨模块典型调用链"></a>19. 跨模块典型调用链</h2><h3 id="19-1-静态图像分析"><a href="#19-1-静态图像分析" class="headerlink" title="19.1 静态图像分析"></a>19.1 静态图像分析</h3><ol><li><code>imgcodecs::imread</code> 解码文件，失败时拒绝继续。</li><li><code>core</code> 检查尺寸、类型、连续性和数值范围。</li><li><code>imgproc::cvtColor</code>、<code>resize</code>、滤波或阈值完成预处理。</li><li><code>features2d</code>、<code>objdetect</code>、<code>dnn</code> 或 <code>ml</code> 执行任务算法。</li><li><code>imgproc</code> 绘制结果，<code>imgcodecs::imwrite</code> 编码输出。</li><li>调试时可用 <code>highgui</code> 展示，但生产计算不应依赖窗口事件循环。</li></ol><h3 id="19-2-相机标定与位姿"><a href="#19-2-相机标定与位姿" class="headerlink" title="19.2 相机标定与位姿"></a>19.2 相机标定与位姿</h3><ol><li><code>videoio::VideoCapture</code> 采集帧并记录设备、分辨率和时间信息。</li><li><code>imgproc</code> 转灰度，必要时做适度增强。</li><li><code>calib3d</code> 检测标定靶，<code>cornerSubPix</code> 提升角点精度。</li><li><code>calibrateCamera</code> 或鱼眼接口估计内参与畸变。</li><li><code>initUndistortRectifyMap</code> 生成固定映射，<code>imgproc::remap</code> 在每帧复用。</li><li><code>solvePnP</code> 从三维点和二维观测估计后续位姿。</li></ol><h3 id="19-3-特征配准与全景拼接"><a href="#19-3-特征配准与全景拼接" class="headerlink" title="19.3 特征配准与全景拼接"></a>19.3 特征配准与全景拼接</h3><ol><li><code>imgcodecs</code> 或 <code>videoio</code> 提供图像。</li><li><code>imgproc</code> 统一尺度和颜色。</li><li><code>features2d</code> 检测关键点并生成描述子。</li><li><code>BFMatcher</code> 或 <code>FlannBasedMatcher</code> 产生候选匹配。</li><li><code>calib3d::findHomography</code> 配合 RANSAC&#x2F;USAC 剔除外点。</li><li>简单任务可用 <code>warpPerspective</code>；完整全景交给 <code>stitching</code> 的相机估计、接缝和融合阶段。</li></ol><h3 id="19-4-视频检测与跟踪"><a href="#19-4-视频检测与跟踪" class="headerlink" title="19.4 视频检测与跟踪"></a>19.4 视频检测与跟踪</h3><ol><li><code>videoio</code> 解码或采集，独立线程负责限长队列和重连。</li><li><code>imgproc</code> 完成颜色、尺寸和归一化前处理。</li><li><code>dnn</code> 或 <code>objdetect</code> 周期性给出检测框。</li><li><code>video</code> 的光流、Kalman 或 Tracker 在检测间隔内更新状态。</li><li><code>core</code> 管理时间戳和状态矩阵，业务层负责轨迹关联与生命周期。</li><li><code>videoio::VideoWriter</code> 写出时明确编码器、FPS、帧尺寸和颜色约定。</li></ol><h3 id="19-5-HDR-与计算摄影"><a href="#19-5-HDR-与计算摄影" class="headerlink" title="19.5 HDR 与计算摄影"></a>19.5 HDR 与计算摄影</h3><ol><li><code>imgcodecs</code> 以保持原位深的标志读取曝光序列。</li><li><code>photo::AlignMTB</code> 对齐存在轻微相机移动的图像。</li><li><code>CalibrateCRF</code> 估计响应曲线，<code>MergeDebevec</code> 或 <code>MergeRobertson</code> 合成 HDR。</li><li>或使用 <code>MergeMertens</code> 直接进行曝光融合。</li><li><code>Tonemap</code> 将 HDR 映射到可显示范围。</li><li><code>core</code> 做范围检查和类型转换，<code>imgcodecs</code> 按目标格式编码。</li></ol><h3 id="19-6-G-API-流式管线"><a href="#19-6-G-API-流式管线" class="headerlink" title="19.6 G-API 流式管线"></a>19.6 G-API 流式管线</h3><ol><li>用 <code>GMat</code>、<code>GFrame</code> 等符号数据声明预处理和推理图。</li><li>为输入提供准确元信息和流式数据源。</li><li>组合 CPU、Fluid、OpenCL 或推理 kernel package。</li><li>编译器完成元信息传播、岛划分和执行计划生成。</li><li><code>GStreamingCompiled</code> 管理启动、拉取和停止。</li><li>用端到端吞吐和延迟验证跨后端复制是否抵消融合收益。</li></ol><h2 id="20-二次开发指南"><a href="#20-二次开发指南" class="headerlink" title="20. 二次开发指南"></a>20. 二次开发指南</h2><h3 id="20-1-先选择扩展层级"><a href="#20-1-先选择扩展层级" class="headerlink" title="20.1 先选择扩展层级"></a>20.1 先选择扩展层级</h3><ul><li>仅组合公开 API：最稳定，优先放在应用或独立库中。</li><li>实现 <code>Algorithm</code> 派生类：适合需要统一配置、保存和工厂语义的算法。</li><li>为 G-API 增加操作与 kernel：适合声明式流水线和多后端部署。</li><li>扩展 videoio&#x2F;highgui 后端：需要遵循内部后端接口与插件 ABI，维护成本较高。</li><li>修改模块内部实现：只在确需进入 OpenCV 主源码时采用，并准备跨平台测试。</li><li>新增 HAL&#x2F;SIMD 路径：必须保留标量基线，并证明数值一致性和真实性能收益。</li></ul><h3 id="20-2-API-与数据边界"><a href="#20-2-API-与数据边界" class="headerlink" title="20.2 API 与数据边界"></a>20.2 API 与数据边界</h3><ul><li>公开接口优先使用 <code>InputArray</code>&#x2F;<code>OutputArray</code>，内部尽早解析并验证真实类型。</li><li>对尺寸、通道、深度、连续性、允许原地操作与空输入给出明确契约。</li><li>不缓存短生命周期 <code>Mat</code> 的裸 <code>data</code> 指针。</li><li>对 ROI、非连续矩阵和自定义步长编写专门测试。</li><li>算法参数应有可解释默认值，并检查非法组合。</li><li>序列化模型或配置时记录版本、预处理约定和坐标系。</li></ul><h3 id="20-3-后端与性能"><a href="#20-3-后端与性能" class="headerlink" title="20.3 后端与性能"></a>20.3 后端与性能</h3><ul><li>先建立正确的 CPU 基线，再增加 SIMD、OpenCL、CUDA 或第三方后端。</li><li>把上传、下载、颜色转换和布局变换计入端到端性能。</li><li>复用模型、编译图、索引、映射表和输出缓冲。</li><li>避免在逐帧热路径中反复创建 <code>Net</code>、<code>Stitcher</code>、FLANN 索引或 G-API 编译结果。</li><li>多线程时区分对象只读共享、内部可变状态和后端上下文约束。</li><li>使用模块 <code>perf/</code> 风格覆盖典型尺寸，也测试小输入的调度开销。</li></ul><h3 id="20-4-测试与诊断"><a href="#20-4-测试与诊断" class="headerlink" title="20.4 测试与诊断"></a>20.4 测试与诊断</h3><ul><li>功能测试至少覆盖空输入、最小尺寸、奇数尺寸、ROI、不同深度和多通道。</li><li>数值算法同时检查绝对误差、相对误差和几何不变量。</li><li>鲁棒估计算法固定随机种子后测试，也保留统计性压力测试。</li><li>后端一致性测试不能要求所有浮点位完全相同，应按误差模型设阈值。</li><li>通过 <code>getBuildInformation</code> 记录构建能力，通过 videoio registry 或 DNN 查询确认实际后端。</li><li>遇到性能回退时分别测量初始化、首帧、稳态和数据传输。</li></ul><h3 id="20-5-源码提交前检查"><a href="#20-5-源码提交前检查" class="headerlink" title="20.5 源码提交前检查"></a>20.5 源码提交前检查</h3><ol><li>公共声明是否只放在模块 <code>include/opencv2/</code> 下。</li><li>新实现是否被 <code>CMakeLists.txt</code> 和条件编译正确纳入。</li><li>不可用可选依赖时是否仍能构建并给出明确行为。</li><li>C++ API、Python&#x2F;Java 绑定注解和文档是否一致。</li><li>新增代码是否覆盖标量基线、优化路径和异常路径。</li><li>是否在目标模块 <code>test/</code> 与 <code>perf/</code> 增加对应案例。</li><li>是否避免把机器路径、测试资产位置或外部模型硬编码进源码。</li></ol><h2 id="21-模块选型与阅读路线总结"><a href="#21-模块选型与阅读路线总结" class="headerlink" title="21. 模块选型与阅读路线总结"></a>21. 模块选型与阅读路线总结</h2><ul><li>基础矩阵和运行时问题：从 <code>core</code> 开始。</li><li>静态图像读写与处理：<code>imgcodecs + imgproc + core</code>。</li><li>相机和视频分析：<code>videoio + imgproc + video</code>。</li><li>局部特征与几何：<code>features2d + flann + calib3d</code>。</li><li>深度推理：<code>dnn</code>，并按输入来源搭配 <code>imgcodecs</code> 或 <code>videoio</code>。</li><li>全景：优先使用 <code>stitching</code> 高层接口，诊断时逐层进入 <code>detail</code> 组件。</li><li>传统表格特征学习：使用 <code>ml</code>，把预处理和验证集策略放在模块之外。</li><li>声明式或流式异构图：使用 <code>gapi</code>，先核对 kernel 与后端覆盖。</li><li>图形码、标记和经典检测：使用 <code>objdetect</code>。</li><li>HDR、去噪、修复和融合：使用 <code>photo</code>。</li><li>OpenCV 自身测试扩展：使用 <code>ts</code>；应用代码不应依赖它。</li><li>需要简化链接时选择 <code>world</code>，但仍按原模块理解 API、依赖和运行时行为。</li></ul><p>阅读任何模块时，公开头文件回答“允许怎样使用”，统一入口源码回答“如何分发”，具体算法文件回答“怎样计算”，测试与性能目录回答“边界和代价是什么”。</p>]]>
    </content>
    <id>http://example.com/n/1202/</id>
    <link href="http://example.com/n/1202/"/>
    <published>2026-09-16T03:02:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="OpenCV-4-13-0-核心模块手册"><a href="#OpenCV-4-13-0-核心模块手册" class="headerlink" title="OpenCV 4.13.0 核心模块手册"></a>OpenCV 4.13.0 核心模块手册</h1><]]>
    </summary>
    <title>OpenCV 4.13.0 核心模块手册</title>
    <updated>2026-09-16T03:49:31.692Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="03-核心模块详解"><a href="#03-核心模块详解" class="headerlink" title="03 核心模块详解"></a>03 核心模块详解</h1><h2 id="3-1-models-yolo-py"><a href="#3-1-models-yolo-py" class="headerlink" title="3.1 models/yolo.py"></a>3.1 <code>models/yolo.py</code></h2><h3 id="Detect"><a href="#Detect" class="headerlink" title="Detect"></a><code>Detect</code></h3><p>YOLOv5 检测头。主要成员：</p><table><thead><tr><th>成员</th><th>含义</th></tr></thead><tbody><tr><td><code>nc</code></td><td>类别数</td></tr><tr><td><code>no = nc + 5</code></td><td>每个锚点的输出维度</td></tr><tr><td><code>nl</code></td><td>检测层数量，P5 模型通常为 3</td></tr><tr><td><code>na</code></td><td>每层锚点数，通常为 3</td></tr><tr><td><code>anchors</code></td><td>以网格单位保存的 Anchor</td></tr><tr><td><code>stride</code></td><td>各检测层步长</td></tr><tr><td><code>m</code></td><td>每层一个 1×1 输出卷积</td></tr><tr><td><code>grid</code></td><td>网格中心坐标</td></tr><tr><td><code>anchor_grid</code></td><td>Anchor 的像素尺度</td></tr></tbody></table><p>训练时返回三层原始张量：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[B, na, H, W, nc+5]</span><br></pre></td></tr></table></figure><p>推理时解码并拼接为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[B, 所有候选数, nc+5]</span><br></pre></td></tr></table></figure><h3 id="Segment"><a href="#Segment" class="headerlink" title="Segment"></a><code>Segment</code></h3><p>继承 <code>Detect</code>：</p><ul><li><code>Proto</code> 从高分辨率特征产生共享 mask 原型</li><li>每个候选额外预测 <code>nm</code> 个 mask 系数</li><li>默认 <code>nm=32</code>、<code>npr=256</code></li></ul><h3 id="BaseModel"><a href="#BaseModel" class="headerlink" title="BaseModel"></a><code>BaseModel</code></h3><p>通用能力：</p><ul><li><code>_forward_once()</code>：按 YAML 图执行</li><li><code>_profile_one_layer()</code>：逐层耗时&#x2F;FLOPs</li><li><code>fuse()</code>：Conv+BN 融合</li><li><code>_apply()</code>：迁移 stride&#x2F;grid&#x2F;anchor_grid 到设备或精度</li></ul><h3 id="DetectionModel"><a href="#DetectionModel" class="headerlink" title="DetectionModel"></a><code>DetectionModel</code></h3><p>职责：</p><ol><li>读取模型 YAML</li><li>覆盖 <code>nc</code> 或 anchors</li><li>调用 <code>parse_model</code></li><li>用 256×256 假输入推断 P3&#x2F;P4&#x2F;P5 stride</li><li>检查 Anchor 顺序并归一化</li><li>初始化 Detect bias</li></ol><p>它还支持三尺度 TTA：缩放为 1、0.83、0.67，并做水平翻转后合并结果。</p><h3 id="ClassificationModel"><a href="#ClassificationModel" class="headerlink" title="ClassificationModel"></a><code>ClassificationModel</code></h3><p>可从检测模型截取前若干层作为 backbone，并用 <code>Classify</code> 替换尾部模块。</p><h3 id="parse-model"><a href="#parse-model" class="headerlink" title="parse_model"></a><code>parse_model</code></h3><p>这是读懂 YOLOv5 模型图的核心函数：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">YAML 字典</span><br><span class="line">  → 缩放深度/宽度</span><br><span class="line">  → 计算每层输入输出通道</span><br><span class="line">  → 创建模块</span><br><span class="line">  → 记录 from 索引</span><br><span class="line">  → 生成 nn.Sequential 和 save list</span><br></pre></td></tr></table></figure><h2 id="3-2-models-common-py"><a href="#3-2-models-common-py" class="headerlink" title="3.2 models/common.py"></a>3.2 <code>models/common.py</code></h2><h3 id="基础网络块"><a href="#基础网络块" class="headerlink" title="基础网络块"></a>基础网络块</h3><table><thead><tr><th>类</th><th>作用</th></tr></thead><tbody><tr><td><code>Conv</code></td><td>Conv2d + BatchNorm + SiLU</td></tr><tr><td><code>DWConv</code></td><td>深度&#x2F;分组卷积</td></tr><tr><td><code>Bottleneck</code></td><td>残差瓶颈</td></tr><tr><td><code>C3</code></td><td>CSP 风格双分支与瓶颈堆叠</td></tr><tr><td><code>SPPF</code></td><td>串行 5×5 MaxPool 快速空间金字塔</td></tr><tr><td><code>Concat</code></td><td>通道拼接</td></tr><tr><td><code>Proto</code></td><td>分割原型掩码</td></tr><tr><td><code>Classify</code></td><td>分类头</td></tr></tbody></table><p>YOLOv5s 的主体模块是 <code>Conv + C3 + SPPF</code>。</p><h3 id="DetectMultiBackend"><a href="#DetectMultiBackend" class="headerlink" title="DetectMultiBackend"></a><code>DetectMultiBackend</code></h3><p>它不是网络结构，而是部署适配层。构造函数通过权重后缀判断运行时，并加载：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">.pt / .torchscript / .onnx / .engine / .mlmodel</span><br><span class="line">OpenVINO 模型目录</span><br><span class="line">SavedModel / .pb / .tflite / EdgeTPU</span><br><span class="line">Paddle 模型目录</span><br><span class="line">Triton URL</span><br></pre></td></tr></table></figure><p><code>forward()</code> 负责：</p><ul><li>PyTorch Tensor ↔ NumPy</li><li>NCHW ↔ NHWC</li><li>FP16</li><li>TensorRT 动态 shape&#x2F;binding</li><li>TFLite INT8 量化与反量化</li><li>统一输出为当前设备上的 Tensor</li></ul><h3 id="AutoShape"><a href="#AutoShape" class="headerlink" title="AutoShape"></a><code>AutoShape</code></h3><p>PyTorch Hub 的易用包装器，接受：</p><ul><li>路径&#x2F;URL</li><li>PIL</li><li>NumPy</li><li>OpenCV 图</li><li>Tensor</li><li>图片列表</li></ul><p>非 Tensor 输入会自动完成三通道转换、Letterbox、BCHW、归一化、前向、NMS、坐标缩放，并返回 <code>Detections</code>。</p><p>注意：注释明确要求 OpenCV BGR 输入先转 RGB，例如 <code>cv2.imread(...)[..., ::-1]</code>。</p><h3 id="Detections"><a href="#Detections" class="headerlink" title="Detections"></a><code>Detections</code></h3><p>封装结果展示和导出：</p><ul><li><code>print()</code> &#x2F; <code>show()</code> &#x2F; <code>save()</code></li><li><code>crop()</code></li><li><code>render()</code></li><li><code>pandas()</code></li><li><code>tolist()</code></li></ul><h2 id="3-3-models-experimental-py"><a href="#3-3-models-experimental-py" class="headerlink" title="3.3 models/experimental.py"></a>3.3 <code>models/experimental.py</code></h2><p>主要用于：</p><ul><li><code>attempt_load()</code>：加载一个或多个 <code>.pt</code></li><li>Conv+BN 融合</li><li>模型兼容处理</li><li>多模型 <code>Ensemble</code></li></ul><p><code>DetectMultiBackend</code> 加载 PyTorch 权重时调用此处。</p><h2 id="3-4-utils-dataloaders-py"><a href="#3-4-utils-dataloaders-py" class="headerlink" title="3.4 utils/dataloaders.py"></a>3.4 <code>utils/dataloaders.py</code></h2><h3 id="推理加载器"><a href="#推理加载器" class="headerlink" title="推理加载器"></a>推理加载器</h3><table><thead><tr><th>类</th><th>输入</th></tr></thead><tbody><tr><td><code>LoadImages</code></td><td>图片、视频、目录、glob</td></tr><tr><td><code>LoadStreams</code></td><td>摄像头、RTSP&#x2F;RTMP&#x2F;HTTP、多路流</td></tr><tr><td><code>LoadScreenshots</code></td><td>屏幕截图</td></tr></tbody></table><h3 id="训练加载器"><a href="#训练加载器" class="headerlink" title="训练加载器"></a>训练加载器</h3><p><code>LoadImagesAndLabels</code> 负责：</p><ul><li>搜索图像和映射标签路径</li><li>验证图片&#x2F;标签</li><li>建立 <code>.cache</code></li><li>矩形训练</li><li>RAM&#x2F;磁盘缓存</li><li>Mosaic、MixUp、随机透视、HSV、翻转</li><li>标签坐标在归一化 xywh 与像素 xyxy 间转换</li><li>BGR→RGB、HWC→CHW、连续内存</li></ul><p><code>create_dataloader()</code> 再包成 <code>InfiniteDataLoader</code> 或普通 DataLoader，并在 DDP 下使用分布式采样器。</p><h2 id="3-5-utils-augmentations-py"><a href="#3-5-utils-augmentations-py" class="headerlink" title="3.5 utils/augmentations.py"></a>3.5 <code>utils/augmentations.py</code></h2><p>关键函数：</p><table><thead><tr><th>函数&#x2F;类</th><th>作用</th></tr></thead><tbody><tr><td><code>letterbox</code></td><td>保持比例缩放并填充到 stride 倍数</td></tr><tr><td><code>random_perspective</code></td><td>旋转、平移、缩放、剪切、透视</td></tr><tr><td><code>augment_hsv</code></td><td>HSV LUT 颜色增强</td></tr><tr><td><code>mixup</code></td><td>两张图与标签混合</td></tr><tr><td><code>copy_paste</code></td><td>分割数据复制粘贴</td></tr><tr><td><code>Albumentations</code></td><td>可选第三方增强包装</td></tr></tbody></table><h2 id="3-6-utils-loss-py"><a href="#3-6-utils-loss-py" class="headerlink" title="3.6 utils/loss.py"></a>3.6 <code>utils/loss.py</code></h2><p><code>ComputeLoss</code> 的组成：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">总损失 = box gain × CIoU loss</span><br><span class="line">       + obj gain × BCE objectness</span><br><span class="line">       + cls gain × BCE classification</span><br></pre></td></tr></table></figure><p>它还支持：</p><ul><li>Label smoothing</li><li>FocalLoss</li><li>各检测尺度 Objectness balance</li><li>Anchor 宽高比匹配</li><li>相邻网格偏移匹配</li></ul><h2 id="3-7-utils-general-py"><a href="#3-7-utils-general-py" class="headerlink" title="3.7 utils/general.py"></a>3.7 <code>utils/general.py</code></h2><p>高频函数包括：</p><ul><li><code>non_max_suppression</code></li><li><code>scale_boxes</code></li><li><code>xyxy2xywh</code> &#x2F; <code>xywh2xyxy</code></li><li><code>check_dataset</code> &#x2F; <code>check_file</code> &#x2F; <code>check_img_size</code></li><li><code>increment_path</code></li><li><code>strip_optimizer</code></li><li>YAML 加载&#x2F;保存</li></ul><p>这是入口脚本最常依赖的通用工具集。</p><h2 id="3-8-utils-metrics-py"><a href="#3-8-utils-metrics-py" class="headerlink" title="3.8 utils/metrics.py"></a>3.8 <code>utils/metrics.py</code></h2><p>负责：</p><ul><li><code>box_iou</code></li><li>AP&#x2F;mAP 计算</li><li><code>ap_per_class</code></li><li>混淆矩阵</li><li>fitness 计算</li></ul><p>验证脚本在 IoU 阈值 0.50 到 0.95 上判断预测正确性，输出 Precision、Recall、<a href="mailto:&#x6d;&#65;&#x50;&#64;&#x30;&#46;&#x35;">mAP@0.5</a>、<a href="mailto:&#x6d;&#65;&#x50;&#x40;&#48;&#x2e;&#x35;">mAP@0.5</a>:0.95。</p><h2 id="3-9-utils-torch-utils-py"><a href="#3-9-utils-torch-utils-py" class="headerlink" title="3.9 utils/torch_utils.py"></a>3.9 <code>utils/torch_utils.py</code></h2><p>关键工程能力：</p><ul><li><code>select_device</code></li><li><code>smart_optimizer</code></li><li><code>smart_DDP</code></li><li><code>ModelEMA</code></li><li>AMP 检查</li><li>EarlyStopping</li><li>Conv+BN 融合</li><li>分布式同步辅助</li></ul><h2 id="3-10-回调和日志"><a href="#3-10-回调和日志" class="headerlink" title="3.10 回调和日志"></a>3.10 回调和日志</h2><ul><li><code>utils/callbacks.py::Callbacks</code>：维护事件与动作</li><li><code>utils/loggers/__init__.py::Loggers</code>：统一日志适配</li></ul><p>主训练循环只触发事件，具体日志平台通过注册回调接入，实现控制流与外部服务解耦。</p>]]>
    </content>
    <id>http://example.com/n/1222/</id>
    <link href="http://example.com/n/1222/"/>
    <published>2026-09-16T03:02:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="03-核心模块详解"><a href="#03-核心模块详解" class="headerlink" title="03 核心模块详解"></a>03 核心模块详解</h1><h2 id="3-1-models-yolo-py"><a href="#3-1-mod]]>
    </summary>
    <title>YOLOv5 7.0：核心模块详解</title>
    <updated>2026-09-16T03:49:31.702Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="02-OpenCV-4-13-0-系统架构"><a href="#02-OpenCV-4-13-0-系统架构" class="headerlink" title="02 OpenCV 4.13.0 系统架构"></a>02 OpenCV 4.13.0 系统架构</h1><h2 id="2-1-架构不是一张模块图"><a href="#2-1-架构不是一张模块图" class="headerlink" title="2.1 架构不是一张模块图"></a>2.1 架构不是一张模块图</h2><p>OpenCV 的实际行为由多套机制叠加决定：</p><ol><li><strong>模块依赖</strong>：哪些 OpenCV 库可以参与构建；</li><li><strong>外部依赖</strong>：哪些格式、设备、GUI 和加速能力被发现；</li><li><strong>数据模型</strong>：<code>Mat</code>、<code>UMat</code>、数组代理和张量怎样流转；</li><li><strong>实现分派</strong>：通用 C++、SIMD、HAL、IPP、OpenCL 等如何选择；</li><li><strong>后端注册</strong>：VideoIO、HighGUI、DNN、G-API 如何发现实现；</li><li><strong>产物组织</strong>：分模块库、插件或 <code>opencv_world</code> 如何部署；</li><li><strong>调用参数</strong>：数据类型、尺寸、后端偏好和设备状态如何影响单次执行。</li></ol><p>因此，“OpenCV 支持某功能”至少要拆成：<br>源码有实现、CMake 找到依赖、实现进入产物、部署完整、运行时成功选中五个问题。</p><h2 id="2-2-模块依赖语义"><a href="#2-2-模块依赖语义" class="headerlink" title="2.2 模块依赖语义"></a>2.2 模块依赖语义</h2><p>OpenCV 模块通常在 <code>modules/&lt;module&gt;/CMakeLists.txt</code> 中通过<br><code>ocv_add_module()</code> 或 <code>ocv_define_module()</code> 声明。</p><p>依赖可分为：</p><table><thead><tr><th>类型</th><th>典型写法</th><th>缺失时的结果</th></tr></thead><tbody><tr><td>必需 OpenCV 模块</td><td>位置参数或 <code>REQUIRED</code> 后的模块</td><td>当前模块通常不能正常构建</td></tr><tr><td>可选 OpenCV 模块</td><td><code>OPTIONAL</code> 后的模块</td><td>当前模块仍可构建，但部分 API&#x2F;实现关闭</td></tr><tr><td>私有外部链接</td><td><code>PRIVATE</code>、<code>LINK_PRIVATE</code> 等</td><td>影响实现，不传播为公共接口要求</td></tr><tr><td>包装目标</td><td><code>WRAP python java ...</code></td><td>决定绑定生成意图，不是算法依赖</td></tr><tr><td>条件功能</td><td><code>if(HAVE_*)</code>、<code>if(WITH_*)</code></td><td>仅满足配置条件时编译</td></tr></tbody></table><p><code>WITH_*</code> 通常表达“用户希望启用”，<br><code>HAVE_*</code> 通常表达“配置阶段确认可用”。<br>两者不能混用：设置 <code>WITH_FFMPEG=ON</code> 不保证最终 <code>HAVE_FFMPEG</code> 成立。</p><h2 id="2-3-核验过的主干依赖"><a href="#2-3-核验过的主干依赖" class="headerlink" title="2.3 核验过的主干依赖"></a>2.3 核验过的主干依赖</h2><p>下表依据 OpenCV 4.13.0 各模块 CMake 声明整理：</p><table><thead><tr><th>模块</th><th>必需 OpenCV 依赖</th><th>可选 OpenCV 依赖</th><th>说明</th></tr></thead><tbody><tr><td><code>core</code></td><td>无其他基础模块</td><td><code>cudev</code></td><td>全库底座；声明多语言包装</td></tr><tr><td><code>imgproc</code></td><td><code>core</code></td><td>无</td><td>经典图像处理主干</td></tr><tr><td><code>imgcodecs</code></td><td><code>imgproc</code></td><td>格式能力由外部库决定</td><td>依赖会传递到 <code>core</code></td></tr><tr><td><code>videoio</code></td><td><code>imgproc</code>、<code>imgcodecs</code></td><td>媒体后端由平台&#x2F;外部库决定</td><td>支持内建和插件实现</td></tr><tr><td><code>highgui</code></td><td><code>imgproc</code></td><td><code>imgcodecs</code>、<code>videoio</code></td><td>Android 与其他平台包装声明略有差异</td></tr><tr><td><code>features2d</code></td><td><code>imgproc</code></td><td><code>flann</code></td><td>调试配置还可引入 <code>highgui</code></td></tr><tr><td><code>calib3d</code></td><td><code>imgproc</code>、<code>features2d</code>、<code>flann</code></td><td>LAPACK 是可探测的外部增强</td><td>标定和多视图几何</td></tr><tr><td><code>video</code></td><td><code>imgproc</code></td><td><code>calib3d</code>、<code>dnn</code></td><td>部分跟踪器依赖 DNN</td></tr><tr><td><code>objdetect</code></td><td><code>core</code>、<code>imgproc</code>、<code>calib3d</code></td><td><code>dnn</code></td><td>DNN 缺失时相关能力条件编译</td></tr><tr><td><code>dnn</code></td><td><code>core</code>、<code>imgproc</code></td><td>多种计算后端</td><td>DNN CUDA 还要求 CUDA、cuBLAS、cuDNN</td></tr><tr><td><code>stitching</code></td><td><code>imgproc</code>、<code>features2d</code>、<code>calib3d</code>、<code>flann</code></td><td>CUDA 模块和额外特征模块</td><td>高级组合模块</td></tr><tr><td><code>gapi</code></td><td><code>imgproc</code>，以及内部图基础 <code>ade</code></td><td><code>video</code>、<code>calib3d</code> 和推理&#x2F;流式后端</td><td>找不到 <code>ade</code> 时模块会禁用</td></tr><tr><td><code>world</code></td><td><code>core</code> 起始并聚合选中模块</td><td>内容取决于整体构建</td><td>不是独立算法层</td></tr></tbody></table><blockquote><p>表中的“可选”不表示不重要。<br>例如 <code>video</code> 缺少 <code>dnn</code> 仍可构建，但若干基于模型的跟踪器不会进入可用接口。</p></blockquote><h2 id="2-4-外部依赖：必需与可选"><a href="#2-4-外部依赖：必需与可选" class="headerlink" title="2.4 外部依赖：必需与可选"></a>2.4 外部依赖：必需与可选</h2><h3 id="构建系统的基础要求"><a href="#构建系统的基础要求" class="headerlink" title="构建系统的基础要求"></a>构建系统的基础要求</h3><p>OpenCV 根工程由 CMake 驱动，并以 C 和 C++ 项目配置。<br>可工作的 C&#x2F;C++ 工具链、平台标准库和 CMake 是构建基础。<br>Python、Java、Ant、NumPy 等只在生成相应绑定或工具时需要。</p><h3 id="常见可选依赖"><a href="#常见可选依赖" class="headerlink" title="常见可选依赖"></a>常见可选依赖</h3><table><thead><tr><th>能力域</th><th>代表依赖</th><th>缺失后的典型影响</th></tr></thead><tbody><tr><td>JPEG</td><td>libjpeg-turbo 或 JPEG 库</td><td>JPEG 读写不可用</td></tr><tr><td>PNG</td><td>libpng&#x2F;libspng 与 zlib</td><td>PNG 读写不可用</td></tr><tr><td>TIFF</td><td>libtiff</td><td>TIFF 读写不可用</td></tr><tr><td>JPEG 2000</td><td>OpenJPEG&#x2F;Jasper</td><td>对应格式不可用或受策略限制</td></tr><tr><td>WebP&#x2F;AVIF&#x2F;JPEG XL</td><td>对应格式库</td><td>对应格式不可用</td></tr><tr><td>OpenEXR</td><td>OpenEXR</td><td>EXR 能力关闭或受运行策略限制</td></tr><tr><td>医学&#x2F;地理影像</td><td>GDCM&#x2F;GDAL</td><td>专用格式和元数据能力关闭</td></tr><tr><td>视频文件&#x2F;流</td><td>FFmpeg、GStreamer</td><td>对应容器、协议和编解码路径不可用</td></tr><tr><td>摄像头</td><td>V4L2、MSMF、AVFoundation 等平台 API</td><td>对应设备后端不可用</td></tr><tr><td>GUI</td><td>Qt、GTK、Wayland、Win32、Cocoa 等</td><td><code>imshow</code> 等能力受限或不可用</td></tr><tr><td>并行</td><td>TBB、OpenMP、平台并发框架</td><td>退回其他并行后端或串行路径</td></tr><tr><td>数值库</td><td>LAPACK 等</td><td>部分数值实现无法使用外部优化</td></tr><tr><td>DNN CPU&#x2F;图后端</td><td>Protobuf、OpenVINO 等</td><td>模型格式或执行后端受限</td></tr><tr><td>DNN CUDA</td><td>CUDA Toolkit、cuBLAS、cuDNN</td><td>CUDA DNN 后端不可构建</td></tr><tr><td>OpenCL</td><td>OpenCL 头、加载机制和运行时</td><td>T-API&#x2F;OpenCL 路径不可用</td></tr></tbody></table><p>有些第三方库可使用系统版本，也可构建 <code>3rdparty/</code> 中的副本；<br>具体策略由 CMake 选项和平台决定。</p><h3 id="“必需”是相对于目标能力"><a href="#“必需”是相对于目标能力" class="headerlink" title="“必需”是相对于目标能力"></a>“必需”是相对于目标能力</h3><p>对 <code>core + imgproc</code> 最小构建而言，FFmpeg 不是必需依赖；<br>对“必须读取 H.264 MP4”的产品需求而言，某个能完成该任务的视频后端就是业务必需依赖。<br>架构评审应同时记录“模块构建必需”和“产品功能必需”。</p><h2 id="2-5-从-API-到实现"><a href="#2-5-从-API-到实现" class="headerlink" title="2.5 从 API 到实现"></a>2.5 从 API 到实现</h2><p>公开声明通常位于 <code>modules/&lt;module&gt;/include/opencv2/&lt;module&gt;/</code>，<br>入口实现通常位于 <code>src/*.cpp</code>；<code>*.dispatch.cpp</code>、<code>*.simd.hpp</code><br>和 <code>opencl/*.cl</code> 分别是 CPU 分发、向量化主体和 OpenCL 内核的重要线索。<br>入口通常先校验参数并创建输出，再按数据条件选择通用、优化或外部后端。</p><h3 id="典型调用链：GaussianBlur"><a href="#典型调用链：GaussianBlur" class="headerlink" title="典型调用链：GaussianBlur"></a>典型调用链：<code>GaussianBlur</code></h3><p><code>cv::GaussianBlur</code> 的公开接口属于 <code>imgproc</code>，<br>4.13.0 的主要入口位于：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">modules/imgproc/src/smooth.dispatch.cpp</span><br></pre></td></tr></table></figure><p>调用链可概括为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  A[&quot;cv::GaussianBlur&quot;] --&gt; V[&quot;参数、核大小、边界类型校验&quot;]</span><br><span class="line">  V --&gt; O&#123;&quot;适用 OpenCL/专用路径？&quot;&#125;</span><br><span class="line">  O --&gt;|是| K[&quot;OpenCL 或专用实现&quot;]</span><br><span class="line">  O --&gt;|否| H&#123;&quot;HAL/IPP 等可处理？&quot;&#125;</span><br><span class="line">  H --&gt;|是| X[&quot;优化实现&quot;]</span><br><span class="line">  H --&gt;|否| C[&quot;CPU 滤波引擎/dispatch&quot;]</span><br><span class="line">  K --&gt; D[&quot;dst&quot;]</span><br><span class="line">  X --&gt; D</span><br><span class="line">  C --&gt; D</span><br></pre></td></tr></table></figure><p>具体选择受输入深度、通道、核大小、边界类型、输出对象种类和构建宏影响。<br>不能把该图理解成每次都按固定顺序执行全部判断。</p><h3 id="典型调用链：imread"><a href="#典型调用链：imread" class="headerlink" title="典型调用链：imread"></a>典型调用链：<code>imread</code></h3><p><code>cv::imread()</code> 的公开声明在 <code>opencv2/imgcodecs.hpp</code>，<br>实现入口位于：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">modules/imgcodecs/src/loadsave.cpp</span><br></pre></td></tr></table></figure><p>该文件中的 <code>ImageCodecInitializer</code> 保存已注册解码器和编码器，<br><code>findDecoder()</code> 通过读取文件签名字节选择解码器，而不是只信任扩展名。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">sequenceDiagram</span><br><span class="line">  participant App as 应用</span><br><span class="line">  participant Load as imread/loadsave.cpp</span><br><span class="line">  participant Registry as 解码器集合</span><br><span class="line">  participant Decoder as ImageDecoder</span><br><span class="line">  participant Lib as 格式库</span><br><span class="line"></span><br><span class="line">  App-&gt;&gt;Load: imread(filename, flags)</span><br><span class="line">  Load-&gt;&gt;Registry: findDecoder(filename)</span><br><span class="line">  Registry-&gt;&gt;Registry: 比较文件签名</span><br><span class="line">  Registry--&gt;&gt;Load: 新解码器实例</span><br><span class="line">  Load-&gt;&gt;Decoder: readHeader()</span><br><span class="line">  Load-&gt;&gt;Load: 创建目标 Mat</span><br><span class="line">  Load-&gt;&gt;Decoder: readData()</span><br><span class="line">  Decoder-&gt;&gt;Lib: 调用对应格式实现</span><br><span class="line">  Lib--&gt;&gt;App: 像素数据</span><br></pre></td></tr></table></figure><p><code>imwrite()</code> 则主要根据文件扩展名选择编码器。<br>读取失败常返回空 <code>Mat</code>，应用必须检查 <code>empty()</code>；<br>参数错误或内部断言也可能抛出 <code>cv::Exception</code>。</p><h3 id="典型调用链：VideoCapture"><a href="#典型调用链：VideoCapture" class="headerlink" title="典型调用链：VideoCapture"></a>典型调用链：<code>VideoCapture</code></h3><p>核心入口位于：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">modules/videoio/src/cap.cpp</span><br><span class="line">modules/videoio/src/videoio_registry.cpp</span><br><span class="line">modules/videoio/src/backend_plugin.cpp</span><br></pre></td></tr></table></figure><p><code>VideoCapture::open()</code> 根据输入类型和 <code>apiPreference</code><br>遍历支持“按索引捕获”“按文件名捕获”或“按流捕获”的后端。<br>注册表维护后端 ID、名称、优先级和工厂。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  OPEN[&quot;VideoCapture::open&quot;] --&gt; PREF&#123;&quot;指定 apiPreference？&quot;&#125;</span><br><span class="line">  PREF --&gt; REG[&quot;过滤并排序注册后端&quot;]</span><br><span class="line">  REG --&gt; FACT[&quot;获取内建或插件工厂&quot;]</span><br><span class="line">  FACT --&gt; TRY[&quot;逐个尝试 create/open&quot;]</span><br><span class="line">  TRY --&gt; OK&#123;&quot;打开成功？&quot;&#125;</span><br><span class="line">  OK --&gt;|否| REG</span><br><span class="line">  OK --&gt;|是| CAP[&quot;保存 IVideoCapture&quot;]</span><br><span class="line">  CAP --&gt; READ[&quot;read()&quot;]</span><br><span class="line">  READ --&gt; GRAB[&quot;grab()&quot;]</span><br><span class="line">  GRAB --&gt; RET[&quot;retrieve(OutputArray)&quot;]</span><br></pre></td></tr></table></figure><p><code>read()</code> 在 <code>cap.cpp</code> 中组合 <code>grab()</code> 与 <code>retrieve()</code>。<br>成功打开不保证每个属性均可设置，也不保证属性单位在所有后端一致。</p><p>运行时可通过以下配置影响 VideoIO：</p><ul><li><code>OPENCV_VIDEOIO_PRIORITY_LIST</code>：提高列出的后端优先级；</li><li><code>OPENCV_VIDEOIO_PRIORITY_&lt;name&gt;</code>：调整或以 <code>0</code> 禁用某后端；</li><li><code>OPENCV_VIDEOIO_PLUGIN_PATH</code>：补充插件搜索路径。</li></ul><p>环境配置必须在相关注册表初始化前设置，并应结合日志验证。</p><h2 id="2-6-Mat-数据流"><a href="#2-6-Mat-数据流" class="headerlink" title="2.6 Mat 数据流"></a>2.6 <code>Mat</code> 数据流</h2><p>典型 CPU 图像流水线如下：</p><p>关键数据语义：</p><ul><li>解码器创建并填充目标 <code>Mat</code>；</li><li>ROI 可能共享原缓冲区且不连续；</li><li><code>OutputArray::create()</code> 可复用匹配的目标内存；</li><li>通道顺序、色彩空间和深度必须显式管理；</li><li>某些算法允许原地计算，另一些不允许；</li><li>跨模块传递 <code>Mat</code> 通常不复制像素，但类型转换和布局转换会复制。</li></ul><h2 id="2-7-UMat-数据流"><a href="#2-7-UMat-数据流" class="headerlink" title="2.7 UMat 数据流"></a>2.7 <code>UMat</code> 数据流</h2><p>当输入或输出是 <code>UMat</code> 时，支持 Transparent API 的实现可使用 OpenCL：</p><p>高效用法是让一串兼容算子持续处理 <code>UMat</code>，<br>尽量推迟 <code>getMat()</code> 或下载。</p><p>以下情况可能破坏收益：</p><ul><li>每个算子后都转回 <code>Mat</code>；</li><li>输入很小，内核启动成本占主导；</li><li>算子或数据类型没有 OpenCL 实现；</li><li>主机访问触发同步；</li><li>OpenCL 运行时不可用或被禁用；</li><li>OpenCL 路径内部因条件不满足回退。</li></ul><p><code>Mat</code> 与 <code>UMat</code> 可以通过共同的数组代理进入相同 API，<br>但这不代表内部存储位置和同步成本相同。</p><h2 id="2-8-I-O-与插件架构"><a href="#2-8-I-O-与插件架构" class="headerlink" title="2.8 I&#x2F;O 与插件架构"></a>2.8 I&#x2F;O 与插件架构</h2><p><code>imgcodecs</code> 按 <code>HAVE_*</code> 条件接入格式实现；<br>读取通常以文件签名选解码器，写入通常以扩展名选编码器。<br>OpenEXR 和 Jasper 等能力还可能受运行策略或强制选项影响。</p><h3 id="VideoIO-插件与注册"><a href="#VideoIO-插件与注册" class="headerlink" title="VideoIO 插件与注册"></a>VideoIO 插件与注册</h3><p><code>modules/videoio/CMakeLists.txt</code> 默认在多数桌面平台允许插件，<br>并提供：</p><ul><li><code>VIDEOIO_ENABLE_PLUGINS</code>；</li><li><code>VIDEOIO_PLUGIN_LIST</code>；</li><li><code>opencv_videoio_plugins</code> 聚合目标。</li></ul><p>FFmpeg、GStreamer、Media SDK&#x2F;oneVPL、MSMF 等可按配置成为插件或内建实现。<br>注册表对不同输入形态维护可用后端列表，并按优先级选择。</p><p>部署时要同时考虑：</p><ol><li>OpenCV 主库；</li><li>VideoIO 插件；</li><li>插件依赖的第三方动态库；</li><li>操作系统设备权限；</li><li>网络协议、容器和编解码器实际支持；</li><li>ABI&#x2F;API 兼容性。</li></ol><h3 id="HighGUI-后端"><a href="#HighGUI-后端" class="headerlink" title="HighGUI 后端"></a>HighGUI 后端</h3><p><code>highgui</code> 的模块必需依赖是 <code>imgproc</code>，<br><code>imgcodecs</code> 和 <code>videoio</code> 为可选模块依赖。<br>实现由平台和 CMake 探测选择 Qt、GTK、Wayland、Win32、Cocoa、<br>Framebuffer 等路径，并支持部分 UI 插件机制。</p><p>主要入口和后端组织位于：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">modules/highgui/src/window.cpp</span><br><span class="line">modules/highgui/src/backend.cpp</span><br><span class="line">modules/highgui/src/window_*.cpp</span><br></pre></td></tr></table></figure><p><code>OPENCV_UI_BACKEND</code> 可请求特定 UI 后端，<br>但目标后端必须已构建且能成功初始化。<br>无头服务器上 <code>imshow()</code> 失败通常是部署环境问题，不是图像算法问题。</p><h2 id="2-9-DNN-架构"><a href="#2-9-DNN-架构" class="headerlink" title="2.9 DNN 架构"></a>2.9 DNN 架构</h2><p><code>dnn</code> 必需依赖 <code>core</code> 和 <code>imgproc</code>。<br>其工作可拆成模型导入、内部图、内存&#x2F;张量、层实现和执行后端。</p><p>主要 API 入口与实现：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">modules/dnn/include/opencv2/dnn/dnn.hpp</span><br><span class="line">modules/dnn/src/net.cpp</span><br><span class="line">modules/dnn/src/net_impl.cpp</span><br><span class="line">modules/dnn/src/layers/</span><br></pre></td></tr></table></figure><p><code>Net::setPreferableBackend()</code> 和 <code>setPreferableTarget()</code> 只表达偏好组合。<br>是否成功取决于：</p><ul><li>后端是否进入构建；</li><li>运行时和设备是否存在；</li><li>模型每个算子是否受支持；</li><li>数据类型、动态形状和精度是否兼容；</li><li>回退策略是否允许；</li><li>后端初始化是否成功。</li></ul><p>DNN CUDA 后端的 CMake 条件明确要求 CUDA、cuBLAS 和 cuDNN。<br>仅启用 CUDA 基础模块不足以保证 DNN CUDA 可用。</p><h2 id="2-10-G-API-架构"><a href="#2-10-G-API-架构" class="headerlink" title="2.10 G-API 架构"></a>2.10 G-API 架构</h2><p>G-API 使用 <code>GMat</code>、<code>GScalar</code> 等描述计算，<br>先构建图，再编译并执行。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  EXPR[&quot;GMat/GScalar 操作表达式&quot;] --&gt; GRAPH[&quot;内部图&quot;]</span><br><span class="line">  GRAPH --&gt; PASS[&quot;元数据推导与编译 Pass&quot;]</span><br><span class="line">  PASS --&gt; PKG[&quot;内核包与后端匹配&quot;]</span><br><span class="line">  PKG --&gt; EXEC[&quot;CPU / Fluid / OCL / Streaming / 推理后端&quot;]</span><br><span class="line">  EXEC --&gt; RESULT[&quot;批处理或流式结果&quot;]</span><br></pre></td></tr></table></figure><p><code>modules/gapi/CMakeLists.txt</code> 明确要求 <code>ade</code> 目标；<br>缺少它时模块会被禁用。<br>G-API 必需依赖 <code>imgproc</code>，可选依赖 <code>video</code> 和 <code>calib3d</code>，<br>另外按构建接入 OpenVINO、GStreamer、oneVPL 等能力。</p><p>G-API 的优势来自图级信息：</p><ul><li>合并或重排可执行阶段；</li><li>选择不同内核包；</li><li>构建流式处理；</li><li>统一管理异构后端。</li></ul><p>代价是需要显式描述图、编译参数和后端内核，<br>并非所有立即执行 API 都能自动转换。</p><h2 id="2-11-opencv-world"><a href="#2-11-opencv-world" class="headerlink" title="2.11 opencv_world"></a>2.11 <code>opencv_world</code></h2><p><code>modules/world/CMakeLists.txt</code> 遍历被标记为 <code>IS_PART_OF_WORLD</code> 的已选模块，<br>收集其头文件、源文件和链接依赖后生成 <code>opencv_world</code>。</p><p>它带来的变化是：</p><ul><li>应用侧链接库数量减少；</li><li>模块符号聚合到一个产物；</li><li>部署时仍可能需要插件和外部动态库；</li><li>静态链接仍需处理传递依赖；</li><li>未启用或被排除的模块不会自动出现；</li><li>模块逻辑边界和命名空间不会因此消失。</li></ul><p><code>world</code> 是构建产物策略，不是比模块库多一套算法实现。</p><h2 id="2-12-构建时选择"><a href="#2-12-构建时选择" class="headerlink" title="2.12 构建时选择"></a>2.12 构建时选择</h2><p>构建时决定：</p><ul><li><code>BUILD_LIST</code> 或 <code>BUILD_opencv_*</code> 选择的模块；</li><li>共享库或静态库；</li><li>是否生成 <code>opencv_world</code>；</li><li>CPU baseline 与 dispatch 指令集；</li><li>是否启用 OpenCL、IPP、并行框架；</li><li>找到哪些图像、视频、GUI 和 DNN 依赖；</li><li>哪些后端内建，哪些生成插件；</li><li>生成哪些语言绑定、测试和示例。</li></ul><p>配置摘要是架构证据，应随二进制归档。</p><h2 id="2-13-运行时选择"><a href="#2-13-运行时选择" class="headerlink" title="2.13 运行时选择"></a>2.13 运行时选择</h2><p>运行时还会继续决策：</p><table><thead><tr><th>时机</th><th>选择内容</th></tr></thead><tbody><tr><td>进程初始化</td><td>CPU 能力、日志、线程和全局配置</td></tr><tr><td>首次使用模块</td><td>注册表、插件发现、设备上下文和缓存</td></tr><tr><td>打开媒体</td><td>后端优先级、输入类型和参数</td></tr><tr><td>单次图像调用</td><td>类型、尺寸、连续性、输出种类和优化条件</td></tr><tr><td>DNN 网络执行</td><td>后端、目标、算子支持和回退</td></tr><tr><td>UMat 调用</td><td>OpenCL 可用性、内核支持和同步状态</td></tr></tbody></table><p>选择结果可能受环境变量、动态库搜索路径、设备权限和驱动改变。<br>可重复部署必须控制这些外部条件。</p><h2 id="2-14-端到端典型链：相机预处理与-DNN"><a href="#2-14-端到端典型链：相机预处理与-DNN" class="headerlink" title="2.14 端到端典型链：相机预处理与 DNN"></a>2.14 端到端典型链：相机预处理与 DNN</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">sequenceDiagram</span><br><span class="line">  participant App as 应用</span><br><span class="line">  participant V as VideoIO</span><br><span class="line">  participant P as Imgproc</span><br><span class="line">  participant D as DNN</span><br><span class="line">  participant G as HighGUI/输出</span><br><span class="line"></span><br><span class="line">  App-&gt;&gt;V: VideoCapture::open(index, preference)</span><br><span class="line">  V-&gt;&gt;V: 注册表选择设备后端</span><br><span class="line">  loop 每帧</span><br><span class="line">    App-&gt;&gt;V: read(frame)</span><br><span class="line">    V--&gt;&gt;App: Mat/BGR</span><br><span class="line">    App-&gt;&gt;P: resize/cvtColor 或 blobFromImage</span><br><span class="line">    P--&gt;&gt;App: 预处理数据</span><br><span class="line">    App-&gt;&gt;D: Net::setInput(blob)</span><br><span class="line">    App-&gt;&gt;D: Net::forward()</span><br><span class="line">    D-&gt;&gt;D: 后端/目标执行与必要回退</span><br><span class="line">    D--&gt;&gt;App: 输出张量</span><br><span class="line">    App-&gt;&gt;P: 解码、缩放坐标、绘制</span><br><span class="line">    App-&gt;&gt;G: imshow 或 VideoWriter::write</span><br><span class="line">  end</span><br></pre></td></tr></table></figure><p>该链路中最常见的架构问题是：</p><ul><li>捕获后端输出格式不符合预期；</li><li>BGR&#x2F;RGB、NCHW&#x2F;NHWC、缩放和均值设置错误；</li><li>每帧重复分配或上传下载；</li><li>DNN 后端未实际启用；</li><li>GUI 阻塞或服务器无显示后端；</li><li>视频时间戳和处理速度不匹配。</li></ul><h2 id="2-15-架构排错顺序"><a href="#2-15-架构排错顺序" class="headerlink" title="2.15 架构排错顺序"></a>2.15 架构排错顺序</h2><p>定位某项能力时建议按以下顺序：</p><ol><li>确认运行时加载的 OpenCV 版本；</li><li>保存 <code>cv::getBuildInformation()</code>；</li><li>确认模块已进入构建；</li><li>核对模块必需和可选依赖；</li><li>找到公开声明和入口实现；</li><li>检查 <code>WITH_*</code>、<code>HAVE_*</code> 和条件编译；</li><li>确认插件与第三方动态库部署；</li><li>开启相关日志，记录后端枚举和选择；</li><li>检查输入类型、布局、连续性和生命周期；</li><li>用最小用例区分配置、数据和算法问题；</li><li>阅读模块 <code>test/</code> 的边界条件；</li><li>最后再做性能和精度比较。</li></ol><h2 id="2-16-注意事项"><a href="#2-16-注意事项" class="headerlink" title="2.16 注意事项"></a>2.16 注意事项</h2><ul><li>模块 CMake 是依赖真相的重要来源，但最终目标仍受全局配置修改；</li><li>格式扩展名存在不代表对应解码器已构建；</li><li>VideoIO 的同名属性在不同后端可能语义不同；</li><li>插件加载成功不代表其第三方依赖和设备初始化成功；</li><li><code>Mat</code> 浅拷贝会让跨阶段修改互相可见；</li><li><code>UMat</code> 映射回主机通常是同步点；</li><li>DNN 指定后端不代表所有层都由该后端执行；</li><li>G-API 编译图的成本应与重复执行次数一起评估；</li><li><code>opencv_world</code> 不消除插件和外部库依赖；</li><li>性能结论必须基于目标二进制、目标设备和真实数据。</li></ul><h2 id="2-17-后续阅读建议"><a href="#2-17-后续阅读建议" class="headerlink" title="2.17 后续阅读建议"></a>2.17 后续阅读建议</h2><p>理解本篇后，可继续：</p><ul><li>在 <code>03_核心模块详解.md</code> 查看模块内部职责；</li><li>在 <code>04_算法流水线.md</code> 查看更多任务级组合；</li><li>在 <code>05_HAL与性能优化.md</code> 深入实现分派；</li><li>在 <code>06_配置与使用.md</code> 将依赖和后端落到构建命令；</li><li>在 <code>07_源码文件索引.md</code> 快速定位声明、实现、测试和性能文件。</li></ul>]]>
    </content>
    <id>http://example.com/n/1201/</id>
    <link href="http://example.com/n/1201/"/>
    <published>2026-09-16T03:01:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="02-OpenCV-4-13-0-系统架构"><a href="#02-OpenCV-4-13-0-系统架构" class="headerlink" title="02 OpenCV 4.13.0 系统架构"></a>02 OpenCV 4.13.0 系统架构</]]>
    </summary>
    <title>02 OpenCV 4.13.0 系统架构</title>
    <updated>2026-09-16T03:49:31.690Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="02-系统架构"><a href="#02-系统架构" class="headerlink" title="02 系统架构"></a>02 系统架构</h1><h2 id="2-1-分层架构"><a href="#2-1-分层架构" class="headerlink" title="2.1 分层架构"></a>2.1 分层架构</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">  subgraph Entry[&quot;任务入口&quot;]</span><br><span class="line">    TR[&quot;train.py&quot;]</span><br><span class="line">    VA[&quot;val.py&quot;]</span><br><span class="line">    DE[&quot;detect.py&quot;]</span><br><span class="line">    EX[&quot;export.py&quot;]</span><br><span class="line">    SG[&quot;segment/*&quot;]</span><br><span class="line">    CL[&quot;classify/*&quot;]</span><br><span class="line">    HUB[&quot;hubconf.py&quot;]</span><br><span class="line">  end</span><br><span class="line"></span><br><span class="line">  subgraph Model[&quot;模型层&quot;]</span><br><span class="line">    YAML[&quot;models/*.yaml&quot;]</span><br><span class="line">    YOLO[&quot;models/yolo.py&quot;]</span><br><span class="line">    COMMON[&quot;models/common.py&quot;]</span><br><span class="line">    EXP[&quot;models/experimental.py&quot;]</span><br><span class="line">  end</span><br><span class="line"></span><br><span class="line">  subgraph Utility[&quot;基础设施&quot;]</span><br><span class="line">    DL[&quot;utils/dataloaders.py&quot;]</span><br><span class="line">    AUG[&quot;utils/augmentations.py&quot;]</span><br><span class="line">    LOSS[&quot;utils/loss.py&quot;]</span><br><span class="line">    GEN[&quot;utils/general.py&quot;]</span><br><span class="line">    MET[&quot;utils/metrics.py&quot;]</span><br><span class="line">    TU[&quot;utils/torch_utils.py&quot;]</span><br><span class="line">    LOG[&quot;utils/loggers/ + callbacks.py&quot;]</span><br><span class="line">  end</span><br><span class="line"></span><br><span class="line">  subgraph Runtime[&quot;运行时&quot;]</span><br><span class="line">    TORCH[&quot;PyTorch / CUDA&quot;]</span><br><span class="line">    CV[&quot;OpenCV&quot;]</span><br><span class="line">    BACK[&quot;ONNX / TRT / OpenVINO / TFLite ...&quot;]</span><br><span class="line">  end</span><br><span class="line"></span><br><span class="line">  Entry --&gt; Model</span><br><span class="line">  Entry --&gt; Utility</span><br><span class="line">  YAML --&gt; YOLO</span><br><span class="line">  YOLO --&gt; COMMON</span><br><span class="line">  EXP --&gt; YOLO</span><br><span class="line">  Utility --&gt; TORCH</span><br><span class="line">  Utility --&gt; CV</span><br><span class="line">  COMMON --&gt; BACK</span><br></pre></td></tr></table></figure><p>入口脚本负责组织流程；<code>models/</code> 负责网络与推理运行时；<code>utils/</code> 负责数据、增强、损失、指标和工程能力。</p><h2 id="2-2-模型构建链"><a href="#2-2-模型构建链" class="headerlink" title="2.2 模型构建链"></a>2.2 模型构建链</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  Y[&quot;yolov5s.yaml&quot;] --&gt; L[&quot;yaml.safe_load&quot;]</span><br><span class="line">  L --&gt; D[&quot;DetectionModel&quot;]</span><br><span class="line">  D --&gt; P[&quot;parse_model&quot;]</span><br><span class="line">  P --&gt; S[&quot;nn.Sequential + save list&quot;]</span><br><span class="line">  S --&gt; F[&quot;BaseModel._forward_once&quot;]</span><br><span class="line">  F --&gt; H[&quot;Detect(P3,P4,P5)&quot;]</span><br></pre></td></tr></table></figure><h3 id="YAML-层定义"><a href="#YAML-层定义" class="headerlink" title="YAML 层定义"></a>YAML 层定义</h3><p>每层格式：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="string">from</span>, <span class="string">number</span>, <span class="string">module</span>, <span class="string">args</span>]</span><br></pre></td></tr></table></figure><ul><li><code>from</code>：输入来自前一层或指定历史层</li><li><code>number</code>：模块重复次数，受 <code>depth_multiple</code> 缩放</li><li><code>module</code>：<code>Conv</code>、<code>C3</code>、<code>SPPF</code>、<code>Concat</code>、<code>Detect</code> 等</li><li><code>args</code>：输出通道、卷积核、步长等构造参数</li></ul><h3 id="动态解析"><a href="#动态解析" class="headerlink" title="动态解析"></a>动态解析</h3><p><code>models/yolo.py::parse_model()</code>：</p><ol><li>合并 <code>backbone + head</code></li><li>解析模块和字符串参数</li><li>按深度系数缩放重复数</li><li>按宽度系数缩放通道并对齐到 8</li><li>为每层附加 <code>i/f/type/np</code></li><li>建立 <code>save</code> 列表，保留后续跳连所需输出</li></ol><h3 id="前向传播"><a href="#前向传播" class="headerlink" title="前向传播"></a>前向传播</h3><p><code>BaseModel._forward_once()</code> 顺序遍历 <code>self.model</code>。若 <code>m.f != -1</code>，就从历史输出 <code>y</code> 取跳连输入；只有 <code>self.save</code> 指定的中间层会被保留。</p><h2 id="2-3-YOLOv5s-网络结构"><a href="#2-3-YOLOv5s-网络结构" class="headerlink" title="2.3 YOLOv5s 网络结构"></a>2.3 YOLOv5s 网络结构</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  IN[&quot;640×640×3&quot;] --&gt; B1[&quot;Conv /2&quot;]</span><br><span class="line">  B1 --&gt; B2[&quot;Conv+C3 /4&quot;]</span><br><span class="line">  B2 --&gt; P3[&quot;C3 P3/8&quot;]</span><br><span class="line">  P3 --&gt; P4[&quot;C3 P4/16&quot;]</span><br><span class="line">  P4 --&gt; P5[&quot;C3+SPPF P5/32&quot;]</span><br><span class="line"></span><br><span class="line">  P5 --&gt; U1[&quot;上采样+Concat P4&quot;]</span><br><span class="line">  U1 --&gt; U2[&quot;上采样+Concat P3&quot;]</span><br><span class="line">  U2 --&gt; D3[&quot;Detect P3/8&quot;]</span><br><span class="line">  U2 --&gt; N4[&quot;下采样+Concat&quot;]</span><br><span class="line">  N4 --&gt; D4[&quot;Detect P4/16&quot;]</span><br><span class="line">  D4 --&gt; N5[&quot;下采样+Concat&quot;]</span><br><span class="line">  N5 --&gt; D5[&quot;Detect P5/32&quot;]</span><br></pre></td></tr></table></figure><ul><li>Backbone：Conv + C3 + SPPF</li><li>Neck：FPN 自顶向下 + PAN 自底向上</li><li>Head：P3、P4、P5 三尺度 Anchor-based Detect</li></ul><p>对 640 输入，三层网格约为 80×80、40×40、20×20。</p><h2 id="2-4-训练数据流"><a href="#2-4-训练数据流" class="headerlink" title="2.4 训练数据流"></a>2.4 训练数据流</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  DS[&quot;data/*.yaml&quot;] --&gt; LO[&quot;LoadImagesAndLabels&quot;]</span><br><span class="line">  LO --&gt; AU[&quot;Mosaic/MixUp/透视/HSV/翻转&quot;]</span><br><span class="line">  AU --&gt; BT[&quot;BGR→RGB, HWC→CHW&quot;]</span><br><span class="line">  BT --&gt; FW[&quot;model(imgs)&quot;]</span><br><span class="line">  FW --&gt; LS[&quot;ComputeLoss&quot;]</span><br><span class="line">  LS --&gt; BP[&quot;AMP backward&quot;]</span><br><span class="line">  BP --&gt; OP[&quot;optimizer step&quot;]</span><br><span class="line">  OP --&gt; EMA[&quot;ModelEMA&quot;]</span><br><span class="line">  EMA --&gt; VAL[&quot;val.run&quot;]</span><br><span class="line">  VAL --&gt; CK[&quot;last.pt / best.pt&quot;]</span><br></pre></td></tr></table></figure><p><code>train.py::train()</code> 是流程控制中心。Rank 0 还负责日志、验证、保存和早停。</p><h2 id="2-5-检测推理数据流"><a href="#2-5-检测推理数据流" class="headerlink" title="2.5 检测推理数据流"></a>2.5 检测推理数据流</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  SRC[&quot;图片/视频/相机/流&quot;] --&gt; LD[&quot;LoadImages/LoadStreams&quot;]</span><br><span class="line">  LD --&gt; LB[&quot;Letterbox&quot;]</span><br><span class="line">  LB --&gt; PRE[&quot;BGR→RGB, CHW, /255&quot;]</span><br><span class="line">  PRE --&gt; MB[&quot;DetectMultiBackend&quot;]</span><br><span class="line">  MB --&gt; NMS[&quot;non_max_suppression&quot;]</span><br><span class="line">  NMS --&gt; SC[&quot;scale_boxes 回原图&quot;]</span><br><span class="line">  SC --&gt; AN[&quot;Annotator&quot;]</span><br><span class="line">  AN --&gt; OUT[&quot;图片/视频/TXT/Crop&quot;]</span><br></pre></td></tr></table></figure><p>关键点：</p><ul><li>网络不是直接吃任意尺寸原图，而是先 Letterbox 到 stride 倍数。</li><li>检测头输出在网络输入坐标系中。</li><li><code>scale_boxes</code> 去掉 padding 并按比例映射回原图。</li></ul><h2 id="2-6-多后端架构"><a href="#2-6-多后端架构" class="headerlink" title="2.6 多后端架构"></a>2.6 多后端架构</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">  DMB[&quot;DetectMultiBackend&quot;]</span><br><span class="line">  DMB --&gt; PT[&quot;PyTorch .pt&quot;]</span><br><span class="line">  DMB --&gt; JIT[&quot;TorchScript&quot;]</span><br><span class="line">  DMB --&gt; ONNX[&quot;ONNX Runtime / OpenCV DNN&quot;]</span><br><span class="line">  DMB --&gt; TRT[&quot;TensorRT&quot;]</span><br><span class="line">  DMB --&gt; OV[&quot;OpenVINO&quot;]</span><br><span class="line">  DMB --&gt; CML[&quot;CoreML&quot;]</span><br><span class="line">  DMB --&gt; TF[&quot;SavedModel / PB / TFLite / EdgeTPU&quot;]</span><br><span class="line">  DMB --&gt; PD[&quot;Paddle&quot;]</span><br><span class="line">  DMB --&gt; TS[&quot;Triton Server&quot;]</span><br></pre></td></tr></table></figure><p>该类统一：</p><ul><li>模型格式识别</li><li>设备与 FP16</li><li>NCHW&#x2F;NHWC 转换</li><li>元数据 <code>stride/names</code></li><li>输入输出转换为 Torch Tensor</li><li>动态 TensorRT binding</li><li>模型 warmup</li></ul><h2 id="2-7-训练并发模型"><a href="#2-7-训练并发模型" class="headerlink" title="2.7 训练并发模型"></a>2.7 训练并发模型</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">单 GPU/CPU: RANK=-1</span><br><span class="line">DataParallel: 可用但源码明确不推荐</span><br><span class="line">DDP: torch.distributed.run，每 GPU 一个进程</span><br></pre></td></tr></table></figure><p>DDP 下：</p><ul><li>每个 Rank 使用分布式 sampler</li><li>反向损失按 <code>WORLD_SIZE</code> 调整</li><li>仅 Rank 0 做完整日志、验证和 checkpoint</li><li>早停结果广播到所有 Rank</li></ul><h2 id="2-8-回调与日志"><a href="#2-8-回调与日志" class="headerlink" title="2.8 回调与日志"></a>2.8 回调与日志</h2><p><code>Callbacks</code> 提供训练生命周期事件，例如：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">on_pretrain_routine_start/end</span><br><span class="line">on_train_start</span><br><span class="line">on_train_epoch_start/end</span><br><span class="line">on_train_batch_start/end</span><br><span class="line">on_fit_epoch_end</span><br><span class="line">on_model_save</span><br><span class="line">on_train_end</span><br></pre></td></tr></table></figure><p><code>Loggers</code> 将对应方法注册为回调，使训练主循环不必绑定具体平台。TensorBoard、ClearML、Comet、W&amp;B 等都通过该层接入。</p>]]>
    </content>
    <id>http://example.com/n/1221/</id>
    <link href="http://example.com/n/1221/"/>
    <published>2026-09-16T03:01:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="02-系统架构"><a href="#02-系统架构" class="headerlink" title="02 系统架构"></a>02 系统架构</h1><h2 id="2-1-分层架构"><a href="#2-1-分层架构" class="headerli]]>
    </summary>
    <title>YOLOv5 7.0：系统架构</title>
    <updated>2026-09-16T03:49:31.701Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/OpenCV/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="OpenCV" scheme="http://example.com/tags/OpenCV/"/>
    <content>
      <![CDATA[<h1 id="01-OpenCV-4-13-0-系统概述"><a href="#01-OpenCV-4-13-0-系统概述" class="headerlink" title="01 OpenCV 4.13.0 系统概述"></a>01 OpenCV 4.13.0 系统概述</h1><h2 id="1-1-项目定位"><a href="#1-1-项目定位" class="headerlink" title="1.1 项目定位"></a>1.1 项目定位</h2><p>OpenCV（Open Source Computer Vision Library）是以 C++ 为核心的跨平台计算机视觉基础库。<br>它用统一的数据结构和 API 覆盖图像处理、几何视觉、视频分析、传统机器学习与神经网络推理，<br>并通过模块化构建、运行时后端和多级优化适配桌面、服务器、移动端与嵌入式平台。</p><p>本篇分析对象是 <strong>OpenCV 4.13.0</strong>。<br>源码中的版本宏位于：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">modules/core/include/opencv2/core/version.hpp</span><br></pre></td></tr></table></figure><p>其中 <code>CV_VERSION_MAJOR</code>、<code>CV_VERSION_MINOR</code>、<code>CV_VERSION_REVISION</code><br>分别为 <code>4</code>、<code>13</code>、<code>0</code>，<code>CV_VERSION_STATUS</code> 为空。<br>运行时可使用 <code>cv::getVersionString()</code> 获取版本，<br>使用 <code>cv::getBuildInformation()</code> 获取本次构建的模块、依赖、CPU 特性和后端信息。</p><h2 id="1-2-许可证与再发布边界"><a href="#1-2-许可证与再发布边界" class="headerlink" title="1.2 许可证与再发布边界"></a>1.2 许可证与再发布边界</h2><p>源码根目录 <code>LICENSE</code> 是 Apache License 2.0 全文，<br>因此 OpenCV 4.13.0 主体按 Apache License 2.0 授权。</p><p>工程使用时仍应区分三个层面：</p><table><thead><tr><th>层面</th><th>核验内容</th></tr></thead><tbody><tr><td>OpenCV 主体</td><td>根目录 <code>LICENSE</code> 和源文件头部声明</td></tr><tr><td>随源码分发的第三方组件</td><td><code>3rdparty/</code> 下各组件自己的许可证与通知</td></tr><tr><td>系统或外部依赖</td><td>FFmpeg、GStreamer、Qt、OpenVINO、CUDA 等各自的授权和再分发要求</td></tr></tbody></table><p>Apache License 2.0 通常允许使用、修改和再分发，<br>但要求保留适用的版权、许可证和通知，并包含专利条款。<br>本文不构成法律意见；产品发布前应按实际启用的组件生成许可证清单。</p><blockquote><p>注意：OpenCV 的许可证不能替代外部编解码器、模型权重、摄像头 SDK<br>或加速运行时的许可证审查。构建配置不同，最终软件的第三方义务也可能不同。</p></blockquote><h2 id="1-3-核心能力"><a href="#1-3-核心能力" class="headerlink" title="1.3 核心能力"></a>1.3 核心能力</h2><p>OpenCV 4.13.0 主仓库提供的主要能力包括：</p><ul><li>图像和多维数组表示、内存管理、基础算术与线性代数；</li><li>颜色转换、滤波、形态学、阈值、边缘、轮廓和几何变换；</li><li>JPEG、PNG、TIFF、WebP、OpenEXR、AVIF 等格式的条件式接入；</li><li>文件、摄像头、视频流和图像序列的统一输入输出接口；</li><li>关键点、描述子、匹配、单应性和多视图几何；</li><li>相机标定、PnP、立体匹配和三维重建基础算法；</li><li>光流、背景建模、卡尔曼滤波与运动分析；</li><li>级联检测、二维码等目标检测能力；</li><li>SVM、决策树、随机森林和神经网络等传统机器学习；</li><li>图像拼接的特征、估计、接缝、曝光补偿和融合流水线；</li><li>ONNX、TensorFlow、Darknet 等模型格式的导入与前向推理；</li><li>G-API 计算图、流式执行和后端映射；</li><li>CPU SIMD、并行框架、HAL、IPP、OpenCL 和条件式设备后端。</li></ul><h2 id="1-4-能力边界"><a href="#1-4-能力边界" class="headerlink" title="1.4 能力边界"></a>1.4 能力边界</h2><table><thead><tr><th>领域</th><th>OpenCV 的职责</th><th>不应期待的能力</th></tr></thead><tbody><tr><td>经典视觉</td><td>提供算法、数据结构和组合接口</td><td>自动理解所有业务场景</td></tr><tr><td>深度学习</td><td>导入模型并执行推理</td><td>完整训练、分布式训练和实验管理</td></tr><tr><td>图像编解码</td><td>统一格式 API</td><td>任意构建都支持全部格式</td></tr><tr><td>视频与相机</td><td>统一捕获&#x2F;写出接口</td><td>所有设备属性具有一致语义</td></tr><tr><td>GUI</td><td>调试和轻量交互</td><td>完整桌面 UI 框架</td></tr><tr><td>GPU&#x2F;加速</td><td>提供若干计算路径</td><td>自动在所有输入上获得加速</td></tr><tr><td>三维视觉</td><td>标定、几何和部分重建能力</td><td>完整 SLAM 或三维引擎</td></tr><tr><td>扩展算法</td><td>主仓库稳定模块</td><td>自动包含额外模块仓库</td></tr><tr><td>媒体处理</td><td>帧级读写和部分属性控制</td><td>完整转码、编辑和封装工作流</td></tr></tbody></table><p>OpenCV 的重点是“视觉计算构件”。<br>它通常与应用框架、媒体系统、模型训练框架、设备 SDK 和部署运行时组合使用。</p><h2 id="1-5-源码根目录"><a href="#1-5-源码根目录" class="headerlink" title="1.5 源码根目录"></a>1.5 源码根目录</h2><p>以下结构以 OpenCV 4.13.0 发布源码根目录为基准。<br>目录项承担运行代码、构建、测试、文档或发布支持等不同职责：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">opencv-4.13.0/</span><br><span class="line">├── .github/          # GitHub 工作流、议题和贡献协作配置</span><br><span class="line">├── 3rdparty/         # 可随源码构建的第三方组件</span><br><span class="line">├── apps/             # 命令行工具和交互式应用</span><br><span class="line">├── cmake/            # 依赖探测、平台判断、模块和安装逻辑</span><br><span class="line">├── data/             # 级联分类器等运行数据</span><br><span class="line">├── doc/              # 官方文档与教程源文件</span><br><span class="line">├── hal/              # 可选 HAL 实现与适配层</span><br><span class="line">├── include/          # 全局聚合入口，如 opencv2/opencv.hpp</span><br><span class="line">├── modules/          # OpenCV 功能模块主体</span><br><span class="line">├── platforms/        # Android、Apple、Web、Linux 等构建支持</span><br><span class="line">├── samples/          # C++、Python、DNN、GPU 等示例</span><br><span class="line">├── CMakeLists.txt    # 根构建入口</span><br><span class="line">├── CONTRIBUTING.md   # 贡献规则</span><br><span class="line">├── COPYRIGHT         # 版权说明</span><br><span class="line">├── LICENSE           # Apache License 2.0</span><br><span class="line">├── README.md         # 上游项目说明</span><br><span class="line">└── SECURITY.md       # 安全问题报告政策</span><br></pre></td></tr></table></figure><p>发布包、源码归档和版本控制检出可能在隐藏文件或辅助文件上略有差异，<br>但构建和分析的主要入口如上。</p><h3 id="模块内部的常见结构"><a href="#模块内部的常见结构" class="headerlink" title="模块内部的常见结构"></a>模块内部的常见结构</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">modules/&lt;module&gt;/</span><br><span class="line">├── include/opencv2/&lt;module&gt;/  # 对外安装的公开头文件</span><br><span class="line">├── src/                       # 内部头文件与实现</span><br><span class="line">├── test/                      # 正确性、回归和异常测试</span><br><span class="line">├── perf/                      # 性能测试</span><br><span class="line">├── samples/                   # 模块专属示例，可能不存在</span><br><span class="line">├── misc/                      # 绑定、打包或辅助元数据</span><br><span class="line">├── cmake/                     # 模块局部的构建逻辑，可能不存在</span><br><span class="line">└── CMakeLists.txt             # 模块声明和条件依赖</span><br></pre></td></tr></table></figure><p>公开 API 与内部实现并非一一对应。<br>一个声明可能由多个平台文件、dispatch 单元、OpenCL 内核或插件共同实现。</p><h2 id="1-6-模块分层"><a href="#1-6-模块分层" class="headerlink" title="1.6 模块分层"></a>1.6 模块分层</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">flowchart TB</span><br><span class="line">  L0[&quot;应用与语言层&lt;br/&gt;C++ / Python / Java / Objective-C / JavaScript&quot;]</span><br><span class="line">  L1[&quot;接口与适配层&lt;br/&gt;公开头文件、InputArray/OutputArray、生成绑定&quot;]</span><br><span class="line">  L2A[&quot;高级流水线&lt;br/&gt;stitching / objdetect / dnn / gapi&quot;]</span><br><span class="line">  L2B[&quot;视觉算法&lt;br/&gt;imgproc / features2d / calib3d / video / ml&quot;]</span><br><span class="line">  L2C[&quot;I/O 与交互&lt;br/&gt;imgcodecs / videoio / highgui&quot;]</span><br><span class="line">  L3[&quot;基础层&lt;br/&gt;core / flann&quot;]</span><br><span class="line">  L4[&quot;优化与平台层&lt;br/&gt;dispatch / HAL / IPP / OpenCL / 并行&quot;]</span><br><span class="line">  L5[&quot;外部系统&lt;br/&gt;格式库、媒体后端、GUI、设备和计算运行时&quot;]</span><br><span class="line"></span><br><span class="line">  L0 --&gt; L1</span><br><span class="line">  L1 --&gt; L2A</span><br><span class="line">  L1 --&gt; L2B</span><br><span class="line">  L1 --&gt; L2C</span><br><span class="line">  L2A --&gt; L2B</span><br><span class="line">  L2A --&gt; L3</span><br><span class="line">  L2B --&gt; L3</span><br><span class="line">  L2C --&gt; L3</span><br><span class="line">  L3 --&gt; L4</span><br><span class="line">  L2B --&gt; L4</span><br><span class="line">  L2C --&gt; L5</span><br><span class="line">  L2A --&gt; L5</span><br></pre></td></tr></table></figure><p>这是用于理解的逻辑分层，不是严格的无环分层规范。<br>例如某些模块具有可选依赖，G-API 和 DNN 也各自维护后端体系。<br>精确构建关系必须查看模块 <code>CMakeLists.txt</code>。</p><h3 id="基础数据与运行设施"><a href="#基础数据与运行设施" class="headerlink" title="基础数据与运行设施"></a>基础数据与运行设施</h3><p><code>core</code> 是绝大多数代码的共同底座：</p><ul><li><code>Mat</code>、<code>UMat</code>、<code>SparseMat</code>；</li><li><code>InputArray</code>、<code>OutputArray</code>；</li><li>标量、向量、点、尺寸、范围等小型类型；</li><li>算术、归约、矩阵分解和随机数；</li><li>并行接口、TLS、日志和追踪；</li><li>OpenCL 基础设施；</li><li>错误码、异常和构建信息。</li></ul><p><code>flann</code> 提供近似最近邻搜索，常被特征匹配和几何模块使用。</p><h3 id="通用视觉算法"><a href="#通用视觉算法" class="headerlink" title="通用视觉算法"></a>通用视觉算法</h3><p><code>imgproc</code> 构成经典视觉主干。<br><code>features2d</code>、<code>calib3d</code> 和 <code>video</code> 在其上形成特征、几何和时序能力；<br><code>ml</code> 主要依赖 <code>core</code>，提供传统机器学习算法。</p><h3 id="边界与外部系统"><a href="#边界与外部系统" class="headerlink" title="边界与外部系统"></a>边界与外部系统</h3><p><code>imgcodecs</code>、<code>videoio</code>、<code>highgui</code> 位于 OpenCV 与文件、设备、媒体框架和窗口系统的边界。<br>它们的公开接口相对稳定，但实际能力最依赖平台和构建配置。</p><h3 id="高级图与流水线"><a href="#高级图与流水线" class="headerlink" title="高级图与流水线"></a>高级图与流水线</h3><p><code>stitching</code> 组合多个基础模块形成完整拼接流水线。<br><code>dnn</code> 导入并执行神经网络图。<br><code>gapi</code> 将运算表达成计算图并映射到执行后端。<br>三者都不是简单的单函数算法集合。</p><h2 id="1-7-cv-Mat-内存模型"><a href="#1-7-cv-Mat-内存模型" class="headerlink" title="1.7 cv::Mat 内存模型"></a>1.7 <code>cv::Mat</code> 内存模型</h2><h3 id="头部与数据分离"><a href="#头部与数据分离" class="headerlink" title="头部与数据分离"></a>头部与数据分离</h3><p><code>cv::Mat</code> 对象本身是一个矩阵头部，包含：</p><ul><li>类型标志；</li><li>维数、每一维大小；</li><li>行步长或多维步长；</li><li>数据起始、当前视图起始和末端指针；</li><li>指向共享管理块 <code>UMatData</code> 的指针；</li><li>可选的 <code>MatAllocator</code>。</li></ul><p>像素或矩阵元素通常位于独立分配的缓冲区中。<br>因此复制一个 <code>Mat</code> 头部的成本与复制全部像素不同。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  A[&quot;Mat A&lt;br/&gt;rows/cols/type/step/data&quot;] --&gt; U[&quot;UMatData&lt;br/&gt;refcount/allocator/origdata&quot;]</span><br><span class="line">  B[&quot;Mat B：浅拷贝&quot;] --&gt; U</span><br><span class="line">  R[&quot;ROI：偏移后的 data&quot;] --&gt; U</span><br><span class="line">  U --&gt; BUF[&quot;共享数据缓冲区&quot;]</span><br></pre></td></tr></table></figure><p>对应声明集中在：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">modules/core/include/opencv2/core/mat.hpp</span><br></pre></td></tr></table></figure><p>常规创建、释放、复制等实现可从以下文件继续跟踪：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">modules/core/src/matrix.cpp</span><br><span class="line">modules/core/src/matrix_operations.cpp</span><br></pre></td></tr></table></figure><h3 id="浅拷贝、深拷贝和-ROI"><a href="#浅拷贝、深拷贝和-ROI" class="headerlink" title="浅拷贝、深拷贝和 ROI"></a>浅拷贝、深拷贝和 ROI</h3><table><thead><tr><th>操作</th><th>典型语义</th><th>是否共享数据</th></tr></thead><tbody><tr><td>拷贝构造&#x2F;赋值</td><td>复制头部并增加引用计数</td><td>是</td></tr><tr><td><code>row()</code>、<code>col()</code>、<code>operator()(Rect)</code></td><td>创建子矩阵视图</td><td>是</td></tr><tr><td><code>clone()</code></td><td>分配并复制全部有效元素</td><td>否</td></tr><tr><td><code>copyTo()</code></td><td>向目标复制，可触发目标重分配</td><td>通常否</td></tr><tr><td>外部指针构造</td><td>包装用户缓冲区</td><td>由用户保证生命周期</td></tr></tbody></table><p>OpenCV 的 <code>Mat</code> 不提供通用写时复制。<br>两个头部共享缓冲区时，通过任一可写视图修改数据，其他视图都可能看到变化。</p><h3 id="引用计数与生命周期"><a href="#引用计数与生命周期" class="headerlink" title="引用计数与生命周期"></a>引用计数与生命周期</h3><p><code>UMatData</code> 中存在 <code>refcount</code> 和 <code>urefcount</code>，<br>分别参与 <code>Mat</code> 与 <code>UMat</code> 侧的共享管理。<br>引用计数的增减是原子操作，但这不意味着对像素的并发读写自动安全。</p><p>需要区分：</p><ul><li><strong>对象生命周期安全</strong>：不同头部释放共享缓冲区时通过引用计数协调；</li><li><strong>数据竞争安全</strong>：多个线程同时写同一缓冲区仍需应用自行同步；</li><li><strong>外部缓冲区安全</strong>：用用户指针构造时，OpenCV 通常不接管外部内存释放。</li></ul><h3 id="步长与连续性"><a href="#步长与连续性" class="headerlink" title="步长与连续性"></a>步长与连续性</h3><p>二维交错图像常见地址计算为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">address(y, x) = data + y * step[0] + x * elemSize()</span><br></pre></td></tr></table></figure><p>ROI、对齐和外部缓冲区可能使 <code>step[0]</code> 大于一行有效像素字节数。<br>只有 <code>isContinuous()</code> 为真时，才可把所有元素视为单段连续内存处理。</p><p><code>type()</code> 同时编码元素深度和通道数，例如 <code>CV_8UC3</code>。<br><code>elemSize()</code> 是一个完整元素的字节数，<br><code>elemSize1()</code> 是单通道标量的字节数。</p><h3 id="输出分配协议"><a href="#输出分配协议" class="headerlink" title="输出分配协议"></a>输出分配协议</h3><p>大多数函数使用 <code>OutputArray</code> 接收输出。<br>实现常调用目标对象的 <code>create()</code>：</p><ol><li>若现有尺寸和类型匹配，可复用缓冲区；</li><li>否则释放旧引用并重新分配；</li><li>输入输出别名是否允许，必须按具体 API 约定判断。</li></ol><p>不能假设每次函数调用都新建内存，也不能假设所有函数都支持原地执行。</p><h3 id="分配器"><a href="#分配器" class="headerlink" title="分配器"></a>分配器</h3><p><code>MatAllocator</code> 定义分配、释放、映射、上传、下载和复制等接口。<br>默认 CPU <code>Mat</code> 使用标准分配器；<br><code>UMat</code> 可借助分配器和 <code>UMatData</code> 管理主机与设备侧状态。<br>自定义分配器适合特殊内存，但必须严格满足对齐、生命周期和线程约定。</p><h2 id="1-8-UMat-与透明-API"><a href="#1-8-UMat-与透明-API" class="headerlink" title="1.8 UMat 与透明 API"></a>1.8 <code>UMat</code> 与透明 API</h2><p><code>UMat</code> 为 Transparent API（T-API）提供数据载体。<br>当 OpenCL 可用、被启用且具体函数存在适用内核时，<br>使用 <code>UMat</code> 的调用可以进入 OpenCL 路径。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  HOST[&quot;主机数据&quot;] --&gt; U[&quot;UMat / UMatData&quot;]</span><br><span class="line">  U --&gt; OCL[&quot;OpenCL 缓冲区与内核&quot;]</span><br><span class="line">  OCL --&gt; U</span><br><span class="line">  U --&gt; MAP[&quot;getMat()/映射&quot;]</span><br><span class="line">  MAP --&gt; HOST</span><br></pre></td></tr></table></figure><p>应避免在流水线中频繁执行 <code>Mat → UMat → Mat</code>，<br>因为上传、下载、映射和同步可能抵消计算收益。<br>小图、短算子或不支持的类型也可能走 CPU 路径。</p><blockquote><p><code>UMat</code> 是条件式加速机制，不是独立 GPU 数组 API 的同义词。<br>是否启用 OpenCL 可通过 <code>cv::ocl</code> 相关接口和运行日志核验。</p></blockquote><p><code>InputArray</code>、<code>OutputArray</code> 和 <code>InputOutputArray</code> 是统一接收<br><code>Mat</code>、<code>UMat</code>、向量等容器的代理，而非数据所有者。<br>从代理取出特定容器时可能发生映射或复制，别名和临时对象生命周期须按具体 API 处理。</p><h2 id="1-9-错误模型"><a href="#1-9-错误模型" class="headerlink" title="1.9 错误模型"></a>1.9 错误模型</h2><h3 id="C-层"><a href="#C-层" class="headerlink" title="C++ 层"></a>C++ 层</h3><p>OpenCV 使用状态码枚举、断言宏和 <code>cv::Exception</code> 表达错误。<br>常见入口包括：</p><ul><li><code>CV_Error</code>、<code>CV_Error_</code>；</li><li><code>CV_Assert</code>、<code>CV_DbgAssert</code>；</li><li><code>cv::error()</code>；</li><li><code>cv::redirectError()</code>。</li></ul><p>主要声明位于：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">modules/core/include/opencv2/core/base.hpp</span><br><span class="line">modules/core/include/opencv2/core/utility.hpp</span><br></pre></td></tr></table></figure><p>错误通常携带：</p><ul><li>数值状态码；</li><li>错误文本；</li><li>触发函数；</li><li>源文件和行号。</li></ul><p>在正常启用异常的 C++ 构建中，<code>cv::error()</code> 通常抛出 <code>cv::Exception</code>。<br>应用边界应捕获 <code>const cv::Exception&amp;</code>，<br>并同时记录 <code>what()</code>、输入元数据、版本和构建信息。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    cv::Mat image = cv::<span class="built_in">imread</span>(<span class="string">&quot;input.png&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (image.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        <span class="keyword">throw</span> std::<span class="built_in">runtime_error</span>(<span class="string">&quot;image decode returned empty result&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125; <span class="keyword">catch</span> (<span class="type">const</span> cv::Exception&amp; e) &#123;</span><br><span class="line">    std::cerr &lt;&lt; <span class="string">&quot;OpenCV error: &quot;</span> &lt;&lt; e.<span class="built_in">what</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="返回值与异常并存"><a href="#返回值与异常并存" class="headerlink" title="返回值与异常并存"></a>返回值与异常并存</h3><p>并非所有失败都抛异常：</p><ul><li><code>imread()</code> 解码失败常返回空 <code>Mat</code>；</li><li><code>VideoCapture::open()</code>、<code>read()</code> 返回 <code>bool</code>；</li><li>查询属性可能返回特殊值；</li><li>某些后端错误仅写日志。</li></ul><p>因此必须同时检查返回值、输出是否为空和异常。</p><h3 id="断言不是输入校验策略"><a href="#断言不是输入校验策略" class="headerlink" title="断言不是输入校验策略"></a>断言不是输入校验策略</h3><p><code>CV_Assert</code> 主要用于库内部前置条件。<br>应用对外部文件、网络输入和用户参数仍应主动校验，<br>不要依赖断言消息构建业务错误协议。</p><h2 id="1-10-语言绑定"><a href="#1-10-语言绑定" class="headerlink" title="1.10 语言绑定"></a>1.10 语言绑定</h2><p>OpenCV 以 C++ API 为源头，通过模块声明和绑定生成器提供其他语言接口。<br>模块 CMake 中的 <code>WRAP</code> 列表表示该模块计划参与哪些绑定，<br>但最终可用性仍受 API 可包装性、平台和构建选项影响。</p><table><thead><tr><th>语言&#x2F;环境</th><th>主要组织位置</th><th>特点</th></tr></thead><tbody><tr><td>C++</td><td>各模块 <code>include/opencv2/</code></td><td>原生 API，能力最完整</td></tr><tr><td>Python</td><td><code>modules/python/</code> 与模块包装元数据</td><td><code>cv2</code> 接口，数组常与 NumPy 协作</td></tr><tr><td>Java</td><td><code>modules/java/</code> 与生成规则</td><td>JNI 包装，需关注原生对象释放</td></tr><tr><td>Objective-C</td><td><code>modules/objc/</code> 与 <code>WRAP objc</code></td><td>面向 Apple 平台</td></tr><tr><td>JavaScript</td><td><code>platforms/js/</code>、<code>WRAP js</code></td><td>通常基于 Emscripten&#x2F;WASM，模块受裁剪</td></tr></tbody></table><p>Python 绑定常将 C++ 异常转换为 <code>cv2.error</code>。<br>Java 包装持有原生资源时需要遵循对应生命周期接口。<br>JavaScript 构建通常只包含显式白名单中的能力。</p><blockquote><p><code>WRAP python</code> 不表示所有重载都能原样出现在 Python。<br>模板、指针、回调和复杂容器可能需要专门包装或根本不导出。</p></blockquote><h2 id="1-11-构建与产物概览"><a href="#1-11-构建与产物概览" class="headerlink" title="1.11 构建与产物概览"></a>1.11 构建与产物概览</h2><p>根 <code>CMakeLists.txt</code> 负责：</p><ol><li>检查平台、编译器和最低依赖版本；</li><li>建立构建选项；</li><li>探测 CPU 特性和第三方库；</li><li>扫描模块并解析依赖；</li><li>生成配置头、模块目标、绑定、测试和安装规则；</li><li>输出构建摘要。</li></ol><p>典型产物包括：</p><ul><li><code>opencv_core</code>、<code>opencv_imgproc</code> 等模块库；</li><li>可选的单体 <code>opencv_world</code>；</li><li>Python&#x2F;Java 等绑定；</li><li>视频、GUI 或并行后端插件；</li><li>工具、示例和测试程序；</li><li>CMake 包配置和 <code>pkg-config</code> 元数据（按配置生成）。</li></ul><p>源码支持、构建启用、产物存在和运行时选中是四个不同状态。</p><h2 id="1-12-源码阅读路线"><a href="#1-12-源码阅读路线" class="headerlink" title="1.12 源码阅读路线"></a>1.12 源码阅读路线</h2><h3 id="路线-A：应用开发"><a href="#路线-A：应用开发" class="headerlink" title="路线 A：应用开发"></a>路线 A：应用开发</h3><ol><li>掌握 <code>Mat</code> 的类型、步长、ROI 和复制语义；</li><li>跑通 <code>imgcodecs → imgproc → highgui/imgcodecs</code>；</li><li>建立返回值和异常的双重检查；</li><li>再进入特征、标定、视频或 DNN 专题。</li></ol><h3 id="路线-B：定位一个-API"><a href="#路线-B：定位一个-API" class="headerlink" title="路线 B：定位一个 API"></a>路线 B：定位一个 API</h3><ol><li>在 <code>modules/&lt;module&gt;/include/</code> 找声明；</li><li>在模块 <code>CMakeLists.txt</code> 确认依赖和条件；</li><li>在 <code>src/</code> 找同名函数或类方法；</li><li>跟踪 <code>dispatch.cpp</code>、<code>simd.hpp</code>、HAL 或 OpenCL 分支；</li><li>阅读 <code>test/</code> 确认行为；</li><li>阅读 <code>perf/</code> 确认主要数据规模。</li></ol><h3 id="路线-C：平台适配"><a href="#路线-C：平台适配" class="headerlink" title="路线 C：平台适配"></a>路线 C：平台适配</h3><ol><li>阅读根 CMake 和 <code>cmake/</code> 中的平台探测；</li><li>区分内建后端与插件后端；</li><li>明确外部库版本、链接方式和部署目录；</li><li>用构建信息确认能力；</li><li>在目标设备验证格式、摄像头、窗口和加速路径。</li></ol><h3 id="路线-D：性能优化"><a href="#路线-D：性能优化" class="headerlink" title="路线 D：性能优化"></a>路线 D：性能优化</h3><ol><li>测量端到端和单算子基线；</li><li>检查不必要的深拷贝、布局转换和同步；</li><li>查看 CPU dispatch、HAL、IPP、OpenCL 或设备后端；</li><li>验证线程数和并行后端；</li><li>同时检查速度、内存、精度和冷启动。</li></ol><h2 id="1-13-阅读时的注意事项"><a href="#1-13-阅读时的注意事项" class="headerlink" title="1.13 阅读时的注意事项"></a>1.13 阅读时的注意事项</h2><ul><li>不要仅凭头文件判断实际实现；</li><li>不要仅凭 <code>WITH_*</code> 选项判断依赖已找到；</li><li>不要把 <code>HAVE_*</code> 宏跨构建环境外推；</li><li>不要假设 ROI 连续；</li><li>不要把引用计数安全等同于数据线程安全；</li><li>不要假设所有后端接受完全相同的属性；</li><li>不要把 DNN 后端偏好当成不回退的强制契约；</li><li>不要忽略首次初始化和数据搬运成本；</li><li>不要用主仓库结论覆盖额外模块；</li><li>不要在版本升级后沿用未经核验的源码路径。</li></ul><h2 id="1-14-后续阅读"><a href="#1-14-后续阅读" class="headerlink" title="1.14 后续阅读"></a>1.14 后续阅读</h2><ul><li>模块依赖、数据流、插件和执行路径：<code>02_系统架构.md</code></li><li>主要模块内部实现：<code>03_核心模块详解.md</code></li><li>按业务任务组合算法：<code>04_算法流水线.md</code></li><li>HAL、SIMD、并行与加速：<code>05_HAL与性能优化.md</code></li><li>构建、调试、测试和部署：<code>06_配置与使用.md</code></li><li>API 与实现文件定位：<code>07_源码文件索引.md</code></li></ul>]]>
    </content>
    <id>http://example.com/n/1200/</id>
    <link href="http://example.com/n/1200/"/>
    <published>2026-09-16T03:00:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="01-OpenCV-4-13-0-系统概述"><a href="#01-OpenCV-4-13-0-系统概述" class="headerlink" title="01 OpenCV 4.13.0 系统概述"></a>01 OpenCV 4.13.0 系统概述</]]>
    </summary>
    <title>01 OpenCV 4.13.0 系统概述</title>
    <updated>2026-09-16T03:49:31.688Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/YOLO/"/>
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    <category term="YOLO" scheme="http://example.com/tags/YOLO/"/>
    <content>
      <![CDATA[<h1 id="01-系统概述"><a href="#01-系统概述" class="headerlink" title="01 系统概述"></a>01 系统概述</h1><h2 id="1-1-项目定位"><a href="#1-1-项目定位" class="headerlink" title="1.1 项目定位"></a>1.1 项目定位</h2><p>YOLOv5 是 Ultralytics 基于 PyTorch 实现的实时视觉框架。当前源码对应 <strong>release v7.0</strong>，核心任务包括：</p><ul><li><strong>目标检测</strong>：<code>train.py</code>、<code>val.py</code>、<code>detect.py</code></li><li><strong>实例分割</strong>：<code>segment/train.py</code>、<code>segment/val.py</code>、<code>segment/predict.py</code></li><li><strong>图像分类</strong>：<code>classify/train.py</code>、<code>classify/val.py</code>、<code>classify/predict.py</code></li><li><strong>模型导出</strong>：<code>export.py</code></li><li><strong>多后端推理</strong>：<code>models/common.py::DetectMultiBackend</code></li></ul><p>该版本的主要发布特性是加入 YOLOv5-seg 实例分割模型。</p><h2 id="1-2-版本与许可证"><a href="#1-2-版本与许可证" class="headerlink" title="1.2 版本与许可证"></a>1.2 版本与许可证</h2><table><thead><tr><th>项</th><th>内容</th></tr></thead><tbody><tr><td>版本</td><td>YOLOv5 v7.0</td></tr><tr><td>语言</td><td>Python</td></tr><tr><td>训练框架</td><td>PyTorch</td></tr><tr><td>许可证</td><td>GPL-3.0</td></tr><tr><td>Python 要求</td><td>README 声明 Python ≥ 3.7</td></tr><tr><td>PyTorch 要求</td><td><code>torch&gt;=1.7.0</code></td></tr></tbody></table><p>源码中的模型、脚本和文档均标注 GPL-3.0。商业产品集成前应核对许可证义务。</p><h2 id="1-3-根目录结构"><a href="#1-3-根目录结构" class="headerlink" title="1.3 根目录结构"></a>1.3 根目录结构</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">yolov5-7.0/</span><br><span class="line">├── train.py                 # 检测训练</span><br><span class="line">├── val.py                   # 检测验证</span><br><span class="line">├── detect.py                # 检测推理</span><br><span class="line">├── export.py                # 多格式导出</span><br><span class="line">├── benchmarks.py            # 导出格式性能/精度测试</span><br><span class="line">├── hubconf.py               # PyTorch Hub 入口</span><br><span class="line">├── sample_detect.py         # 本仓库增加的本地推理示例</span><br><span class="line">├── models/</span><br><span class="line">│   ├── yolo.py              # Detect/Segment/模型解析</span><br><span class="line">│   ├── common.py            # 网络块、多后端、AutoShape</span><br><span class="line">│   ├── experimental.py      # 权重加载、模型集成</span><br><span class="line">│   ├── tf.py                # TensorFlow/Keras 对应实现</span><br><span class="line">│   ├── yolov5&#123;n,s,m,l,x&#125;.yaml</span><br><span class="line">│   ├── segment/             # 分割模型 YAML</span><br><span class="line">│   └── hub/                 # P6/P7/实验结构</span><br><span class="line">├── utils/</span><br><span class="line">│   ├── dataloaders.py       # 数据集、图片/视频/流加载</span><br><span class="line">│   ├── augmentations.py     # Letterbox、Mosaic、几何增强</span><br><span class="line">│   ├── loss.py              # 检测损失与目标匹配</span><br><span class="line">│   ├── general.py           # NMS、坐标、检查与通用工具</span><br><span class="line">│   ├── metrics.py           # IoU、AP、混淆矩阵</span><br><span class="line">│   ├── plots.py             # 绘图与 Annotator</span><br><span class="line">│   ├── torch_utils.py       # 设备、EMA、DDP、优化器</span><br><span class="line">│   ├── autoanchor.py        # Anchor 检查与进化</span><br><span class="line">│   ├── callbacks.py         # 训练生命周期回调</span><br><span class="line">│   ├── loggers/             # TensorBoard/ClearML/Comet/W&amp;B</span><br><span class="line">│   └── segment/             # 分割损失、数据与指标</span><br><span class="line">├── data/</span><br><span class="line">│   ├── coco.yaml            # 数据集定义</span><br><span class="line">│   ├── coco128.yaml         # 小型入门数据集</span><br><span class="line">│   ├── coco128-seg.yaml</span><br><span class="line">│   ├── hyps/                # 训练超参数</span><br><span class="line">│   └── scripts/             # 数据/权重下载脚本</span><br><span class="line">├── segment/                 # 分割任务入口</span><br><span class="line">├── classify/                # 分类任务入口</span><br><span class="line">├── requirements.txt</span><br><span class="line">└── README.md</span><br></pre></td></tr></table></figure><h2 id="1-4-主要依赖"><a href="#1-4-主要依赖" class="headerlink" title="1.4 主要依赖"></a>1.4 主要依赖</h2><table><thead><tr><th>依赖</th><th>用途</th></tr></thead><tbody><tr><td>PyTorch &#x2F; torchvision</td><td>模型、训练、AMP、数据接口</td></tr><tr><td>OpenCV</td><td>图像与视频读写、缩放、绘图</td></tr><tr><td>NumPy &#x2F; SciPy</td><td>数组与科学计算</td></tr><tr><td>PyYAML</td><td>模型、数据集、超参数配置</td></tr><tr><td>Pillow</td><td>PIL 图像及 AutoShape 输入</td></tr><tr><td>matplotlib &#x2F; seaborn &#x2F; pandas</td><td>可视化与统计</td></tr><tr><td>tqdm</td><td>训练进度条</td></tr><tr><td>thop</td><td>参数量与 FLOPs 统计</td></tr><tr><td>tensorboard</td><td>训练日志</td></tr></tbody></table><p>ONNX、TensorRT、OpenVINO、CoreML、TensorFlow、Paddle、Triton 等是按导出&#x2F;部署目标选装的依赖。</p><h2 id="1-5-三类任务"><a href="#1-5-三类任务" class="headerlink" title="1.5 三类任务"></a>1.5 三类任务</h2><h3 id="检测"><a href="#检测" class="headerlink" title="检测"></a>检测</h3><p>输出每个候选框的：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(x, y, w, h, objectness, class scores...)</span><br></pre></td></tr></table></figure><p>经 NMS 后成为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(x1, y1, x2, y2, confidence, class_id)</span><br></pre></td></tr></table></figure><h3 id="实例分割"><a href="#实例分割" class="headerlink" title="实例分割"></a>实例分割</h3><p><code>Segment</code> 继承 <code>Detect</code>，除检测输出外增加：</p><ul><li>每个候选实例的 mask 系数</li><li><code>Proto</code> 生成的共享原型掩码</li></ul><p>预测阶段用 mask 系数线性组合原型，再裁剪到框内。</p><h3 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h3><p><code>ClassificationModel</code> 可截取检测模型的 backbone，并将最后一层替换为 <code>Classify</code> 头。</p><h2 id="1-6-模型规模"><a href="#1-6-模型规模" class="headerlink" title="1.6 模型规模"></a>1.6 模型规模</h2><p>P5 检测模型包括：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yolov5n → yolov5s → yolov5m → yolov5l → yolov5x</span><br></pre></td></tr></table></figure><p>它们主要共享拓扑，通过 YAML 中：</p><ul><li><code>depth_multiple</code>：缩放模块重复次数</li><li><code>width_multiple</code>：缩放输出通道</li></ul><p>实现从轻量到高精度的系列化。</p><h2 id="1-7-核心设计思想"><a href="#1-7-核心设计思想" class="headerlink" title="1.7 核心设计思想"></a>1.7 核心设计思想</h2><p>一句话概括：</p><blockquote><p>用 YAML 描述网络图，<code>parse_model()</code> 动态创建 PyTorch 模型；用锚框三尺度头完成密集预测；训练端以 CIoU、Objectness BCE、Class BCE 联合优化；部署端通过 <code>DetectMultiBackend</code> 隔离不同推理运行时。</p></blockquote>]]>
    </content>
    <id>http://example.com/n/1220/</id>
    <link href="http://example.com/n/1220/"/>
    <published>2026-09-16T03:00:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="01-系统概述"><a href="#01-系统概述" class="headerlink" title="01 系统概述"></a>01 系统概述</h1><h2 id="1-1-项目定位"><a href="#1-1-项目定位" class="headerli]]>
    </summary>
    <title>YOLOv5 7.0：系统概述</title>
    <updated>2026-09-16T03:49:31.700Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="工业协议" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/MQTT/"/>
    <category term="工业协议" scheme="http://example.com/tags/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/tags/MQTT/"/>
    <content>
      <![CDATA[<h1 id="Reason-Code-与-Properties-目录（MQTT-5）"><a href="#Reason-Code-与-Properties-目录（MQTT-5）" class="headerlink" title="Reason Code 与 Properties 目录（MQTT 5）"></a>Reason Code 与 Properties 目录（MQTT 5）</h1><blockquote><p>依据 OASIS MQTT 5.0 <strong>§2.2.2 Properties</strong>、<strong>§2.4 Reason Code</strong> 及各控制报文章节整理<br>完整规范性定义以正式 HTML&#x2F;PDF 为准：<br><a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html">https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html</a><br>MQTT 3.1.1 <strong>无</strong>本目录所述 Properties &#x2F; 细粒度 Reason Code 体系</p></blockquote><hr><h2 id="1-Reason-Code-使用位置"><a href="#1-Reason-Code-使用位置" class="headerlink" title="1. Reason Code 使用位置"></a>1. Reason Code 使用位置</h2><table><thead><tr><th>报文</th><th>是否常见带 Reason</th></tr></thead><tbody><tr><td>CONNACK</td><td>Connect Reason Code</td></tr><tr><td>PUBACK &#x2F; PUBREC &#x2F; PUBREL &#x2F; PUBCOMP</td><td>发布流 Reason</td></tr><tr><td>SUBACK &#x2F; UNSUBACK</td><td>每订阅&#x2F;每过滤一项</td></tr><tr><td>DISCONNECT</td><td>断开原因</td></tr><tr><td>AUTH</td><td>认证步骤结果</td></tr></tbody></table><p><code>0x00</code> 在多数上下文表示成功；<code>0x80</code> 及以上通常表示错误（具体以该报文章节表格为准）。</p><hr><h2 id="2-常用-Reason-Code-速查（跨报文高频）"><a href="#2-常用-Reason-Code-速查（跨报文高频）" class="headerlink" title="2. 常用 Reason Code 速查（跨报文高频）"></a>2. 常用 Reason Code 速查（跨报文高频）</h2><table><thead><tr><th>Code</th><th>名称（英文习惯）</th><th>典型场景</th></tr></thead><tbody><tr><td>0x00</td><td>Success &#x2F; Normal disconnection &#x2F; Granted QoS0</td><td>成功</td></tr><tr><td>0x01</td><td>Granted QoS 1</td><td>SUBACK</td></tr><tr><td>0x02</td><td>Granted QoS 2</td><td>SUBACK</td></tr><tr><td>0x04</td><td>Disconnect with Will Message</td><td>DISCONNECT</td></tr><tr><td>0x10</td><td>No matching subscribers</td><td>PUBACK&#x2F;PUBREC</td></tr><tr><td>0x11</td><td>No subscription existed</td><td>UNSUBACK</td></tr><tr><td>0x18</td><td>Continue authentication</td><td>AUTH</td></tr><tr><td>0x19</td><td>Re-authenticate</td><td>AUTH</td></tr><tr><td>0x80</td><td>Unspecified error</td><td>多处</td></tr><tr><td>0x81</td><td>Malformed Packet</td><td>解析失败</td></tr><tr><td>0x82</td><td>Protocol Error</td><td>协议违规</td></tr><tr><td>0x83</td><td>Implementation specific error</td><td>实现特定</td></tr><tr><td>0x84</td><td>Unsupported Protocol Version</td><td>CONNACK</td></tr><tr><td>0x85</td><td>Client Identifier not valid</td><td>CONNACK</td></tr><tr><td>0x86</td><td>Bad User Name or Password</td><td>CONNACK</td></tr><tr><td>0x87</td><td>Not authorized</td><td>鉴权失败</td></tr><tr><td>0x88</td><td>Server unavailable</td><td>CONNACK</td></tr><tr><td>0x89</td><td>Server busy</td><td>CONNACK &#x2F; DISCONNECT</td></tr><tr><td>0x8A</td><td>Banned</td><td>CONNACK</td></tr><tr><td>0x8B</td><td>Server shutting down &#x2F; Keep Alive timeout</td><td>视报文</td></tr><tr><td>0x8C</td><td>Bad authentication method</td><td>CONNACK</td></tr><tr><td>0x8D</td><td>Session taken over</td><td>DISCONNECT</td></tr><tr><td>0x8F</td><td>Topic Filter invalid</td><td>SUBACK 等</td></tr><tr><td>0x90</td><td>Topic Name invalid</td><td>PUBLISH 相关</td></tr><tr><td>0x91</td><td>Packet Identifier in use</td><td>订阅&#x2F;发布</td></tr><tr><td>0x93</td><td>Receive Maximum exceeded</td><td>流控</td></tr><tr><td>0x94</td><td>Topic Alias invalid</td><td>PUBLISH</td></tr><tr><td>0x95</td><td>Packet too large</td><td>包长</td></tr><tr><td>0x97</td><td>Quota exceeded</td><td>配额</td></tr><tr><td>0x99</td><td>Payload format invalid</td><td>载荷格式</td></tr><tr><td>0x9A</td><td>Retain not supported</td><td>CONNACK&#x2F;相关</td></tr><tr><td>0x9B</td><td>QoS not supported</td><td>CONNACK</td></tr><tr><td>0x9C</td><td>Use another server</td><td>重定向</td></tr><tr><td>0x9D</td><td>Server moved</td><td>重定向</td></tr><tr><td>0x9E</td><td>Shared Subscriptions not supported</td><td>SUBACK</td></tr><tr><td>0x9F</td><td>Connection rate exceeded</td><td>CONNACK</td></tr><tr><td>0xA1</td><td>Subscription Identifiers not supported</td><td>SUBACK</td></tr><tr><td>0xA2</td><td>Wildcard Subscriptions not supported</td><td>SUBACK</td></tr></tbody></table><blockquote><p>同一数值在不同报文中的<strong>官方名称</strong>可能略有差别；排障时以该报文章节的 Reason Code 表为准。</p></blockquote><hr><h2 id="3-Property-Identifier-目录（常用）"><a href="#3-Property-Identifier-目录（常用）" class="headerlink" title="3. Property Identifier 目录（常用）"></a>3. Property Identifier 目录（常用）</h2><table><thead><tr><th>ID</th><th>属性名</th><th>值类型</th><th>典型报文</th></tr></thead><tbody><tr><td>0x01</td><td>Payload Format Indicator</td><td>Byte</td><td>PUBLISH, Will</td></tr><tr><td>0x02</td><td>Message Expiry Interval</td><td>Four Byte</td><td>PUBLISH, Will</td></tr><tr><td>0x03</td><td>Content Type</td><td>UTF-8 String</td><td>PUBLISH, Will</td></tr><tr><td>0x08</td><td>Response Topic</td><td>UTF-8 String</td><td>PUBLISH, Will</td></tr><tr><td>0x09</td><td>Correlation Data</td><td>Binary</td><td>PUBLISH, Will</td></tr><tr><td>0x0B</td><td>Subscription Identifier</td><td>Var Byte Int</td><td>SUBSCRIBE, PUBLISH</td></tr><tr><td>0x11</td><td>Session Expiry Interval</td><td>Four Byte</td><td>CONNECT, CONNACK, DISCONNECT</td></tr><tr><td>0x12</td><td>Assigned Client Identifier</td><td>UTF-8 String</td><td>CONNACK</td></tr><tr><td>0x13</td><td>Server Keep Alive</td><td>Two Byte</td><td>CONNACK</td></tr><tr><td>0x15</td><td>Authentication Method</td><td>UTF-8 String</td><td>CONNECT, CONNACK, AUTH</td></tr><tr><td>0x16</td><td>Authentication Data</td><td>Binary</td><td>CONNECT, CONNACK, AUTH</td></tr><tr><td>0x17</td><td>Request Problem Information</td><td>Byte</td><td>CONNECT</td></tr><tr><td>0x18</td><td>Will Delay Interval</td><td>Four Byte</td><td>Will Properties</td></tr><tr><td>0x19</td><td>Request Response Information</td><td>Byte</td><td>CONNECT</td></tr><tr><td>0x1A</td><td>Response Information</td><td>UTF-8 String</td><td>CONNACK</td></tr><tr><td>0x1C</td><td>Server Reference</td><td>UTF-8 String</td><td>CONNACK, DISCONNECT</td></tr><tr><td>0x1F</td><td>Reason String</td><td>UTF-8 String</td><td>多种 ACK&#x2F;DISCONNECT</td></tr><tr><td>0x21</td><td>Receive Maximum</td><td>Two Byte</td><td>CONNECT, CONNACK</td></tr><tr><td>0x22</td><td>Topic Alias Maximum</td><td>Two Byte</td><td>CONNECT, CONNACK</td></tr><tr><td>0x23</td><td>Topic Alias</td><td>Two Byte</td><td>PUBLISH</td></tr><tr><td>0x24</td><td>Maximum QoS</td><td>Byte</td><td>CONNACK</td></tr><tr><td>0x25</td><td>Retain Available</td><td>Byte</td><td>CONNACK</td></tr><tr><td>0x26</td><td>User Property</td><td>UTF-8 String Pair</td><td>多处（可重复）</td></tr><tr><td>0x27</td><td>Maximum Packet Size</td><td>Four Byte</td><td>CONNECT, CONNACK</td></tr><tr><td>0x28</td><td>Wildcard Subscription Available</td><td>Byte</td><td>CONNACK</td></tr><tr><td>0x29</td><td>Subscription Identifier Available</td><td>Byte</td><td>CONNACK</td></tr><tr><td>0x2A</td><td>Shared Subscription Available</td><td>Byte</td><td>CONNACK</td></tr></tbody></table><p>未列出的 Identifier 见规范完整表；实现必须忽略无法识别属性或按规范报错（视报文规则）。</p><hr><h2 id="4-与本库其它文档"><a href="#4-与本库其它文档" class="headerlink" title="4. 与本库其它文档"></a>4. 与本库其它文档</h2><table><thead><tr><th>主题</th><th>文档</th></tr></thead><tbody><tr><td>报文总结构</td><td><a href="/n/1170/">10-MQTT控制报文格式总览.md</a></td></tr><tr><td>连接</td><td><a href="/n/1171/">11</a></td></tr><tr><td>发布&#x2F;QoS</td><td><a href="/n/1172/">12</a></td></tr><tr><td>订阅</td><td><a href="/n/1173/">13</a></td></tr><tr><td>心跳&#x2F;断开&#x2F;认证</td><td><a href="/n/1174/">14</a></td></tr><tr><td>5.0 特性综述</td><td><a href="/n/1164/">04-MQTT5新特性.md</a></td></tr><tr><td>正式规范链接</td><td><a href="/n/1169/">09-规范与资料索引.md</a></td></tr></tbody></table><hr><h2 id="5-合规声明"><a href="#5-合规声明" class="headerlink" title="5. 合规声明"></a>5. 合规声明</h2><p>本目录为便于联调的<strong>速查整理</strong>。字段强制条件、默认值、哪些属性可重复、错误时关闭连接还是仅丢包等，<strong>一律以 OASIS MQTT 5.0 正式文本对应章节的 Normative 表述为准</strong>。</p>]]>
    </content>
    <id>http://example.com/n/1175/</id>
    <link href="http://example.com/n/1175/"/>
    <published>2026-09-16T02:15:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="Reason-Code-与-Properties-目录（MQTT-5）"><a href="#Reason-Code-与-Properties-目录（MQTT-5）" class="headerlink" title="Reason Code 与 Properti]]>
    </summary>
    <title>Reason Code 与 Properties 目录（MQTT 5）</title>
    <updated>2026-09-16T02:53:51.281Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="工业协议" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/MQTT/"/>
    <category term="工业协议" scheme="http://example.com/tags/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/tags/MQTT/"/>
    <content>
      <![CDATA[<h1 id="PING-DISCONNECT-AUTH-报文格式"><a href="#PING-DISCONNECT-AUTH-报文格式" class="headerlink" title="PING &#x2F; DISCONNECT &#x2F; AUTH 报文格式"></a>PING &#x2F; DISCONNECT &#x2F; AUTH 报文格式</h1><blockquote><p>OASIS MQTT 5.0：<strong>§3.12 PINGREQ</strong>、<strong>§3.13 PINGRESP</strong>、<strong>§3.14 DISCONNECT</strong>、<strong>§3.15 AUTH</strong><br>Keep Alive &#x2F; 会话行为见：<a href="/n/1162/">02-控制报文与会话.md</a>、<a href="/n/1171/">11-CONNECT与CONNACK报文格式.md</a></p></blockquote><hr><h2 id="1-PINGREQ（§3-12）"><a href="#1-PINGREQ（§3-12）" class="headerlink" title="1. PINGREQ（§3.12）"></a>1. PINGREQ（§3.12）</h2><table><thead><tr><th>项</th><th>值</th></tr></thead><tbody><tr><td>Type</td><td><code>12</code></td></tr><tr><td>Flags</td><td><code>0000</code></td></tr><tr><td>Remaining Length</td><td><strong>0</strong></td></tr><tr><td>Variable Header &#x2F; Payload</td><td><strong>无</strong></td></tr></tbody></table><p>用途：在 Keep Alive 周期内保活；证明 Client 存活且连接可用。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Fixed Header 仅 2 字节：0xC0 0x00</span><br></pre></td></tr></table></figure><hr><h2 id="2-PINGRESP（§3-13）"><a href="#2-PINGRESP（§3-13）" class="headerlink" title="2. PINGRESP（§3.13）"></a>2. PINGRESP（§3.13）</h2><table><thead><tr><th>项</th><th>值</th></tr></thead><tbody><tr><td>Type</td><td><code>13</code></td></tr><tr><td>Flags</td><td><code>0000</code></td></tr><tr><td>Remaining Length</td><td><strong>0</strong></td></tr></tbody></table><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Fixed Header：0xD0 0x00</span><br></pre></td></tr></table></figure><p>Server 必须响应 PINGREQ。Client 若收不到 PINGRESP，应按规范处理为连接故障。</p><hr><h2 id="3-DISCONNECT（§3-14）"><a href="#3-DISCONNECT（§3-14）" class="headerlink" title="3. DISCONNECT（§3.14）"></a>3. DISCONNECT（§3.14）</h2><h3 id="3-1-方向"><a href="#3-1-方向" class="headerlink" title="3.1 方向"></a>3.1 方向</h3><ul><li><strong>MQTT 5</strong>：Client→Server <strong>与</strong> Server→Client 均可发送  </li><li><strong>MQTT 3.1.1</strong>：主要是 Client→Server；且报文极简</li></ul><h3 id="3-2-Fixed-Header"><a href="#3-2-Fixed-Header" class="headerlink" title="3.2 Fixed Header"></a>3.2 Fixed Header</h3><p>Type&#x3D;<code>14</code>，Flags&#x3D;<code>0000</code>。</p><h3 id="3-3-Variable-Header（MQTT-5）"><a href="#3-3-Variable-Header（MQTT-5）" class="headerlink" title="3.3 Variable Header（MQTT 5）"></a>3.3 Variable Header（MQTT 5）</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Reason Code (1 byte) → Properties</span><br></pre></td></tr></table></figure><p>Remaining Length 可为 0（等价 Reason&#x3D;<code>0x00</code> 且无属性，规范允许的简写形式）。</p><h4 id="常见-Reason-Code"><a href="#常见-Reason-Code" class="headerlink" title="常见 Reason Code"></a>常见 Reason Code</h4><table><thead><tr><th>Code</th><th>含义（示例）</th></tr></thead><tbody><tr><td><code>0x00</code></td><td>Normal disconnection</td></tr><tr><td><code>0x04</code></td><td>Disconnect with Will Message（Client 可请求仍发 Will）</td></tr><tr><td><code>0x80</code></td><td>Unspecified error</td></tr><tr><td><code>0x81</code></td><td>Malformed Packet</td></tr><tr><td><code>0x82</code></td><td>Protocol Error</td></tr><tr><td><code>0x87</code></td><td>Not authorized</td></tr><tr><td><code>0x88</code></td><td>Server busy</td></tr><tr><td><code>0x89</code></td><td>Server shutting down</td></tr><tr><td><code>0x8B</code></td><td>Keep Alive timeout（Server→Client）</td></tr><tr><td><code>0x8D</code></td><td>Session taken over</td></tr><tr><td><code>0x8E</code></td><td>Topic Filter invalid</td></tr><tr><td><code>0x90</code></td><td>Topic Name invalid</td></tr><tr><td><code>0x93</code></td><td>Receive Maximum exceeded</td></tr><tr><td><code>0x94</code></td><td>Topic Alias invalid</td></tr><tr><td><code>0x95</code></td><td>Packet too large</td></tr><tr><td><code>0x96</code></td><td>Message rate too high</td></tr><tr><td><code>0x98</code></td><td>Administrative action</td></tr><tr><td><code>0x9C</code></td><td>Use another server</td></tr><tr><td><code>0x9D</code></td><td>Server moved</td></tr><tr><td><code>0xA0</code></td><td>Maximum connect time</td></tr><tr><td><code>0xA1</code></td><td>Subscription Identifiers not supported 等</td></tr></tbody></table><h4 id="常见-Properties"><a href="#常见-Properties" class="headerlink" title="常见 Properties"></a>常见 Properties</h4><table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td>Session Expiry Interval</td><td>Client 可在断开时改会话过期（有条件）</td></tr><tr><td>Reason String</td><td>可读原因</td></tr><tr><td>User Property</td><td>自定义</td></tr><tr><td>Server Reference</td><td>指向另一服务器</td></tr></tbody></table><h3 id="3-4-正常断开-vs-异常断开"><a href="#3-4-正常断开-vs-异常断开" class="headerlink" title="3.4 正常断开 vs 异常断开"></a>3.4 正常断开 vs 异常断开</h3><table><thead><tr><th>情况</th><th>Will</th></tr></thead><tbody><tr><td>发送 DISCONNECT（正常原因）后关连接</td><td>通常<strong>不</strong>发布 Will</td></tr><tr><td>网络中断 &#x2F; Keep Alive 超时 &#x2F; 未发 DISCONNECT</td><td>可触发 Will（若已配置）</td></tr></tbody></table><p>MQTT 5 的 <code>0x04 Disconnect with Will Message</code> 允许显式要求发送 Will。</p><h3 id="3-5-MQTT-3-1-1-DISCONNECT"><a href="#3-5-MQTT-3-1-1-DISCONNECT" class="headerlink" title="3.5 MQTT 3.1.1 DISCONNECT"></a>3.5 MQTT 3.1.1 DISCONNECT</h3><ul><li>仅 Fixed Header：<code>0xE0 0x00</code>  </li><li>无 Reason &#x2F; Properties</li></ul><hr><h2 id="4-AUTH（§3-15，仅-MQTT-5）"><a href="#4-AUTH（§3-15，仅-MQTT-5）" class="headerlink" title="4. AUTH（§3.15，仅 MQTT 5）"></a>4. AUTH（§3.15，仅 MQTT 5）</h2><p>用于 <strong>Enhanced Authentication</strong> 多步交换（CONNECT 中声明 Authentication Method）。</p><h3 id="4-1-Fixed-Header"><a href="#4-1-Fixed-Header" class="headerlink" title="4.1 Fixed Header"></a>4.1 Fixed Header</h3><p>Type&#x3D;<code>15</code>，Flags&#x3D;<code>0000</code>。</p><h3 id="4-2-Variable-Header"><a href="#4-2-Variable-Header" class="headerlink" title="4.2 Variable Header"></a>4.2 Variable Header</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Authenticate Reason Code → Properties</span><br></pre></td></tr></table></figure><table><thead><tr><th>Reason（例）</th><th>含义</th></tr></thead><tbody><tr><td><code>0x00</code></td><td>Success</td></tr><tr><td><code>0x18</code></td><td>Continue authentication</td></tr><tr><td><code>0x19</code></td><td>Re-authenticate</td></tr></tbody></table><p>Properties 必含&#x2F;常含：</p><table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td>Authentication Method</td><td>方法名（与 CONNECT 一致）</td></tr><tr><td>Authentication Data</td><td>方法相关二进制挑战&#x2F;应答</td></tr><tr><td>Reason String &#x2F; User Property</td><td>诊断</td></tr></tbody></table><h3 id="4-3-典型流程（概念）"><a href="#4-3-典型流程（概念）" class="headerlink" title="4.3 典型流程（概念）"></a>4.3 典型流程（概念）</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Client ── CONNECT (Auth Method=…) ──▶ Server</span><br><span class="line">Client ◀─ AUTH (Continue + Data) ──── Server</span><br><span class="line">Client ── AUTH (Continue + Data) ───▶ Server</span><br><span class="line">Client ◀─ CONNACK (Success) ───────── Server</span><br></pre></td></tr></table></figure><p>亦可在已连接状态下 <strong>Re-authenticate</strong>。</p><hr><h2 id="5-运维抓包提示"><a href="#5-运维抓包提示" class="headerlink" title="5. 运维抓包提示"></a>5. 运维抓包提示</h2><table><thead><tr><th>现象</th><th>看什么</th></tr></thead><tbody><tr><td>周期性 <code>C0 00</code> &#x2F; <code>D0 00</code></td><td>Keep Alive 正常</td></tr><tr><td>Server 发 DISCONNECT <code>0x8B</code></td><td>Keep Alive 超时</td></tr><tr><td>Server 发 DISCONNECT <code>0x8D</code></td><td>同 ClientID 被顶号</td></tr><tr><td>AUTH 循环失败</td><td>Method&#x2F;Data 或 Broker 插件配置</td></tr></tbody></table><p>下一篇：<a href="/n/1175/">15-Reason-Code与Properties目录.md</a></p>]]>
    </content>
    <id>http://example.com/n/1174/</id>
    <link href="http://example.com/n/1174/"/>
    <published>2026-09-16T02:14:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="PING-DISCONNECT-AUTH-报文格式"><a href="#PING-DISCONNECT-AUTH-报文格式" class="headerlink" title="PING &#x2F; DISCONNECT &#x2F; AUTH 报文格式"><]]>
    </summary>
    <title>PING / DISCONNECT / AUTH 报文格式</title>
    <updated>2026-09-16T02:53:51.280Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="工业协议" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="CANopen" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/CANopen/"/>
    <category term="工业协议" scheme="http://example.com/tags/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="CANopen" scheme="http://example.com/tags/CANopen/"/>
    <content>
      <![CDATA[<h1 id="LSS-报文格式（CiA-305）"><a href="#LSS-报文格式（CiA-305）" class="headerlink" title="LSS 报文格式（CiA 305）"></a>LSS 报文格式（CiA 305）</h1><blockquote><p>官方概述：<a href="https://www.can-cia.org/can-knowledge/cia-305-layer-setting-services-lss">CiA 305 — Layer Setting Services</a><br>用途：在总线上配置 <strong>Node-ID</strong>、<strong>波特率</strong>，并查询 LSS 地址（Identity <code>1018h</code>）<br>正式文本多为 <strong>DSP（会员）</strong>；本篇给出公开描述与工程通用帧格式</p></blockquote><hr><h2 id="1-固定-COB-ID"><a href="#1-固定-COB-ID" class="headerlink" title="1. 固定 COB-ID"></a>1. 固定 COB-ID</h2><table><thead><tr><th>方向</th><th>COB-ID</th><th>说明</th></tr></thead><tbody><tr><td>LSS Master → Slave(s)</td><td><strong><code>0x7E5</code></strong></td><td>请求 &#x2F; 命令</td></tr><tr><td>LSS Slave → Master</td><td><strong><code>0x7E4</code></strong></td><td>响应</td></tr></tbody></table><ul><li>DLC 通常为 <strong>8</strong>  </li><li>仅使用这两帧 CAN-ID，与 Node-ID 无关（方便未配置节点）</li></ul><hr><h2 id="2-通用数据布局（概念）"><a href="#2-通用数据布局（概念）" class="headerlink" title="2. 通用数据布局（概念）"></a>2. 通用数据布局（概念）</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> Byte0      Byte1 …… Byte7</span><br><span class="line">┌─────────┬────────────────────────┐</span><br><span class="line">│ CS      │ 命令参数               │</span><br><span class="line">│(命令码) │                        │</span><br><span class="line">└─────────┴────────────────────────┘</span><br></pre></td></tr></table></figure><p>具体 CS 与参数域以 <strong>CiA 305</strong> 为准。工程上常见服务类别：</p><table><thead><tr><th>类别</th><th>作用</th></tr></thead><tbody><tr><td>Switch Mode Global &#x2F; Selective</td><td>进入&#x2F;退出配置模式</td></tr><tr><td>Configure Node-ID</td><td>设置 Node-ID</td></tr><tr><td>Configure Bit Timing</td><td>设置波特率相关参数</td></tr><tr><td>Activate Bit Timing</td><td>激活新波特率</td></tr><tr><td>Store Configuration</td><td>存盘</td></tr><tr><td>Inquire Identity</td><td>查询 Vendor-ID &#x2F; Product &#x2F; Revision &#x2F; Serial</td></tr><tr><td>Identify Remote Slave &#x2F; Fastscan</td><td>扫描未配置节点</td></tr></tbody></table><hr><h2 id="3-模式：Configuration-vs-Operation"><a href="#3-模式：Configuration-vs-Operation" class="headerlink" title="3. 模式：Configuration vs Operation"></a>3. 模式：Configuration vs Operation</h2><ul><li><strong>Operation Mode</strong>：通常仅允许切换模式类服务  </li><li><strong>Configuration Mode</strong>：允许改 Node-ID &#x2F; 波特率等</li></ul><p><strong>Switch Mode Selective</strong>：按 Identity（<code>1018h</code> 四元组）精确选中一台从站进入配置模式——产线多台未配 ID 设备时必需。</p><p><strong>Switch Mode Global</strong>：全网切换。</p><hr><h2 id="4-与-Identity-Object-的关系"><a href="#4-与-Identity-Object-的关系" class="headerlink" title="4. 与 Identity Object 的关系"></a>4. 与 Identity Object 的关系</h2><p><code>1018h</code> 典型子索引：</p><table><thead><tr><th>Sub</th><th>内容</th></tr></thead><tbody><tr><td>01h</td><td>Vendor-ID</td></tr><tr><td>02h</td><td>Product code</td></tr><tr><td>03h</td><td>Revision number</td></tr><tr><td>04h</td><td>Serial number</td></tr></tbody></table><p>LSS 选择性寻址依赖这些值在出厂时唯一或可区分。</p><hr><h2 id="5-典型工程流程（报文级叙事）"><a href="#5-典型工程流程（报文级叙事）" class="headerlink" title="5. 典型工程流程（报文级叙事）"></a>5. 典型工程流程（报文级叙事）</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">1. 未配置从站上电（Node-ID=0xFF 等非法/无效值，以厂商为准）</span><br><span class="line">2. Master @7E5: Switch Mode Selective（带 1018h 匹配）</span><br><span class="line">3. Slave  @7E4: 确认进入 Configuration</span><br><span class="line">4. Master @7E5: Configure Node-ID = 5</span><br><span class="line">5. Master @7E5: Store Configuration（若支持）</span><br><span class="line">6. Master @7E5: Switch Mode Operation</span><br><span class="line">7. 之后使用标准 NMT/SDO/PDO（COB-ID 按新 Node-ID）</span><br></pre></td></tr></table></figure><p>改波特率需全网协调：配置 → Activate → 主从同时切速率，否则总线失步。</p><hr><h2 id="6-抓包提示"><a href="#6-抓包提示" class="headerlink" title="6. 抓包提示"></a>6. 抓包提示</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">candump can0 | rg &#x27;7E[45]&#x27;</span><br></pre></td></tr></table></figure><ul><li>只见 <code>7E5</code> 无 <code>7E4</code>：从站未进 LSS、线断、或 Identity 不匹配  </li><li>配置后仍用旧 COB-ID 通信：未存盘&#x2F;未复位&#x2F;未按新 ID 寻址</li></ul><hr><h2 id="7-文档边界声明"><a href="#7-文档边界声明" class="headerlink" title="7. 文档边界声明"></a>7. 文档边界声明</h2><p>本篇基于 CiA <strong>公开 Knowledge</strong> 与通用实现习惯，用于学习与联调。<br><strong>命令码数值表、状态机细节以 CiA 305 正式 PDF 为准</strong>（见 <a href="/n/1128/">08-CiA规范与资料索引.md</a>）。</p><p>返回报文总览：<a href="/n/1129/">09-通信报文总览与CAN帧.md</a></p>]]>
    </content>
    <id>http://example.com/n/1133/</id>
    <link href="http://example.com/n/1133/"/>
    <published>2026-09-16T02:13:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="LSS-报文格式（CiA-305）"><a href="#LSS-报文格式（CiA-305）" class="headerlink" title="LSS 报文格式（CiA 305）"></a>LSS 报文格式（CiA 305）</h1><blockquote>]]>
    </summary>
    <title>LSS 报文格式（CiA 305）</title>
    <updated>2026-09-16T02:53:51.261Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="工业协议" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/MQTT/"/>
    <category term="工业协议" scheme="http://example.com/tags/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/tags/MQTT/"/>
    <content>
      <![CDATA[<h1 id="SUBSCRIBE-SUBACK-UNSUBSCRIBE-UNSUBACK-报文格式"><a href="#SUBSCRIBE-SUBACK-UNSUBSCRIBE-UNSUBACK-报文格式" class="headerlink" title="SUBSCRIBE &#x2F; SUBACK &#x2F; UNSUBSCRIBE &#x2F; UNSUBACK 报文格式"></a>SUBSCRIBE &#x2F; SUBACK &#x2F; UNSUBSCRIBE &#x2F; UNSUBACK 报文格式</h1><blockquote><p>OASIS MQTT 5.0：<strong>§3.8 SUBSCRIBE</strong>、<strong>§3.9 SUBACK</strong>、<strong>§3.10 UNSUBSCRIBE</strong>、<strong>§3.11 UNSUBACK</strong><br>Topic &#x2F; 通配符 &#x2F; 共享订阅概念见：<a href="/n/1161/">01-主题与发布订阅模型.md</a></p></blockquote><hr><h2 id="1-SUBSCRIBE（§3-8）"><a href="#1-SUBSCRIBE（§3-8）" class="headerlink" title="1. SUBSCRIBE（§3.8）"></a>1. SUBSCRIBE（§3.8）</h2><h3 id="1-1-Fixed-Header"><a href="#1-1-Fixed-Header" class="headerlink" title="1.1 Fixed Header"></a>1.1 Fixed Header</h3><table><thead><tr><th>Type</th><th>Flags</th></tr></thead><tbody><tr><td><code>8</code></td><td><strong>必须 <code>0010</code></strong>（bit1&#x3D;1）</td></tr></tbody></table><h3 id="1-2-Variable-Header"><a href="#1-2-Variable-Header" class="headerlink" title="1.2 Variable Header"></a>1.2 Variable Header</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Packet Identifier → Properties(5.0)</span><br></pre></td></tr></table></figure><p>常见 Properties：</p><table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td>Subscription Identifier</td><td>订阅标识；后续 PUBLISH 可带回，便于 Client 分流回调</td></tr><tr><td>User Property</td><td>自定义</td></tr></tbody></table><h3 id="1-3-Payload：订阅列表"><a href="#1-3-Payload：订阅列表" class="headerlink" title="1.3 Payload：订阅列表"></a>1.3 Payload：订阅列表</h3><p>由一个或多个订阅组成，每项：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">┌─────────────────────┬──────────────────┐</span><br><span class="line">│ Topic Filter        │ Subscription     │</span><br><span class="line">│ (UTF-8 String)      │ Options (1 byte) │</span><br><span class="line">└─────────────────────┴──────────────────┘</span><br></pre></td></tr></table></figure><h4 id="Subscription-Options（1-字节，5-0）"><a href="#Subscription-Options（1-字节，5-0）" class="headerlink" title="Subscription Options（1 字节，5.0）"></a>Subscription Options（1 字节，5.0）</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"> bit7-6      bit5-4     bit3      bit2       bit1-0</span><br><span class="line">┌──────────┬──────────┬─────────┬──────────┬─────────┐</span><br><span class="line">│ Reserved │ Retain   │ Retain  │ No Local │ Maximum │</span><br><span class="line">│ =0       │ Handling │ As Pub.*│          │ QoS     │</span><br><span class="line">└──────────┴──────────┴─────────┴──────────┴─────────┘</span><br><span class="line">* bit3: RAP — Retain As Published（名称以规范为准）</span><br></pre></td></tr></table></figure><table><thead><tr><th>字段</th><th>含义</th></tr></thead><tbody><tr><td>Maximum QoS</td><td>Client 愿接受的最大 QoS（0&#x2F;1&#x2F;2）</td></tr><tr><td>No Local</td><td>1&#x3D;不接收自己在同连接上发布的消息</td></tr><tr><td>Retain As Published</td><td>转发时保留原消息 RETAIN 标志</td></tr><tr><td>Retain Handling</td><td>0&#x3D;发送保留消息；1&#x3D;仅新订阅发送；2&#x3D;不发送保留消息</td></tr></tbody></table><p>3.1.1：Payload 每项仅为 <strong>Topic Filter + Requested QoS（1 字节，高 6 位必须为 0）</strong>。</p><h3 id="1-4-Topic-Filter-规则（摘要）"><a href="#1-4-Topic-Filter-规则（摘要）" class="headerlink" title="1.4 Topic Filter 规则（摘要）"></a>1.4 Topic Filter 规则（摘要）</h3><ul><li>可含 <code>+</code> &#x2F; <code>#</code> 通配符（<code>#</code> 须单独一层且在末尾）  </li><li>MQTT 5 共享订阅：<code>$share/{ShareName}/{TopicFilter}</code>  </li><li>非法 Filter → Server 在 SUBACK 返回失败 Reason，或协议错误处理</li></ul><hr><h2 id="2-SUBACK（§3-9）"><a href="#2-SUBACK（§3-9）" class="headerlink" title="2. SUBACK（§3.9）"></a>2. SUBACK（§3.9）</h2><h3 id="2-1-Fixed-Header"><a href="#2-1-Fixed-Header" class="headerlink" title="2.1 Fixed Header"></a>2.1 Fixed Header</h3><p>Type&#x3D;<code>9</code>，Flags&#x3D;<code>0000</code>。</p><h3 id="2-2-Variable-Header"><a href="#2-2-Variable-Header" class="headerlink" title="2.2 Variable Header"></a>2.2 Variable Header</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Packet Identifier → Properties(5.0)（Reason String、User Property…）</span><br></pre></td></tr></table></figure><h3 id="2-3-Payload：Reason-Code-列表"><a href="#2-3-Payload：Reason-Code-列表" class="headerlink" title="2.3 Payload：Reason Code 列表"></a>2.3 Payload：Reason Code 列表</h3><ul><li><strong>按订阅顺序一一对应</strong> SUBSCRIBE Payload 中的每一项  </li><li>每个 1 字节</li></ul><table><thead><tr><th>Reason（例）</th><th>含义</th></tr></thead><tbody><tr><td><code>0x00</code></td><td>Granted QoS 0</td></tr><tr><td><code>0x01</code></td><td>Granted QoS 1</td></tr><tr><td><code>0x02</code></td><td>Granted QoS 2</td></tr><tr><td><code>0x80</code></td><td>Unspecified error</td></tr><tr><td><code>0x83</code></td><td>Implementation specific error</td></tr><tr><td><code>0x87</code></td><td>Not authorized</td></tr><tr><td><code>0x8F</code></td><td>Topic Filter invalid</td></tr><tr><td><code>0x91</code></td><td>Packet Identifier in use</td></tr><tr><td><code>0x97</code></td><td>Quota exceeded</td></tr><tr><td><code>0x9E</code></td><td>Shared Subscriptions not supported</td></tr><tr><td><code>0xA1</code></td><td>Subscription Identifiers not supported</td></tr><tr><td><code>0xA2</code></td><td>Wildcard Subscriptions not supported</td></tr></tbody></table><p><strong>要点</strong>：Granted QoS <strong>可以低于</strong> Requested QoS；Client 必须以 SUBACK 为准。</p><p>3.1.1：Payload 为 Return Code（<code>0x00</code>&#x2F;<code>0x01</code>&#x2F;<code>0x02</code>&#x2F;<code>0x80</code>）。</p><hr><h2 id="3-UNSUBSCRIBE（§3-10）"><a href="#3-UNSUBSCRIBE（§3-10）" class="headerlink" title="3. UNSUBSCRIBE（§3.10）"></a>3. UNSUBSCRIBE（§3.10）</h2><h3 id="3-1-Fixed-Header"><a href="#3-1-Fixed-Header" class="headerlink" title="3.1 Fixed Header"></a>3.1 Fixed Header</h3><p>Type&#x3D;<code>10</code>，Flags&#x3D;<strong><code>0010</code></strong>。</p><h3 id="3-2-Variable-Header"><a href="#3-2-Variable-Header" class="headerlink" title="3.2 Variable Header"></a>3.2 Variable Header</h3><p>Packet Identifier + Properties(5.0)。</p><h3 id="3-3-Payload"><a href="#3-3-Payload" class="headerlink" title="3.3 Payload"></a>3.3 Payload</h3><p>一个或多个 <strong>Topic Filter</strong>（UTF-8 String），无 Options 字节。</p><hr><h2 id="4-UNSUBACK（§3-11）"><a href="#4-UNSUBACK（§3-11）" class="headerlink" title="4. UNSUBACK（§3.11）"></a>4. UNSUBACK（§3.11）</h2><h3 id="4-1-Fixed-Header"><a href="#4-1-Fixed-Header" class="headerlink" title="4.1 Fixed Header"></a>4.1 Fixed Header</h3><p>Type&#x3D;<code>11</code>，Flags&#x3D;<code>0000</code>。</p><h3 id="4-2-Variable-Header"><a href="#4-2-Variable-Header" class="headerlink" title="4.2 Variable Header"></a>4.2 Variable Header</h3><p>Packet Identifier + Properties(5.0)。</p><h3 id="4-3-Payload（MQTT-5）"><a href="#4-3-Payload（MQTT-5）" class="headerlink" title="4.3 Payload（MQTT 5）"></a>4.3 Payload（MQTT 5）</h3><p>每个 Topic Filter 对应 1 字节 Reason Code，例如：</p><table><thead><tr><th>Code</th><th>含义</th></tr></thead><tbody><tr><td><code>0x00</code></td><td>Success</td></tr><tr><td><code>0x11</code></td><td>No subscription existed</td></tr><tr><td><code>0x80</code></td><td>Unspecified error</td></tr><tr><td><code>0x87</code></td><td>Not authorized</td></tr><tr><td><code>0x8F</code></td><td>Topic Filter invalid</td></tr></tbody></table><p>3.1.1：UNSUBACK <strong>仅有</strong> Packet Identifier，无 Payload Reason 列表。</p><hr><h2 id="5-时序示例"><a href="#5-时序示例" class="headerlink" title="5. 时序示例"></a>5. 时序示例</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Client ── SUBSCRIBE  (P=10, filter=siteA/+/state, maxQoS=1) ──▶ Server</span><br><span class="line">Client ◀─ SUBACK     (P=10, reason=0x01 Granted QoS1) ─────── Server</span><br><span class="line">Server ── PUBLISH    (匹配消息) ─────────────────────────────▶ Client</span><br><span class="line"></span><br><span class="line">Client ── UNSUBSCRIBE (P=11, filter=siteA/+/state) ──────────▶ Server</span><br><span class="line">Client ◀─ UNSUBACK    (P=11, reason=0x00) ─────────────────── Server</span><br></pre></td></tr></table></figure><p>下一篇：<a href="/n/1174/">14-PING-DISCONNECT-AUTH报文格式.md</a></p>]]>
    </content>
    <id>http://example.com/n/1173/</id>
    <link href="http://example.com/n/1173/"/>
    <published>2026-09-16T02:13:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="SUBSCRIBE-SUBACK-UNSUBSCRIBE-UNSUBACK-报文格式"><a href="#SUBSCRIBE-SUBACK-UNSUBSCRIBE-UNSUBACK-报文格式" class="headerlink" title="SUBSCRIB]]>
    </summary>
    <title>SUBSCRIBE / SUBACK / UNSUBSCRIBE / UNSUBACK 报文格式</title>
    <updated>2026-09-16T02:53:51.280Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="工业协议" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="CANopen" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/CANopen/"/>
    <category term="工业协议" scheme="http://example.com/tags/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="CANopen" scheme="http://example.com/tags/CANopen/"/>
    <content>
      <![CDATA[<h1 id="PDO-报文与映射编码"><a href="#PDO-报文与映射编码" class="headerlink" title="PDO 报文与映射编码"></a>PDO 报文与映射编码</h1><blockquote><p>官方概念：<a href="https://www.can-cia.org/can-knowledge/pdo-protocol/">PDO protocol (CiA)</a><br>PDO &#x3D; <strong>单帧 CAN</strong>，最多 <strong>8 字节纯应用数据</strong>（无 SDO 式命令字节）</p></blockquote><hr><h2 id="1-帧结构"><a href="#1-帧结构" class="headerlink" title="1. 帧结构"></a>1. 帧结构</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">┌─────────────┬─────┬──────────────────────────┐</span><br><span class="line">│ COB-ID      │ DLC │ Data[0..DLC-1]           │</span><br><span class="line">│ (可配置)    │≤8   │ = 映射对象按序拼接的位串   │</span><br><span class="line">└─────────────┴─────┴──────────────────────────┘</span><br></pre></td></tr></table></figure><table><thead><tr><th>类型</th><th>相对节点</th><th>预定义 COB-ID（1～4）</th></tr></thead><tbody><tr><td><strong>TPDO</strong></td><td>节点发送</td><td><code>0x180/280/380/480 + Node-ID</code></td></tr><tr><td><strong>RPDO</strong></td><td>节点接收</td><td><code>0x200/300/400/500 + Node-ID</code></td></tr></tbody></table><p>无应用层 ACK：可靠性靠 CAN ACK、Heartbeat、应用层状态机（如 402 Fault）。</p><hr><h2 id="2-通信参数-vs-映射参数（OD）"><a href="#2-通信参数-vs-映射参数（OD）" class="headerlink" title="2. 通信参数 vs 映射参数（OD）"></a>2. 通信参数 vs 映射参数（OD）</h2><p>以 <strong>TPDO1</strong> 为例（RPDO1 对称：<code>1400h</code>&#x2F;<code>1600h</code>）：</p><table><thead><tr><th>对象</th><th>名称</th><th>作用</th></tr></thead><tbody><tr><td><code>1800h</code></td><td>TPDO1 communication parameter</td><td>COB-ID、传输类型、Inhibit、Event timer…</td></tr><tr><td><code>1A00h</code></td><td>TPDO1 mapping parameter</td><td>映射表</td></tr></tbody></table><h3 id="2-1-通信参数记录（典型子索引）"><a href="#2-1-通信参数记录（典型子索引）" class="headerlink" title="2.1 通信参数记录（典型子索引）"></a>2.1 通信参数记录（典型子索引）</h3><table><thead><tr><th>Sub</th><th>含义（常见）</th></tr></thead><tbody><tr><td>00h</td><td>最高子索引</td></tr><tr><td>01h</td><td><strong>COB-ID</strong>（含有效位等）</td></tr><tr><td>02h</td><td><strong>Transmission type</strong></td></tr><tr><td>03h</td><td>Inhibit time（×100 µs 量级，以实现为准）</td></tr><tr><td>05h</td><td>Event timer（ms）</td></tr></tbody></table><p><strong>COB-ID Bit31</strong>：常表示 PDO <strong>无效&#x2F;有效</strong>（1&#x3D;invalid）。改映射前须先置无效——见 CiA 映射步骤。</p><h3 id="2-2-Transmission-Type（传输类型）"><a href="#2-2-Transmission-Type（传输类型）" class="headerlink" title="2.2 Transmission Type（传输类型）"></a>2.2 Transmission Type（传输类型）</h3><table><thead><tr><th>值</th><th>行为</th></tr></thead><tbody><tr><td><strong>0</strong></td><td>同步，无环计数：由 SYNC 触发，但需配合事件（acyclic sync）</td></tr><tr><td><strong>1～240</strong></td><td>同步循环：每收到 n 次 SYNC 发一次</td></tr><tr><td><strong>254</strong></td><td>异步：厂商特定事件</td></tr><tr><td><strong>255</strong></td><td>异步：设备行规定义的事件；常配合 Event timer</td></tr></tbody></table><p>（具体枚举以 CiA 301 &#x2F; EDS 为准。）</p><hr><h2 id="3-映射参数编码"><a href="#3-映射参数编码" class="headerlink" title="3. 映射参数编码"></a>3. 映射参数编码</h2><h3 id="3-1-子索引布局"><a href="#3-1-子索引布局" class="headerlink" title="3.1 子索引布局"></a>3.1 子索引布局</h3><table><thead><tr><th>Sub</th><th>含义</th></tr></thead><tbody><tr><td>00h</td><td>已映射对象个数 <strong>N</strong></td></tr><tr><td>01h…Nh</td><td>第 i 个映射项（32-bit）</td></tr></tbody></table><h3 id="3-2-单个映射项（32-bit，小端存于-OD）"><a href="#3-2-单个映射项（32-bit，小端存于-OD）" class="headerlink" title="3.2 单个映射项（32-bit，小端存于 OD）"></a>3.2 单个映射项（32-bit，小端存于 OD）</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> 31────────────16 15─────8 7──────0</span><br><span class="line">┌────────────────┬────────┬────────┐</span><br><span class="line">│ Index          │ SubIdx │ Length │</span><br><span class="line">│ (被映射对象)    │        │ (bits) │</span><br><span class="line">└────────────────┴────────┴────────┘</span><br></pre></td></tr></table></figure><table><thead><tr><th>字段</th><th>说明</th></tr></thead><tbody><tr><td>Index</td><td>应用对象索引（如 <code>6041h</code>）</td></tr><tr><td>SubIndex</td><td>子索引</td></tr><tr><td>Length</td><td><strong>位长度</strong>（如 16、32；不是字节）</td></tr></tbody></table><p>例：映射 Statusword <code>6041h:00</code> 共 16 bit → 映射字 <code>0x60410010</code>。</p><h3 id="3-3-净荷拼接规则"><a href="#3-3-净荷拼接规则" class="headerlink" title="3.3 净荷拼接规则"></a>3.3 净荷拼接规则</h3><ul><li>按映射表 <strong>01h → Nh</strong> 顺序，把各对象的位串紧密排列进 PDO Data  </li><li>多字节对象内部一般为 <strong>小端</strong>  </li><li>总位数 ≤ 64（8 字节）</li></ul><hr><h2 id="4-完整示例（402-常见教学映射）"><a href="#4-完整示例（402-常见教学映射）" class="headerlink" title="4. 完整示例（402 常见教学映射）"></a>4. 完整示例（402 常见教学映射）</h2><p><strong>RPDO1</strong>（主站→节点 5）映射：</p><ol><li><code>6040h:00</code> Controlword 16 bit  </li><li><code>607Ah:00</code> Target position 32 bit</li></ol><p>总长 48 bit &#x3D; 6 字节 → DLC&#x3D;6  </p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">COB-ID 0x205:</span><br><span class="line">Data:  cw_lo cw_hi  pos0 pos1 pos2 pos3</span><br></pre></td></tr></table></figure><p><strong>TPDO1</strong>（节点 5→主站）：</p><ol><li><code>6041h:00</code> Statusword 16  </li><li><code>6064h:00</code> Position actual 32</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">COB-ID 0x185:</span><br><span class="line">Data:  sw_lo sw_hi  p0 p1 p2 p3</span><br></pre></td></tr></table></figure><hr><h2 id="5-触发方式（与-SYNC-的关系）"><a href="#5-触发方式（与-SYNC-的关系）" class="headerlink" title="5. 触发方式（与 SYNC 的关系）"></a>5. 触发方式（与 SYNC 的关系）</h2><p>CiA 定义的触发包括：</p><table><thead><tr><th>类型</th><th>说明</th></tr></thead><tbody><tr><td>Event &#x2F; timer-driven</td><td>内部事件或事件定时器</td></tr><tr><td>Remotely-requested</td><td>RTR 请求（遗留）</td></tr><tr><td>Synchronous cyclic</td><td>每 n 次 SYNC</td></tr><tr><td>Synchronous acyclic</td><td>事件置位，遇下一 SYNC 再发</td></tr></tbody></table><p>运动控制常用：<strong>同步 TPDO&#x2F;RPDO + 周期 SYNC</strong>。</p><hr><h2 id="6-修改映射的官方步骤（Variable-Dynamic）"><a href="#6-修改映射的官方步骤（Variable-Dynamic）" class="headerlink" title="6. 修改映射的官方步骤（Variable&#x2F;Dynamic）"></a>6. 修改映射的官方步骤（Variable&#x2F;Dynamic）</h2><p>CiA 公开步骤（<a href="https://www.can-cia.org/can-knowledge/pdo-protocol/">PDO protocol</a>）：</p><ol><li>将对应 COB-ID 的 <strong>Bit31 置 1</strong>，使 PDO 无效  </li><li>写映射参数 Sub00 &#x3D; <code>00h</code>，使映射无效  </li><li>写入各映射项 Sub01…  </li><li>写 Sub00 &#x3D; 映射对象个数  </li><li>清 COB-ID Bit31，使 PDO 重新有效</li></ol><table><thead><tr><th>映射类型</th><th>何时可改</th></tr></thead><tbody><tr><td>Static</td><td>出厂固定，不可经 CANopen 改</td></tr><tr><td>Variable</td><td><strong>Pre-Operational</strong> 可改</td></tr><tr><td>Dynamic</td><td><strong>Operational</strong> 亦可改（设备需声明支持）</td></tr></tbody></table><hr><h2 id="7-抓包对照清单"><a href="#7-抓包对照清单" class="headerlink" title="7. 抓包对照清单"></a>7. 抓包对照清单</h2><ul><li><input disabled="" type="checkbox"> COB-ID 是否仍为预定义，或已被 SDO 改写  </li><li><input disabled="" type="checkbox"> DLC 是否等于映射总字节数  </li><li><input disabled="" type="checkbox"> 字节序&#x2F;多对象边界是否与 EDS 一致  </li><li><input disabled="" type="checkbox"> 节点是否已 NMT Start（否则不应有 PDO）  </li><li><input disabled="" type="checkbox"> Transmission type 与 SYNC 是否匹配</li></ul><p>下一篇：<a href="/n/1133/">13-LSS报文格式.md</a></p>]]>
    </content>
    <id>http://example.com/n/1132/</id>
    <link href="http://example.com/n/1132/"/>
    <published>2026-09-16T02:12:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="PDO-报文与映射编码"><a href="#PDO-报文与映射编码" class="headerlink" title="PDO 报文与映射编码"></a>PDO 报文与映射编码</h1><blockquote>
<p>官方概念：<a href="https:/]]>
    </summary>
    <title>PDO 报文与映射编码</title>
    <updated>2026-09-16T02:53:51.260Z</updated>
  </entry>
  <entry>
    <author>
      <name>fish</name>
    </author>
    <category term="工业协议" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/categories/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/MQTT/"/>
    <category term="工业协议" scheme="http://example.com/tags/%E5%B7%A5%E4%B8%9A%E5%8D%8F%E8%AE%AE/"/>
    <category term="MQTT" scheme="http://example.com/tags/MQTT/"/>
    <content>
      <![CDATA[<h1 id="PUBLISH-与-QoS-握手报文格式"><a href="#PUBLISH-与-QoS-握手报文格式" class="headerlink" title="PUBLISH 与 QoS 握手报文格式"></a>PUBLISH 与 QoS 握手报文格式</h1><blockquote><p>OASIS MQTT 5.0：<strong>§3.3 PUBLISH</strong>、<strong>§3.4 PUBACK</strong>、<strong>§3.5 PUBREC</strong>、<strong>§3.6 PUBREL</strong>、<strong>§3.7 PUBCOMP</strong><br>QoS 语义综述另见：<a href="/n/1163/">03-QoS与消息投递.md</a></p></blockquote><hr><h2 id="1-PUBLISH（§3-3）"><a href="#1-PUBLISH（§3-3）" class="headerlink" title="1. PUBLISH（§3.3）"></a>1. PUBLISH（§3.3）</h2><h3 id="1-1-Fixed-Header"><a href="#1-1-Fixed-Header" class="headerlink" title="1.1 Fixed Header"></a>1.1 Fixed Header</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Type=3 | DUP | QoS1 | QoS0 | RETAIN | Remaining Length…</span><br></pre></td></tr></table></figure><table><thead><tr><th>标志</th><th>含义</th></tr></thead><tbody><tr><td><strong>DUP</strong></td><td>1&#x3D;可能是重传的 PUBLISH（QoS&gt;0）；接收方须按 Packet ID 去重&#x2F;续传逻辑处理</td></tr><tr><td><strong>QoS</strong></td><td><code>00</code>&#x3D;0，<code>01</code>&#x3D;1，<code>10</code>&#x3D;2；<code>11</code> 非法 → 协议错误</td></tr><tr><td><strong>RETAIN</strong></td><td>1&#x3D;Server 应作为该 Topic 的保留消息存储&#x2F;替换（空载荷 Retain 可删除保留消息，见规范）</td></tr></tbody></table><h3 id="1-2-Variable-Header"><a href="#1-2-Variable-Header" class="headerlink" title="1.2 Variable Header"></a>1.2 Variable Header</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Topic Name → Packet Identifier(若 QoS&gt;0) → Properties(5.0)</span><br></pre></td></tr></table></figure><table><thead><tr><th>字段</th><th>规则</th></tr></thead><tbody><tr><td>Topic Name</td><td>UTF-8；<strong>不得含通配符</strong>；可用 Topic Alias 缩短（5.0）</td></tr><tr><td>Packet Identifier</td><td>QoS 1&#x2F;2 <strong>必须</strong>；QoS 0 <strong>不得</strong>出现</td></tr><tr><td>Properties</td><td>Payload Format、Message Expiry、Topic Alias、Response Topic、Correlation Data、User Property、Subscription Identifier、Content Type 等</td></tr></tbody></table><h3 id="1-3-Payload"><a href="#1-3-Payload" class="headerlink" title="1.3 Payload"></a>1.3 Payload</h3><ul><li>应用消息原始字节；长度 &#x3D; Remaining Length − Variable Header 长度  </li><li>协议对内容不可知（JSON&#x2F;Protobuf&#x2F;二进制均可）</li></ul><h3 id="1-4-抓包心算"><a href="#1-4-抓包心算" class="headerlink" title="1.4 抓包心算"></a>1.4 抓包心算</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Fixed Header: 0x30 = PUBLISH, QoS0, no DUP, no RETAIN</span><br><span class="line">Fixed Header: 0x32 = PUBLISH, QoS1</span><br><span class="line">Fixed Header: 0x33 = PUBLISH, QoS1 + RETAIN</span><br><span class="line">Fixed Header: 0x34 = PUBLISH, QoS2</span><br></pre></td></tr></table></figure><hr><h2 id="2-QoS-0：无确认"><a href="#2-QoS-0：无确认" class="headerlink" title="2. QoS 0：无确认"></a>2. QoS 0：无确认</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Sender ──PUBLISH (QoS0)──▶ Receiver</span><br></pre></td></tr></table></figure><p>无 Packet Identifier；可丢。</p><hr><h2 id="3-QoS-1：PUBACK（§3-4）"><a href="#3-QoS-1：PUBACK（§3-4）" class="headerlink" title="3. QoS 1：PUBACK（§3.4）"></a>3. QoS 1：PUBACK（§3.4）</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Sender ──PUBLISH (QoS1, PacketID=P, DUP?)──▶ Receiver</span><br><span class="line">Sender ◀─PUBACK  (PacketID=P, Reason?)───── Receiver</span><br></pre></td></tr></table></figure><h3 id="PUBACK-结构"><a href="#PUBACK-结构" class="headerlink" title="PUBACK 结构"></a>PUBACK 结构</h3><table><thead><tr><th>部分</th><th>内容</th></tr></thead><tbody><tr><td>Fixed Header</td><td>Type&#x3D;4，Flags&#x3D;0000</td></tr><tr><td>Variable Header</td><td>Packet Identifier；<strong>5.0</strong> 可跟 Reason Code + Properties</td></tr><tr><td>Payload</td><td>无</td></tr></tbody></table><p>成功 Reason 常为 <code>0x00</code> Success；亦可 <code>0x10</code> No matching subscribers 等（5.0，视角色）。</p><p>超时未收到 PUBACK → Sender 以 <strong>DUP&#x3D;1</strong> 重传同一 Packet ID 的 PUBLISH。</p><hr><h2 id="4-QoS-2：四步握手（§3-5～3-7）"><a href="#4-QoS-2：四步握手（§3-5～3-7）" class="headerlink" title="4. QoS 2：四步握手（§3.5～3.7）"></a>4. QoS 2：四步握手（§3.5～3.7）</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Sender ──PUBLISH (QoS2, P)──▶ Receiver</span><br><span class="line">Sender ◀─PUBREC  (P)───────── Receiver</span><br><span class="line">Sender ──PUBREL  (P)─────────▶ Receiver   # Flags 必须 0010</span><br><span class="line">Sender ◀─PUBCOMP (P)───────── Receiver</span><br></pre></td></tr></table></figure><table><thead><tr><th>报文</th><th>Type</th><th>Flags</th><th>作用</th></tr></thead><tbody><tr><td>PUBREC</td><td>5</td><td>0000</td><td>Receiver：已收到，进入第二阶段</td></tr><tr><td>PUBREL</td><td>6</td><td><strong>0010</strong></td><td>Sender：释放；可带 Reason（5.0）</td></tr><tr><td>PUBCOMP</td><td>7</td><td>0000</td><td>Receiver：完成</td></tr></tbody></table><p>任一步超时按规范重传对应报文；状态机必须持久化未完成流（会话恢复相关）。</p><p>MQTT 5 下 PUBREC&#x2F;PUBREL&#x2F;PUBCOMP 均可带 <strong>Reason Code + Properties</strong>（如 Reason String）。</p><hr><h2 id="5-端到端注意（规范视角）"><a href="#5-端到端注意（规范视角）" class="headerlink" title="5. 端到端注意（规范视角）"></a>5. 端到端注意（规范视角）</h2><ul><li>QoS 保证的是 <strong>MQTT 协议跳</strong>（如 Client↔Server），不是自动的业务全局 exactly-once  </li><li>Publisher→Server 与 Server→Subscriber 是两段独立 QoS  </li><li>应用层仍建议：<code>message_id</code> &#x2F; 幂等键</li></ul><hr><h2 id="6-3-1-1-vs-5-0"><a href="#6-3-1-1-vs-5-0" class="headerlink" title="6. 3.1.1 vs 5.0"></a>6. 3.1.1 vs 5.0</h2><table><thead><tr><th>项</th><th>3.1.1</th><th>5.0</th></tr></thead><tbody><tr><td>PUBACK 等</td><td>仅 Packet ID</td><td>+ Reason Code + Properties</td></tr><tr><td>PUBLISH 元数据</td><td>无标准属性</td><td>Topic Alias、Expiry、Response Topic…</td></tr><tr><td>无匹配订阅者</td><td>无标准反馈</td><td>PUBACK Reason <code>0x10</code> 等</td></tr></tbody></table><p>下一篇：<a href="/n/1173/">13-SUBSCRIBE与UNSUBSCRIBE报文格式.md</a></p>]]>
    </content>
    <id>http://example.com/n/1172/</id>
    <link href="http://example.com/n/1172/"/>
    <published>2026-09-16T02:12:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="PUBLISH-与-QoS-握手报文格式"><a href="#PUBLISH-与-QoS-握手报文格式" class="headerlink" title="PUBLISH 与 QoS 握手报文格式"></a>PUBLISH 与 QoS 握手报文格式</h1><]]>
    </summary>
    <title>PUBLISH 与 QoS 握手报文格式</title>
    <updated>2026-09-16T02:53:51.279Z</updated>
  </entry>
</feed>
