OpenCV  4.10.0
开源计算机视觉
正在加载...
正在搜索...
无匹配项
过渡指南

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

原作者Maksim Shabunin
兼容性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 版允许堆栈分配和堆分配,可以直接分配或通过智能指针分配。

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

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

过渡提示

本节描述了具体的操作并给出了示例。

准备 2.4

在最新版 2.4.11 OpenCV 中进行的某些更改可让您准备当前代码库进行迁移

  • 现可使用 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>() 调用

机器学习模块

由于该模型经过重写,因此将软件改编到新模型中需要费一番功夫。所有算法与其基本类StatModel一起位于单独的ml命名空间中。单独的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;
// ======== version 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, // boost_type
100, // weak_count
0.95, // weight_trim_rate
2, // max_depth
false, //use_surrogates
0 // priors
);
boost.train( trainSamples, CV_ROW_SAMPLE, trainClasses, Mat(), Mat(), var_types, Mat(), params );
// ======== version 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:812
int cols
定义 mat.hpp:2138
std::shared_ptr< _Tp > Ptr
定义 cvstd_wrapper.hpp:23
无符号字符 uchar
定义 interface.h:51
#define CV_8UC1
定义 interface.h:88
与磁盘上的文件中关联的文件存储的“黑匣子”表示形式。
定义 core.hpp:102

检测功能

某些算法(FREAK、BRIEF、SIFT、SURF)已移动到opencv_contrib存储库中的xfeatures2d模块、xfeatures2d命名空间。它们的接口也已更改(继承自cv::Feature2D基类)。

xfeatures2d模块类的列表

需要执行以下步骤

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

现在某些类使用由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); //在每个关键点位置计算简要描述符
// ====== 3.0 =======
using namespace cv::xfeatures2d;
Ptr<BriefDescriptorExtractor> brief = BriefDescriptorExtractor::create(32);
Ptr<FastFeatureDetector> detector = FastFeatureDetector::create(10, true);
// ...
detector->detect(gray, query_kpts); //Find interest points
brief->compute(gray, query_kpts, query_desc); //Compute brief descriptors at each keypoint location
使用 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, ...);
    // 绘制矩形……
    // 显示图像……
    }
    用于从视频文件、图像序列或摄像头中捕获视频的类。
    定义 videoio.hpp:731
  • 认识 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, ...);
    // 绘制矩形……
    // 显示图像……
    }
    用于目标检测的级联分类器类。
    定义 objdetect.hpp:258
    定义 mat.hpp:2433

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 文件具有标准字段版本

示例

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