OpenCV过渡指南
变更概述
本文档面向希望将代码迁移到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和all C风格的API定义已被移动到单独的标题(例如opencv2 / core / core_c.h)。
算法接口
一般算法使用模式已经改变了:现在它必须在包裹在智能指针cv :: Ptr的堆上创建。版本2.4允许堆栈和堆分配,直接或通过智能指针。
get和set方法已经从cv :: Algorithm类以及CV_INIT_ALGORITHM宏中删除。在3.0中,所有属性都已转换为getProperty / setProperty纯虚拟方法。因此,它是不是能够创建和使用CV ::算法通过名称实例(使用通用的算法::创建(字符串)方法),应该显式调用相应的工厂方法。
更改模块
- ml模块已被重写
- highgui模块已经分为几部分:imgcodecs,videoio和highgui本身
- features2d模块已被重组(某些功能检测器已被移动到opencv_contrib / xfeatures2d模块)
- 传统的,非自由的模块已被删除。一些算法已被移动到不同的位置,一些算法被完全重写或删除
- CUDA API已经更新(gpu模块 - >几个cuda模块,命名空间gpu - >命名空间cuda)
- OpenCL API已更改(ocl模块已被删除,单独的ocl :: implementation - > Transparent API)
- 其他一些方法和类已被重定位
过渡提示
本节通过实例介绍具体的操作。
准备2.4
在最新的2.4.11 OpenCV版本中进行的一些更改允许您准备当前的代码库进行迁移:
- cv :: makePtr函数现在可用
- opencv2 / <module> .hpp头已创建
新标题布局
注意: OpenCV 3.0中进行了旨在简化迁移的更改,因此不需要以下说明,但建议。
- 更换旧模块标题的内含物
// old header
#include "opencv2/<module>/<module>.hpp"
// new header
#include "opencv2/<module>.hpp"
- 如果您的代码使用C API(cv*函数,Cv*结构或CV_*枚举),请包含相应的*_c.h头文件。虽然建议使用C ++ API,但大多数C函数仍然可以在单独的头文件(opencv2 / core / core_c.h,opencv2 / core / types_c.h,opencv2 / imgproc / imgproc_c.h等)中访问。
现代使用算法
- 必须使用cv :: makePtr函数或相应的静态工厂方法(如果可用)创建算法实例:
// good ways
Ptr<SomeAlgo> algo = makePtr<SomeAlgo>(...);
Ptr<SomeAlgo> algo = SomeAlgo::create(...);
其他方式已弃用:
// bad ways
Ptr<SomeAlgo> algo = new SomeAlgo(...);
SomeAlgo * algo = new SomeAlgo(...);
SomeAlgo algo(...);
Ptr<SomeAlgo> algo = Algorithm::create<SomeAlgo>("name");
- 应通过相应的虚拟方法访问算法属性,getSomeProperty / setSomeProperty,通用get / set方法已被删除:
// good way
double clipLimit = clahe->getClipLimit();
clahe->setClipLimit(clipLimit);
// bad way
double clipLimit = clahe->getDouble("clipLimit");
clahe->set("clipLimit", clipLimit);
clahe->setDouble("clipLimit", clipLimit);
- 删除initModule_<moduleName>()呼叫
机器学习模块
由于该模块已被重写,因此需要花费一些时间来适应您的软件。所有算法都位于单独的ml命名空间及其基类StatModel中。单独的SomeAlgoParams类已被替换为一组相应的getProperty / setProperty方法。
下表说明了2.4和3.0机器学习类之间的对应关系。
2.4 | 3.0 |
---|---|
CvStatModel | CV ::毫升:: StatModel |
CvNormalBayesClassifier | CV ::毫升:: NormalBayesClassifier |
CvKNearest | CV ::毫升:: KNearest |
CvSVM | CV ::毫升:: SVM |
CvDTree | CV ::毫升:: DTrees |
CV升压 | CV ::毫升::升压 |
CvGBTrees | 未实现 |
CvRTrees | CV ::毫升::的rtrees |
CvERTrees | 未实现 |
EM | CV ::毫升:: EM |
CvANN_MLP | CV ::毫升:: ANN_MLP |
未实现 | CV ::毫升::逻辑回归 |
CvMLData | CV ::毫升:: 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' returns an instance of ml::TrainData class
特征检测
一些算法(FREAK,BRIEF,SIFT,SURF)已被移动到opencv_contrib存储库,到xfeatures2d模块,xfeatures2d命名空间。他们的界面也被改变了(继承于cv::Feature2D基类)。
xfeatures2d模块类的列表:
- cv :: xfeatures2d :: BriefDescriptorExtractor - 用于计算简要描述符的类(2.4位置:features2d)
- cv :: xfeatures2d :: FREAK - 实现FREAK(Fast Retina Keypoint)关键点描述符的类(2.4位置:features2d)
- cv :: xfeatures2d :: StarDetector - 该类实现了CenSurE检测器(2.4位置:features2d)
- cv :: xfeatures2d :: SIFT - 使用Scale Invariant特征变换(SIFT)算法提取关键点和计算描述符的类(2.4位置:非自由)
- cv :: xfeatures2d :: SURF - 用于从图像中提取加速的强大功能的类(2.4位置:非自由)
需要执行以下步骤:
- 将opencv_contrib添加到编译过程中
- 包含opencv2/xfeatures2d.h标题
- 使用命名空间 xfeatures2d
- 用或替换operator()呼叫detect,compute或detectAndCompute如果需要
一些类现在使用一般方法detect,compute或detectAndCompute由Feature2D基类而不是自定义提供operator()
以下代码片段说明了区别(从video_homography.cpp示例):
using namespace cv;
// ====== 2.4 =======
#include "opencv2/features2d/features2d.hpp"
BriefDescriptorExtractor brief(32);
GridAdaptedFeatureDetector detector(new FastFeatureDetector(10, true), DESIRED_FTRS, 4, 4);
// ...
detector.detect(gray, query_kpts); //Find interest points
brief.compute(gray, query_kpts, query_desc); //Compute brief descriptors at each keypoint location
// ====== 3.0 =======
#include "opencv2/features2d.hpp"
#include "opencv2/xfeatures2d.hpp"
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
OpenCL的
所有专门的ocl实现都隐藏在一般的C ++算法接口之后。现在可以在运行时动态选择功能执行路径:CPU或OpenCL; 这个机制也被称为“透明API”。
新类cv :: UMat旨在以方便的方式隐藏与OpenCL设备的数据交换。
以下示例说明了API修改(来自OpenCV站点):
- OpenCL感知代码OpenCV-2.x
// initialization
VideoCapture vcap(...);
ocl::OclCascadeClassifier fd("haar_ff.xml");
ocl::oclMat frame, frameGray;
Mat frameCpu;
vector<Rect> faces;
for(;;){
// processing loop
vcap >> frameCpu;
frame = frameCpu;
ocl::cvtColor(frame, frameGray, BGR2GRAY);
ocl::equalizeHist(frameGray, frameGray);
fd.detectMultiScale(frameGray, faces, ...);
// draw rectangles …
// show image …
}
- OpenCL感知代码OpenCV-3.x
// initialization
VideoCapture vcap(...);
CascadeClassifier fd("haar_ff.xml");
UMat frame, frameGray; // the only change from plain CPU version
vector<Rect> faces;
for(;;){
// processing loop
vcap >> frame;
cvtColor(frame, frameGray, BGR2GRAY);
equalizeHist(frameGray, frameGray);
fd.detectMultiScale(frameGray, faces, ...);
// draw rectangles …
// show image …
}
CUDA
cuda模块已经分成几个较小的部分:
- cuda - CUDA加速计算机视觉
- cudaarithm - 矩阵运算
- cudabgsegm - 背景分割
- cudacodec - 视频编码/解码
- cudafeatures2d - 特征检测和描述
- 咖啡杯 - 图像过滤
- cudaimgproc - 图像处理
- cudalegacy - 遗产支持
- cudaoptflow - 光流
- cudastereo - 立体匹配
- 可口可乐 - 图像扭曲
- cudev - 设备层
gpu命名空间已被删除,使用cv :: cuda命名空间。许多课程也已经重新命名,例如:
- gpu::FAST_GPU- > cv :: cuda :: FastFeatureDetector
- gpu::createBoxFilter_GPU- > cv :: cuda :: createBoxFilter
文件格式
文档已转换为Doxygen格式。您可以在OpenCV参考文档(OpenCV的写作文档)的教程部分找到更新的文档写作指南。
支持两个版本
在某些情况下,可以支持两种版本的OpenCV。
源代码
要检查应用程序源代码中的库主要版本,应使用以下方法:
#include "opencv2/core/version.hpp"
#if CV_MAJOR_VERSION == 2
// do opencv 2 code
#elif CV_MAJOR_VERSION == 3
// do opencv 3 code
#endif
- 注意
- 不要使用CV_VERSION_MAJOR,它对2.4和3.x分支有不同的含义!
构建系统
通过检查构建系统中的库版本,可以链接不同的模块或启用/禁用应用程序中的某些功能。可以使用标准cmake或pkg-config变量:
- OpenCV_VERSION 对于cmake将包含完整版本:“2.4.11”或“3.0.0”
- OpenCV_VERSION_MAJOR 对于cmake将仅包含主版本号:2或3
- pkg-config文件有标准字段 Version
例:
if(OpenCV_VERSION VERSION_LESS "3.0")
# use 2.4 modules
else()
# use 3.x modules
endif()
更多建议: