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()