OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
迁移指南

上一个教程: 为 OpenCV 编写文档
下一个教程: 从其他 Doxygen 项目交叉引用 OpenCV

原始作者马克西姆·沙布宁
兼容性OpenCV >= 3.0

变更概述

本文档旨在帮助希望将其代码迁移到 OpenCV 3.0 的软件开发人员。

与 2.4 版本相比,OpenCV 3.0 引入了许多新算法和功能。一些模块已被重写,一些已被重组。尽管 2.4 中的大多数算法仍然存在,但接口可能有所不同。

本节概述了最显著的变更,所有详细信息和迁移操作示例将在文档的下一部分中介绍。

Contrib 仓库

https://github.com/opencv/opencv_contrib

这里是所有新的、实验性的和非免费算法的存放地。与主仓库相比,它没有得到支持团队那么多的关注,但社区会努力维护它。

要使用 contrib 仓库构建 OpenCV,请将以下选项添加到您的 cmake 命令中

-DOPENCV_EXTRA_MODULES_PATH=<path-to-opencv_contrib>/modules
头文件布局

在 2.4 版本中,所有头文件都位于相应的模块子文件夹中(opencv2/<module>/<module>.hpp),而在 3.0 版本中,存在包含大部分模块功能的顶级模块头文件:opencv2/<module>.hpp,并且所有 C 风格的 API 定义已移至单独的头文件(例如 opencv2/core/core_c.h)。

算法接口

通用算法使用模式已更改:现在必须在堆上创建并封装在智能指针 cv::Ptr 中。2.4 版本允许栈分配和堆分配,无论是直接分配还是通过智能指针。

getset 方法以及 CV_INIT_ALGORITHM 宏已从 cv::Algorithm 类中移除。在 3.0 版本中,所有属性都已转换为 getProperty/setProperty 纯虚方法对。因此,无法通过名称(使用通用 Algorithm::create(String) 方法)创建和使用 cv::Algorithm 实例,而应显式调用相应的工厂方法。

