簡介

OpenCV(開源計算機視覺庫 http://opencv.org ) 是一個開源的BSD許可庫,包含數百種計算機視覺算法。 該文檔描述了所謂的OpenCV 2.x API,它本質上是一個C ++ API,與基于C語言的OpenCV 1.x API有所差異。此文檔針對于OpenCV 2.X API翻譯,OPenCV 1.X API.pdf有關于C語言接口解釋,敬請關注。

OpenCV具有模塊化結構,這意味著該包包含多個共享庫或靜態庫。 可以使用以下模塊:

  • Core functionality:基礎數據模塊,包含一些發雜數據結構和基本函數方法。
  • Image processing :圖像處理模塊,包括線性和非線性圖像濾波,幾何圖像變換(調整大小,仿射和透視扭曲,基于通用表的重新映射),顏色空間轉換,直方圖等。
  • video : 視頻分析模塊,包括運動估計,背景減法和對象跟蹤算法。
  • calib3d : 基本的多視圖幾何算法,單一和立體攝像機校準,對象姿態估計,立體視覺匹配算法和3D重建元素。
  • features2d : 特征檢測器,描述符和描述符匹配器。
  • objdetect : 檢測預定義類的對象和實例(例如,面部,眼睛,馬克杯,人,汽車等)。
  • highgui :UI界面以及UI功能
  • Video I/O :簡單的視頻捕獲和視頻編解碼器接口。
  • gpu : 支持不同OpenCV模塊的GPU加速算法.
  • ... 一些其他幫助器模塊,例如FLANN和Google測試包裝器,Python綁定等。
    文檔的后續章節講述了每個模塊的功能。 但首先,請確保熟悉庫中徹底使用的常見API概念。

API 概述

cv Namespace

所有OpenCV類和函數都放在cv命名空間中。 因此,要從代碼中訪問此功能,請使用cv :: specifier或using namespace cv; 指示:

#include "opencv2/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2, CV_RANSAC, 5);
...

or :

#include "opencv2/core.hpp"
using namespace cv;
...
Mat H = findHomography(points1, points2, CV_RANSAC, 5 );
...

在遇到OpenCV外部名稱可能與STL或其他庫沖突。 在這種情況下,使用顯式名稱空間說明符來解決名稱沖突:

Mat a(100, 100, CV_32F);
randu(a, Scalar::all(1), Scalar::all(std::rand()));
cv::log(a, a);
a /= std::log(2.);
Automatic Memory Management(內存自動管理)

OpenCV自動處理所有內存。

首先,函數和方法使用的std :: vector,Mat和其他數據結構都有析構函數,可以在需要時釋放底層內存緩沖區。 這意味著析構函數并不總是釋放緩沖區,就像Mat一樣。 他們考慮了可能的數據共享。 析構函數遞減與矩陣數據緩沖區關聯的引用計數器。 當且僅當引用計數器達到零時,即當沒有其他結構引用相同的緩沖區時,緩沖區被釋放。 同樣,復制Mat實例時,實際上并未復制任何實際數據。 相反,引用計數器遞增以記住存在相同數據的另一個所有者。 還有Mat :: clone方法可以創建矩陣數據的完整副本。 請參閱以下示例:

 // create a big 8Mb matrix
Mat A(1000, 1000, CV_64F);
// create another header for the same matrix;
// this is an instant operation, regardless of the matrix size.
Mat B = A;
// create another header for the 3-rd row of A; no data is copied either
Mat C = B.row(3);
// now create a separate copy of the matrix
Mat D = B.clone();
// copy the 5-th row of B to C, that is, copy the 5-th row of A
// to the 3-rd row of A.
B.row(5).copyTo(C);
// now let A and D share the data; after that the modified version
// of A is still referenced by B and C.
A = D;
// now make B an empty matrix (which references no memory buffers),
// but the modified version of A will still be referenced by C,
// despite that C is just a single row of the original A
B.release();
// finally, make a full copy of C. As a result, the big modified
// matrix will be deallocated, since it is not referenced by anyone
C = C.clone();

你看到Mat和其他基本結構的使用很簡單。 但是,如果不考慮自動內存管理而創建的高級類甚至用戶數據類型呢? 對于他們來說,OpenCV提供的Ptr模板類與C ++ 11中的std :: shared_ptr類似。 所以,而不是使用普通指針:

T* ptr = new T(...);

你可以使用:

Ptr<T> ptr(new T(...));

or:

Ptr<T> ptr = makePtr<T>(...);

Ptr <T>封裝指向T實例的指針和指針相關聯的引用計數器。 有關詳細信息,請參閱Ptr說明。

Automatic Allocation of the Output Data(輸出數據的自動分配)

OpenCV自動釋放內存,并在大多數時間自動為輸出函數參數分配內存。 因此,如果函數具有一個或多個輸入數組(cv :: Mat實例)和一些輸出數組,則會自動分配或重新分配輸出數組。 輸出數組的大小和類型由輸入數組的大小和類型決定。 如果需要,函數會采用額外的參數來幫助確定輸出數組屬性。
Example:

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main(int, char**)
{
    VideoCapture cap(0);
    if(!cap.isOpened()) return -1;
    Mat frame, edges;
    namedWindow("edges",1);
    for(;;)
    {
        cap >> frame;
        cvtColor(frame, edges, COLOR_BGR2GRAY);
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
        Canny(edges, edges, 0, 30, 3);
        imshow("edges", edges);
        if(waitKey(30) >= 0) break;
    }
    return 0;
}

由于視頻幀分辨率和比特深度對于視頻捕獲模塊是已知的,所以陣列幀由">>"運算符自動分配。 數組邊緣由cvtColor函數自動分配。 它具有與輸入數組相同的大小和位深度。 通道數為1,因為顏色轉換代碼COLOR_BGR2GRAY被傳遞,這意味著顏色到灰度轉換。 請注意,在第一次執行循環體時,幀和邊僅分配一次,因為所有下一個視頻幀具有相同的分辨率。 如果以某種方式更改視頻分辨率,則會自動重新分配數組。
該技術的關鍵組件是Mat :: create方法。 它需要所需的數組大小和類型。 如果數組已具有指定的大小和類型,則該方法不執行任何操作。 否則,它釋放先前分配的數據(如果有的話)(這部分涉及遞減引用計數器并將其與零比較),然后分配所需大小的新緩沖區。 大多數函數為每個輸出數組調用Mat :: create方法,因此實現了自動輸出數據分配。
這個方案的一些值得注意的特別之處是cv :: mixChannels,cv :: RNG :: fill,以及一些其他函數和方法。 它們無法分配輸出數組,因此您必須提前執行此操作。

Saturation Arithmetics(飽和度技術)

作為一個計算機視覺庫,OpenCV經常處理圖像像素,這些像素通常以緊湊的,每通道8-bit或16-bit編碼形式,因此具有有限的值范圍。 此外,對圖像的某些操作,如色彩空間轉換,亮度/對比度調整,銳化,復雜插值(bi-cubic,Lanczos)可以產生超出可用范圍的值。 如果只存儲結果的最低8(16)bit,則會導致視覺偽像,并可能影響進一步的圖像分析。 為了解決這個問題,使用所謂的飽和算術。 例如,要將操作結果r存儲到8位圖像,您會在0..255范圍內找到最接近的值:

                     I(x,y)=min(max(round(r),0),255)

類似的規則適用于8-bit帶符號的16-bit有符號和無符號類型。 這種語義在庫中的任何地方都使用。 在C ++代碼中,它使用類似于標準C ++強制轉換操作的saturate_cast <>函數完成。 見下文上面提供的公式的實施:

   I.at<uchar>(y, x) = saturate_cast<uchar>(r);

其中cv :: uchar是OpenCV 8-bit無符號整數類型。 在優化的SIMD代碼中,使用諸如paddusb,packuswb等SSE2指令。 它們有助于實現與C ++代碼完全相同的行為。
Note
當結果為32位整數時,不應用飽和度。

Fixed Pixel Types. Limited Use of Templates(固定像素,受限模板)

模板是C ++的一個很好的特性,它可以實現非常強大,高效且安全的數據結構和算法。但是,廣泛使用模板可能會大大增加編譯時間和代碼大小。此外,當專門使用模板時,很難將界面和實現分開。這對于基本算法來說可能很好,但對于計算機視覺庫來說并不好,其中單個算法可能跨越數千行代碼。正因為如此,并且為了簡化其他開發語言的綁定,如Python,Java,Matlab,它們根本沒有模板或具有有限的模板功能,當前的OpenCV實現基于多態和基于模板的運行時調度。在那些運行時調度太慢(像素訪問運算符),不可能(通用Ptr <>實現)或非常不方便(saturate_cast <>())的地方,當前實現引入了小模板類,方法和函數。在當前OpenCV版本的任何其他地方,模板的使用都是有限的。
因此,庫可以操作有限的固定原始數據類型集。 也就是說,數組元素應該具有以下類型之一:

  • 8-bit unsigned integer (uchar)

  • 8-bit signed integer (schar)

  • 16-bit unsigned integer (ushort)

  • 16-bit signed integer (short)

  • 32-bit signed integer (int)

  • 32-bit floating-point number (float)

  • 64-bit floating-point number (double)

  • a tuple of several elements where all elements have the same type (one of the above). An array whose elements are such tuples, are called multi-channel arrays, as opposite to the single-channel arrays, whose elements are scalar values. The maximum possible number of channels is defined by the CV_CN_MAX constant, which is currently set to 512.
    對于這些基本類型,應用以下枚舉:

    enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };
    

可以使用以下選項指定Multi-channel (n-channel)類型:

  • CV_8UC1 ... CV_64FC4 constants (for a number of channels from 1 to 4)

  • CV_8UC(n) ... CV_64FC(n) or CV_MAKETYPE(CV_8U, n) ... CV_MAKETYPE(CV_64F, n) macros when the number of channels is more than 4 or unknown at the compilation time.
    Note
    CV_32FC1 == CV_32F, CV_32FC2 == CV_32FC(2) == CV_MAKETYPE(CV_32F, 2), andCV_MAKETYPE(depth, n) == ((depth&7) + ((n-1)<<3)``。 這意味著常量類型由深度形成,取最低3位,通道數減1,取下一個`log2(CV_CN_MAX)bit。
    Examples:

    Mat mtx(3, 3, CV_32F); // make a 3x3 floating-point matrix
    Mat cmtx(10, 1, CV_64FC2); // make a 10x1 2-channel floating-point
                       // matrix (10-element complex vector)
    Mat img(Size(1920, 1080), CV_8UC3); // make a 3-channel (color)           image
                                                        // of 1920 columns and 1080 rows.
     Mat grayscale(image.size(), CV_MAKETYPE(image.depth(), 1)); //       make a 1-channel image of
                                                        // the same size and sam
                                                       // channel type as img
    

使用OpenCV無法構造或處理具有更復雜元素的數組。 此外,每個函數或方法只能處理所有可能的數組類型的子集。 通常,算法越復雜,支持的格式子集越小。 請參閱下面這些限制的典型示例:

  • 人臉檢測算法僅適用于8-bit灰度或彩色圖像。
  • 線性代數函數和大多數機器學習算法僅適用于浮點數組。
  • 基礎函數,如cv :: add,支持所有類型。
  • 色彩空間轉換功能支持8-bit無符號,16bit無符號和32-bit浮點類型。
    每個功能的受支持類型的子集已根據實際需要進行定義,并可根據用戶請求在將來進行擴展。
InputArray and OutputArray

許多OpenCV函數處理密集的二維或多維數組。 通常這樣的函數將cppMat作為參數,但在某些情況下,使用std :: vector <>(如,對于點集)或Matx <>(對于3x3單應矩陣等)更方便。 為了避免API中的許多重復,引入了特殊的“代理”類。 基礎“代理”類是InputArray。 它用于在函數輸入上傳遞只讀數組。 從InputArray類派生的OutputArray用于指定函數的輸出數組。 通常你不應該關心那些中間類型(并且您不應該顯示聲明這些類型的變量) - 它們都將自動運行。 你可以假設你可以使用Mat,std :: vector <>,Matx <>,Vec <>或Scalar來代替InputArray / OutputArray。 當一個函數有一個可選的輸入或輸出數組,并且你沒有或不想要一個時,傳遞cv :: noArray()。

Error Handling

OpenCV使用異常來表示嚴重錯誤。 當輸入數據具有正確的格式并且屬于指定的值范圍,但算法由于某種原因不能成功時(例如,優化算法沒有收斂),它返回一個特殊的錯誤代碼(通常只是一個布爾變量)。
異常可以是cv :: Exception類或其派生類的實例。 反過來,cv :: Exception是std :: exception的衍生物。 因此,可以使用其他標準C ++庫組件在代碼中優雅地處理它。
異常通常使用CV_Error(錯誤代碼,描述)宏或其類似printf的CV_Error_(錯誤代碼,printf-spec,(printf-args))變體或使用檢查條件和的CV_Assert(條件)宏來拋出異常。 不滿意時拋出異常。 對于性能關鍵代碼,CV_DbgAssert(條件)僅保留在Debug配置中。 由于自動內存管理,所有中間緩沖區在發生突然錯誤時會自動解除分配。 如果需要,您只需要添加一個try語句來捕獲異常:

try
{
    ... // call OpenCV
 }
catch( cv::Exception& e )
{
    const char* err_msg = e.what();
    std::cout << "exception caught: " << err_msg << std::endl;
}
Multi-threading and Re-enterability

當前的OpenCV實現是完全可以重新輸入的。 也就是說,可以從不同的線程調用相同的函數,類實例的相同常量方法或不同類實例的相同非常量方法。 此外,相同的cv :: Mat可以在不同的線程中使用,因為引用計數操作使用特定于體系結構的原子指令。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,065評論 25 708
  • 1、通過CocoaPods安裝項目名稱項目信息 AFNetworking網絡請求組件 FMDB本地數據庫組件 SD...
    陽明AGI閱讀 16,003評論 3 119
  • 今天還是丁酉年正月十六。這還是地二十三篇簡書。 時隔十分鐘,我為什么又回來了呢。很明顯,我想起來了。 還是要說身邊...
    塵___世_美閱讀 145評論 0 0
  • 公司簡介 廣州普升商貿有限公司創立于2010年,位于廣東省廣州市,是一家主要經營紫砂壺的企業。主要產品有圓壺、方壺...
    嵐兒0閱讀 231評論 0 0