已更改模块
  • ml 模块已被重写
  • highgui 模块已被拆分为多个部分:imgcodecsvideoiohighgui 本身
  • features2d 模块已被重组(一些特征检测器已移至 opencv_contrib/xfeatures2d 模块)
  • legacynonfree 模块已被移除。一些算法已被移至不同位置,一些已被完全重写或移除
  • CUDA API 已更新(gpu 模块 -> 多个 cuda 模块,命名空间 gpu -> 命名空间 cuda
  • OpenCL API 已更改(ocl 模块已被移除,独立的 ocl:: 实现 -> 透明 API)
  • 一些其他方法和类已被重新定位

迁移提示

本节将通过示例描述具体操作。

准备 2.4 版本

OpenCV 最新 2.4.11 版本中的一些更改允许您为迁移准备当前代码库

  • cv::makePtr 函数现在可用
  • opencv2/<module>.hpp 头文件已创建

新头文件布局

注意: OpenCV 3.0 中已进行了旨在简化迁移的更改,因此以下说明并非必需,但建议遵循。

  1. 替换旧模块头文件的包含
    // 旧头文件
    #include "opencv2/<module>/<module>.hpp"
    // 新头文件
    #include "opencv2/<module>.hpp"

现代算法使用方式

  1. 算法实例必须使用 cv::makePtr 函数或相应的静态工厂方法(如果可用)创建。
    // 推荐方式
    Ptr<SomeAlgo> algo = makePtr<SomeAlgo>(...);
    Ptr<SomeAlgo> algo = SomeAlgo::create(...);
    其他方式已被弃用
    // 不推荐方式
    Ptr<SomeAlgo> algo = new SomeAlgo(...);
    SomeAlgo * algo = new SomeAlgo(...);
    SomeAlgo algo(...);
    Ptr<SomeAlgo> algo = Algorithm::create<SomeAlgo>("name");
  2. 算法属性应通过相应的虚方法 getSomeProperty/setSomeProperty 访问,通用的 get/set 方法已被移除
    // 推荐方式
    double clipLimit = clahe->getClipLimit();
    clahe->setClipLimit(clipLimit);
    // 不推荐方式
    double clipLimit = clahe->getDouble("clipLimit");
    clahe->set("clipLimit", clipLimit);
    clahe->setDouble("clipLimit", clipLimit);
  3. 移除 initModule_<moduleName>() 调用

机器学习模块

由于此模块已被重写,因此您的软件需要进行一些适配工作。所有算法都位于独立的 ml 命名空间中,以及它们的基类 StatModel。独立的 SomeAlgoParams 类已被替换为相应的 getProperty/setProperty 方法集。

下表说明了 2.4 和 3.0 机器学习类之间的对应关系。

2.4 3.0
CvStatModelcv::ml::StatModel
CvNormalBayesClassifiercv::ml::NormalBayesClassifier
CvKNearestcv::ml::KNearest
CvSVMcv::ml::SVM
CvDTreecv::ml::DTrees
CvBoostcv::ml::Boost
CvGBTrees未实现
CvRTreescv::ml::RTrees
CvERTrees未实现
EMcv::ml::EM
CvANN_MLPcv::ml::ANN_MLP
未实现 cv::ml::LogisticRegression
CvMLDatacv::ml::TrainData

尽管 3.0 中重写的 ml 算法允许您从 xml/yml 文件加载旧的训练模型,但预测过程中可能会出现偏差。

以下来自 points_classifier.cpp 示例的代码片段说明了模型训练过程中的差异

using namespace cv;
// ======== 2.4 版本 ========
Mat trainSamples, trainClasses;
prepare_train_data( trainSamples, trainClasses );
CvBoost boost;
Mat var_types( 1, trainSamples.cols + 1, CV_8UC1, Scalar(CV_VAR_ORDERED) );
var_types.at<uchar>( trainSamples.cols ) = CV_VAR_CATEGORICAL;
CvBoostParams params( CvBoost::DISCRETE, // 提升类型
100, // 弱分类器数量
0.95, // 权重修剪率
2, // 最大深度
false, //使用代理
0 // 先验
);
boost.train( trainSamples, CV_ROW_SAMPLE, trainClasses, Mat(), Mat(), var_types, Mat(), params );
// ======== 3.0 版本 ========
Ptr<Boost> boost = Boost::create();
boost->setBoostType(Boost::DISCRETE);
boost->setWeakCount(100);
boost->setWeightTrimRate(0.95);
boost->setMaxDepth(2);
boost->setUseSurrogates(false);
boost->setPriors(Mat());
boost->train(prepare_train_data()); // 'prepare_train_data' 返回 ml::TrainData 类的一个实例
n 维密集数组类
定义 mat.hpp:830
int cols
定义 mat.hpp:2165
std::shared_ptr< _Tp > Ptr
Definition cvstd_wrapper.hpp:23
I.at<uchar>(y, x) = saturate_cast<uchar>(r);
uchar
unsigned char uchar
#define CV_8UC1
定义 interface.h:88
定义 core.hpp:107

特征检测

一些算法(FREAK、BRIEF、SIFT、SURF)已移至 opencv_contrib 仓库中的 xfeatures2d 模块,位于 xfeatures2d 命名空间下。它们的接口也已更改(继承自 cv::Feature2D 基类)。

xfeatures2d 模块类列表

需要以下步骤

  1. opencv_contrib 添加到编译过程
  2. 包含 opencv2/xfeatures2d.h 头文件
  3. 使用命名空间 xfeatures2d
  4. 如果需要,将 operator() 调用替换为 detectcomputedetectAndCompute

现在,一些类使用 Feature2D 基类提供的通用方法 detectcomputedetectAndCompute,而不是自定义的 operator()

以下代码片段说明了差异(来自 video_homography.cpp 示例)

using namespace cv;
// ====== 2.4 =======
BriefDescriptorExtractor brief(32);
GridAdaptedFeatureDetector detector(new FastFeatureDetector(10, true), DESIRED_FTRS, 4, 4);
// ...
detector.detect(gray, query_kpts); // 查找兴趣点
brief.compute(gray, query_kpts, query_desc); // 在每个关键点位置计算 BRIEF 描述符
// ====== 3.0 =======
using namespace cv::xfeatures2d;
Ptr<BriefDescriptorExtractor> brief = BriefDescriptorExtractor::create(32);
Ptr<FastFeatureDetector> detector = FastFeatureDetector::create(10, true);
// ...
detector->detect(gray, query_kpts); // 查找兴趣点
brief->compute(gray, query_kpts, query_desc); // 在每个关键点位置计算 BRIEF 描述符
用于使用 FAST 方法进行特征检测的包装类。
定义 features2d.hpp:574
定义 xfeatures2d.hpp:67

OpenCL

所有专门的 ocl 实现都已隐藏在通用 C++ 算法接口之后。现在,函数执行路径可以在运行时动态选择:CPU 或 OpenCL;这种机制也称为“透明 API”。

新类 cv::UMat 旨在以便捷的方式隐藏与 OpenCL 设备的数据交换。

以下示例说明了 API 修改(摘自 OpenCV 网站

  • OpenCL 感知代码 OpenCV-2.x
    // 初始化
    VideoCapture vcap(...);
    ocl::OclCascadeClassifier fd("haar_ff.xml");
    ocl::oclMat frame, frameGray;
    Mat frameCpu;
    vector<Rect> faces;
    for(;;){
    // 处理循环
    vcap >> frameCpu;
    frame = frameCpu;
    ocl::cvtColor(frame, frameGray, BGR2GRAY);
    ocl::equalizeHist(frameGray, frameGray);
    fd.detectMultiScale(frameGray, faces, ...);
    // 绘制矩形 …
    // 显示图像 …
    }
    用于从视频文件、图像序列或摄像头捕获视频的类。
    Definition videoio.hpp:772
  • OpenCL 感知代码 OpenCV-3.x
    // 初始化
    VideoCapture vcap(...);
    CascadeClassifier fd("haar_ff.xml");
    UMat frame, frameGray; // 与纯 CPU 版本相比唯一的变化
    vector<Rect> faces;
    for(;;){
    // 处理循环
    vcap >> frame;
    cvtColor(frame, frameGray, BGR2GRAY);
    equalizeHist(frameGray, frameGray);
    fd.detectMultiScale(frameGray, faces, ...);
    // 绘制矩形 …
    // 显示图像 …
    }
    用于对象检测的 Cascade 分类器类。
    定义 objdetect.hpp:258
    Definition mat.hpp:2460

CUDA

CUDA 模块已移至 opencv_contrib 仓库。

文档格式

文档已转换为 Doxygen 格式。您可以在 OpenCV 参考文档的 教程 部分找到更新的文档编写指南(为 OpenCV 编写文档)。

同时支持两个版本

在某些情况下,可以同时支持 OpenCV 的两个版本。

源代码

要在应用程序源代码中检查库的主版本,应使用以下方法

#if CV_MAJOR_VERSION == 2
// 执行 OpenCV 2 代码
#elif CV_MAJOR_VERSION == 3
// 执行 OpenCV 3 代码
#endif
注意
不要使用 CV_VERSION_MAJOR,它在 2.4 和 3.x 分支中具有不同的含义!

构建系统

通过在构建系统中检查库版本,可以在应用程序中链接不同的模块或启用/禁用某些功能。标准 cmake 或 pkg-config 变量可用于此目的

  • cmake 的 OpenCV_VERSION 将包含完整版本号,例如 "2.4.11" 或 "3.0.0"
  • cmake 的 OpenCV_VERSION_MAJOR 将只包含主版本号:2 或 3
  • pkg-config 文件具有标准字段 Version

示例

if(OpenCV_VERSION VERSION_LESS "3.0")
# 使用 2.4 模块
else()
# 使用 3.x 模块
endif()