24
前言 這本書是 C++ 開放原始碼電腦視覺資料庫(OpenCV3.x 版的工作指南,目的是讓讀 者瞭解電腦視覺的背景,以有效地使用 OpenCV本書的目的 電腦視覺是個快速崛起的領域,主要的原因來自四種趨勢: 因為行動電話的普及,上百萬人手上都有一台照相機。 • Internet 與搜尋引擎的結合,讓大量的影像與影片資料被儲存在龐大的資料庫中。 你只要付出少許的代價,就可以讓電腦具備強大的處理能力。 視覺演算法更成熟(伴隨著深層類神經網路的問世,OpenCV 也逐漸支援這種演算法, opencv_contrib dnnhttps://github.com/opencv/opencv_contrib[opencv_contrib])。 在電腦視覺興起的過程中,OpenCV 讓成千上萬人更有效率地進行視覺工作。現在 OpenCV 3.x 可讓學生、研究員、專業人士及企業主更有效率地實作專案,它也在許多 平台上提供最佳化且一致的 C++ 電腦視覺結構,讓人們迅速地開始進行研究。 本書的目的在於: 詳細說明 OpenCV,包括詳述函式呼叫規範的真正含意,以及如何正確使用它們 讓讀者直觀地理解視覺演算法的原理 讓讀者知道該選擇哪一種演算法,與使用它們的時機

前言 - 碁峰資訊epaper.gotop.com.tw/pdf/A291.pdf · 你不需要依序閱讀本書。你可以將它當成使用者手冊,在需要某個函式時查詢它,並且 在你想要瞭解它“幕後”如何運作時閱讀函式說明。但是,本書的目的是扮演教學的角

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

前言

這本書是 C++開放原始碼電腦視覺資料庫(OpenCV)3.x版的工作指南,目的是讓讀者瞭解電腦視覺的背景,以有效地使用 OpenCV。

本書的目的

電腦視覺是個快速崛起的領域,主要的原因來自四種趨勢:

• 因為行動電話的普及,上百萬人手上都有一台照相機。

• Internet與搜尋引擎的結合,讓大量的影像與影片資料被儲存在龐大的資料庫中。

• 你只要付出少許的代價,就可以讓電腦具備強大的處理能力。

• 視覺演算法更成熟(伴隨著深層類神經網路的問世,OpenCV也逐漸支援這種演算法,見 opencv_contrib的 dnn(https://github.com/opencv/opencv_contrib)[opencv_contrib])。

在電腦視覺興起的過程中,OpenCV 讓成千上萬人更有效率地進行視覺工作。現在OpenCV 3.x可讓學生、研究員、專業人士及企業主更有效率地實作專案,它也在許多平台上提供最佳化且一致的 C++電腦視覺結構,讓人們迅速地開始進行研究。

本書的目的在於:

• 詳細說明 OpenCV,包括詳述函式呼叫規範的真正含意,以及如何正確使用它們

• 讓讀者直觀地理解視覺演算法的原理

• 讓讀者知道該選擇哪一種演算法,與使用它們的時機

xviii | 前言

• 提供許多可動作的範例程式,為讀者立下起跑點,實作電腦視覺與機器學習演算法

• 提出一些做法,讓你在出錯時可修正一些較進階的程式

透過本書講解 OpenCV的方式,讀者可以快速地使用電腦視覺來做一些有趣且好玩的作品。它可以讓你直觀地瞭解演算法的原理,在設計視覺程式與除錯的過程中引導你,並

讓你更容易理解與記住外界的正式文件說明的電腦視覺與機器學習演算法。

本書對象

本書的內容包括說明文字、可動作的範例程式,以及 OpenCV 3.x程式庫中的 C++電腦視覺工具的解說。所以這本書應該可幫助各種使用者:

專業人士與企業主

對於需要快速建立或實作電腦視覺系統原型的職業專家來說,我們的範例程式提供

一個框架來讓你可以快速開始實作。書中對於演算法的說明,可快速地教導與提醒

讀者如何著手實作。OpenCV 3.x是建立在硬體加速層之上的,所以你製作的演算法

可以有效地執行,無縫地利用各種硬體平台的優點。

學生

這是一本我希望在當學生時能夠擁有的書籍。它裡面有直觀的解釋、詳細的說明,

以及許多範例程式,可讓你快速上手,編寫有趣的課堂專案,最終為這個領域貢獻

新的研究成果。

教師

電腦視覺是變化快速的領域。我們發現最有效的做法,是讓學生立刻閱讀文章,同

時,教師在必要時進行詳細的講解,並提供最新的論文或客座專家講座。學生可以

儘早開始進行課業專案,嘗試較有挑戰性的工作。

業餘愛好者

電腦視覺真的很有趣,而這本書的目的,正是為了教你如何深度地理解它。我們把

重點放在提供直觀、文件化,且可動作的程式碼給讀者,來讓讀者可以快速寫出即

時的視覺應用程式。

前言 | xix

不適合本書的讀者

本書不是正式文件。我們會在許多地方用數學來解說 1,但目的是為了讓你直接瞭解演算

法背後的原理,或釐清這些演算法的發展過程中,任何假設的意義。我們並未在這裡做

任何正式的數學解釋,這可能會讓一些寫過正式論文的人不太開心。

這本書比較屬於“應用”性質。它的目的是提供整體性的協助,而非專業性的電腦視覺

(例如,醫學影像或遠端感測分析)。

也就是說,我們相信讓學生先閱讀本書的說明之後,他們不但可以更瞭解理論,也可以

深刻記憶。因此,這本書很適合當成理論課程的參考書,也適合當成介紹課程或專案課

程的教科書。

關於本書的程式

本書的程式都是以 OpenCV 3.x 版寫成的。這些程式應該都可以在 Linux、Windows與 OS X 之下運行。藉由閱讀線上參考文件,你也可以讓 OpenCV 3.x 在 Android與 iOS 上完整運行。你可以從本書的網站取得書中的程式原始碼(http://bit.ly/

learningOpenCV3); 在 GitHub 取 得 OpenCV 的 原 始 碼(https://github.com/opencv/

opencv),以及從 OpenCV的 SourceForge網站下載組建好的版本(http://sourceforge.net/

projects/opencvlibrary)。

OpenCV仍在持續開發中,每季都會釋出官方版本。為了跟上最新版本,你可以從上述的 GitHub網站取得最新的程式碼。OpenCV的網站位於 http://opencv.org,它也有一個

wiki可供開發人員參考:https://github.com/opencv/opencv/wiki。

使用本書的先決條件

多數情況下,讀者只要知道如何編寫 C++程式即可。本書的數學章節都是選讀的,我們也這樣標記它們。這些數學涉及簡單的代數與基本的矩數代數,並假設你某種程度地

瞭解最小平方最佳化問題(least-squares optimization problems)的解法,與高斯分布(Gaussian distributions)、貝氏法則(Bayes' law)和函數導數的基本知識。數學的目的,是為了開發你對演算法的直覺。讀者可以跳過數學與演算法的說明,只使用函式定

義與範例程式來開發與執行視覺應用程式。

1 特別提醒可能會跳過這些小節的讀者。

xx | 前言

本書的最佳用法

你不需要依序閱讀本書。你可以將它當成使用者手冊,在需要某個函式時查詢它,並且

在你想要瞭解它“幕後”如何運作時閱讀函式說明。但是,本書的目的是扮演教學的角

色。它可以讓你瞭解電腦視覺的基本概念,以及書中的演算法的用法與使用時機。

本書期望成為大學與研究所的電腦視覺主要與輔助教材。我們的基本策略,是讓學生使

用這本書來大致瞭解電腦視覺,接著提供其他的教科書,來讓他們閱讀較正式的文獻,

以及讓他們進一步閱讀外面的論文。每一章的結尾都有一些練習題,可協助測試學生的

理解程度,並進一步開發他們的直覺。

你可以採取以下的任何一種方式來閱讀:

隨意

先閱讀第 1章至第 5章,接著視你的需求閱讀適合的章或節。除了第 18章與第 19章(討論相機校準與立體成像)與第 20章、21章與 22章(討論機器學習)之外,你不需要按照順序閱讀本書。企業主與正在學習專案課程的學生適合採取這種方

式。

按照進度學習

每週閱讀兩章,用十一週讀完第 1至 22章(第 23章可以很快讀完)。接著開始寫專案,並深入研究你選擇的領域,酌情參考其他的文章與論文。

快速瀏覽

以你的閱讀與理解能力,快速看完第 1至 23章。接著開始寫專案,並參考其他的文章與論文,深入研究你選擇的領域。這或許是適合專家的選項,也應該適合較進階

的電腦視覺課程。

第 20章是簡短的一章,討論基本的機器學習,接下來的第 21章與第 22章進一步說明OpenCV的機器學習演算法,與如何使用它們。當然,在辨識物件時,機器學習是不可或缺的一環,它也是電腦視覺的主角,但它是需要用整本書來說明的領域。專業人士應

該可認同這些內容很適合當成進一步探索的起點,或者,你可以直接使用程式庫的程式

來開發商務軟體。OpenCV 3.x已經大大地簡化與統一機器學習的介面了。

前言 | xxi

我們最喜歡的電腦視覺教學方式是快速帶過課程內容,讓學生可以掌握事物運作的原

理,接著讓學生實作有意義的課堂專案,同時在你選擇的領域中,透過其他的文章或論

文來提供有深度、正規、嚴謹的內容。這種方法也適合季度、學期或兩個學期的課程。

如此一來,學生就可以大致了解他們的視覺專案與配合的程式碼,快速開始實作。當他

們開始進行有挑戰性且耗時的專案時,教師可協助他們開發複雜的系統,並進行除錯。

對於比較長期的課程,專案本身可以成為專案管理的教材。先建構可動作的系統,之後

再透過進一步的知識、更深入細節以及進行研究來提升品質。這種課程的目標,是為了

開發值得在會議上發表的專案,並且在進一步開發之後(在課程結束之後)當成論文來

發表。OpenCV 3.x裡面的 C++程式碼框架、Buildbots、GitHub的使用、pull request檢閱、單位與迴歸測試,以及文件都是很好範例,示範專業軟體基礎架構的初始樣貌,以

及如何納入其他的事物。

本書編排慣例

本書使用以下的編排規則:

斜體字(Italic)

代表新的術語、URL、電子郵件地址、檔案名稱、副檔案名稱、路徑名稱、目錄與Unix公用程式。中文以楷體字表示。

定寬字(Constant width)

代表命令、選項、開關、變數、屬性、鍵、函式、型態、類別、命名空間、方法、

模組、特性、參數、值、物件、事件、事件處理器、XML標籤、HTML標籤、檔案的內容,或命令的輸出結果。

定寬粗體字(Constant width bold)

代表應由使用者逐字輸入的指令或其他文字,以及範例程式的重點。

定寬斜體字(Constant width italic)

顯示必須用使用者提供的值來取代的文字。

[...]

代表參考文獻。

第一章

簡介

什麼是 OpenCV?OpenCV [OpenCV]是一種開放原始碼(見 http://opensource.org)的電腦視覺程式庫,

你可以從 http://opencv.org 下載它。1999 年,當 Gary Bradski [Bradski] 在 Intel 公司服務時,為了促進電腦視覺與人工智慧的發展,希望提供一個堅實的基礎架構來讓所有

人都可以在這個領域中發展,於是發起 OpenCV專案。這個程式庫是用 C與 C++寫成的,可在 Linux、Windows與 Mac OS X上運行。目前也有人正在開發 Python、Java、MATLAB與其他語言的介面,以及將程式庫移植到 Android與 iOS,以供行動應用程式使用。OpenCV多年來一直受到 Intel與 Google的支援,但貢獻最多的支援者是 Itseez [Itseez](最近已被 Intel收購),它完成大量的早期開發工作。最後,Arraiy [Arraiy]加入團隊,負責維護永遠開放且免費的 OpenCV.org [OpenCV]。

OpenCV的設計是為了提供有效率的運算,焦點放在即時的應用程式上。它是用最佳化的 C++寫成的,可充分利用多核心處理器的功能。如果你希望在 Intel架構上 [Intel]進一步取得自動最佳化,可以購買 Intel的 Integrated Performance Primitives (IPP) 程式庫

[IPP],它含有許多演算法領域的最佳化低階程式。當你安裝這個程式庫之後,OpenCV可以在執行階段自動使用適當的 IPP程式庫。從 OpenCV 3.0開始,Intel授權 OpenCV團隊與 OpenCV社群免費使用 IPP的子集合(暱稱 IPPICV),OpenCV已預設內建它。

OpenCV的其中一個目的是提供易用的電腦視覺基礎結構,以協助人們快速建立相當精密的視覺應用程式。OpenCV程式庫有超過 500個函式,橫跨許多視覺領域,包括工廠產品檢驗、醫學影像、保全、使用者介面、相機校準、立體視覺,與機器人技術。因為

電腦視覺與機器學習通常並肩同行,OpenCV也含有完整、通用的 Machine Learning程

2 | 第一章

式庫(ML模組)。這個子程式庫的目標是統計模式辨識與群聚。對 OpenCV的核心視覺工作而言,ML模組相當實用,但它也有足夠的泛用性,可解決任何機器學習問題。

誰會使用 OpenCV?多數的電腦科學家與實務程式員都知道電腦視覺扮演的角色,但很少人知道電腦視覺所

有的用途。例如,多數人都知道它在監控系統中的用途,也知道有愈來愈多人將它用在

Web的影像與影片上。有些人看過電腦視覺在遊戲介面的應用。但很少人知道,多數的空拍與街景影像(例如 Google街景服務)重度使用相機校準與影像拼接技術。有些人知道它適用於安全監控、無人飛行器與生物醫學分析。但很少人知道製造業使用機器視

覺的普遍程度:幾乎所有大量製造的東西都會在某個時刻被電腦視覺自動檢查。

OpenCV的開放原始碼授權結構已經可以讓你完全或部分使用 OpenCV來製作商業產品了。你不需要公開產品的原始碼,或將改善後的程式回饋給大眾,雖然我們希望你這麼

做。因為這些自由的授權條款,它有龐大的使用者社群,包括來自大公司的人(IBM、Microsoft、Intel、SONY、Siemens 與 Google,只列舉一些公司),及研究中心(例如 Stanford、MIT、CMU、Cambridge 與 INRIA)。另外也有一個 Yahoo Groups 論壇(http://groups.yahoo.com/group/OpenCV)可讓使用者發表問題與進行討論,它有大約

50,000位會員。OpenCV受到舉世的歡迎,在中國、日本、俄羅斯、歐洲與以色列都有龐大的使用者社群。

自從 OpenCV在 1999年 1月發表 alpha版開始,它已經被用在許多應用程式、產品與研究工作上。這些應用包括在衛星與網路地圖中拼接影像、影像掃描對準、降低醫學影

像雜訊、物件分析、保全與入侵偵測系統、自動監控與安全系統、製造檢驗系統、相

機校準、軍事應用,與空中、地面、水下的無人載具。它也被用來辨識聲音與音樂,

因為視覺辨識也可用在聲音波譜影像上。OpenCV是 Stanford大學的“Stanley”機器人的視覺系統關鍵成分,這個機器人在 DARPA沙漠機器人大賽中贏得兩百萬美元獎金[Thrun06]。

簡介 | 3

什麼是電腦視覺?

電腦視覺 1是一種轉換,將相機或攝影機拍到的資料轉換成決策(decision)或新的表示法。這些轉換都是為了完成特定的目標。輸入的資料可能包含一些環境資訊,例如

“這台相機被裝在車內”或“雷射測距儀指出 1公尺遠的地方有一個物體”。決策可能是“這個場景有一個人”或“這張照片裡面有 14個腫瘤細胞”。新的表示法可能是將彩色影像轉換成灰階影像,或將影像序列中相機的晃動移除。

因為我們是視覺動物,你很容易就會誤以為電腦視覺的工作很簡單。對你來說,在一張

影像中找一輛車子有多難?但你的直覺可能會出錯。人腦會將視覺訊號分成許多通道,

來將各種不同類型的資訊串流匯入大腦。你的大腦有一個關注系統,依工作的不同來認

出影像中重要的部分來檢視它,並抑制對其他部分的關注。視覺串流有大量的回饋訊

號,但是到目前為止,我們還不太瞭解它。大腦可用肌肉控制感應器官與其他感應器官

來取得大量的輸入,並且根據過去的生活經驗來產生交叉關聯。大腦的回饋迴圈會執行

所有處理階段,包括調整它的硬體感測器(眼睛),機械性地透過虹膜控制光線,並調

整視網膜表面的接收方式。

但是,在機器視覺系統中,電腦是從相機或磁碟接收網格狀排列的數字,僅此而已。多

數情況下,機器沒有內建的圖案辨識能力,無法自動控制聚焦與光圈,沒有多年累積

的交叉關聯經驗。多數的視覺系統仍然相當稚嫩。圖 1-1是一張汽車相片,在這張相片中,我們可以看到車子有個側邊後照鏡。電腦“看到”的,只是格狀排列的數字而已,

格子內的數字有大量的雜訊成分,所以它本身提供的資訊很少,不過這個格式排列的數

字就是電腦“看見”的一切。接下來,我們的工作就是將這些有雜訊的格狀排列數字轉

換成可以感知的“側邊後照鏡”。圖 1-2可讓你知道電腦視覺的困難在哪裡。

1 電腦視覺是個寬廣的領域。這本書提供的是這個領域的基礎,但我們也推薦 Trucco [Trucco98] 的簡介文章,Forsyth [Forsyth03] 的全面性參考文章,與 Hartley [Hartley06] 以及 Faugeras [Faugeras93] 關於 3D 視覺如何實際工作的探討。

4 | 第一章

但是相機看到這個:

圖 1-1 對電腦來說,汽車的側邊後照鏡只是格狀排列的數字而已

影像 1

影像 2

圖 1-2 視覺的誤區:物體的 2D外觀可能會因為視角的不同而有很大的變化

簡介 | 5

事實上,以上提出的問題並非只是難以解決而已,它根本不可能解決。你無法將 3D世界的二維(2D)畫面重構為 3D訊號。正式的說法是,這種誤區問題並沒有單一或絕對的解法。同一張的 2D影像可能代表無限數量的 3D場景組合之一,就算資料本身是完美的。但是,如前所述,資料會因為雜訊與畸變而受損。這種損壞來自世間的各種因素

(天氣、照明、反射、移動)、鏡頭與機械設備的缺陷、感應器有限的計算時間(因為

移動造成的模糊)、感應器或其他電子元件的電子雜訊,以及照相後的壓縮失真。看到

這些令人害怕的挑戰,我們該如何追求進步?

在設計實際的系統時,我們通常會使用額外的環境知識來處理視覺感應器的限制。假設

有一個行動機器人的任務是尋找與撿起室內的釘書機。機器人可能會利用“在辦公室裡

面可以找到桌子這種物體,而釘書機通常可在桌子上找到”這個事實。這暗示一個可參

考的大小:釘書機一定可以放在桌上。這也有助於避免在不可能的地方錯誤地“辨識”

釘書機(例如在天花板上,或窗戶上)。因為飛船的背景不是桌面必有的木紋,機器人

可以放心地忽略 200英呎遠,長得像釘書機的廣告飛船。相較之下,在影像檢索這種工作中,資料庫所有的釘書機影像可能都是真正的釘書機,所以龐大的尺寸與不尋常的情

況可能都被照相者默默地排除了,也就是說,照相者可能只會拍攝實際、正常尺寸的釘

書機。人類在照相時,通常會將物件擺在中間,也經常會調整方向,以清楚地展示它的

特徵。因此,人類拍攝的相片通常已經在無意間隱含許多資訊了。

你也可以用機器學習技術來明確地建立環境資訊模型,接著使用大小、重力方向等隱含

變數的值,在標籤化的訓練集合中建立關聯。或者,你也可以使用其他的感應器來嘗試

測量隱藏的偏移變數。使用雷射測距儀來測量深度,可讓我們準確地測量物體的大小。

電腦視覺所面臨的下一個問題是雜訊。我們通常會使用統計方法來處理雜訊。例如,你

不可能只藉由比較相鄰的兩個點來偵測影像的邊緣。但如果我們查看一個局部區域的統

計數據,就可以輕鬆地偵測邊緣。一個真正的邊緣應該長得像一條線,線上每一個鄰點

的方向都是一致的。你也可以根據長時間累積的統計資料來降低雜訊的影響。此外還有

一些其他的技術是直接用資料來學習,以建立明確的模型來解決雜訊問題。例如,因為

透鏡畸變(Lens distortion)是眾所周知的問題,你只要掌握描述這種畸變的多項式模型的參數,就可以近乎完美地修正它。

電腦視覺是在特定的用途或工作的情況下,根據相機資料嘗試採取行動或決策的。我們

消除影像的雜訊與毀損的目的,可能是希望有人試圖爬越圍牆時,讓安全系統發出警

報,或是讓監視系統計算有多少人路過樂園的某個區域。在辦公室中漫遊的機器人與固

定的保全攝影機使用的視覺軟體可能會採取不同的策略,因為這兩種系統的環境與目標

6 | 第一章

有明顯的差異。一般來說,電腦視覺的環境有愈多限制,我們就愈能利用這些限制來簡

化問題,讓最終的答案更可靠。

OpenCV的目標是提供一個可以解決電腦視覺問題的工具。在某些情況下,程式庫內的高級功能已經足以解決較複雜的電腦視覺問題了。即便無法解決,程式庫的基本組件也

足以讓你自行建立完整的解決方案,來處理幾乎所有的電腦視覺問題。就第二種情況而

言,你可以參考坊間一些人使用程式庫的方式,他們都盡量使用程式庫內的組件來解決

問題。一般來說,在你初步開發解決草案之後,可以查看這個方案的弱點,接著使用你

的程式與智慧來修正這些弱點(通常稱為“解決實際的問題,而不是想像的問題”)。接

著你可以用解決草案來作為基準,評估改善的程式。之後,你可以利用較大型的系統環

境來處理其餘的弱點。

OpenCV的起源OpenCV 是 Intel 的一項研究計劃,旨在促進大量使用 CPU 的應用程式的發展。為此,Intel啟動許多專案,包括即時光線追蹤與 3D顯示牆。本書的作者 Gary Bradski [Bradski]當時在 Intel服務,他曾經訪問一些大學,發現有些頂尖的大學團隊(例如麻省理工學院的媒體實驗室)都開發了很好的內部電腦視覺基礎架構,開放給內部人員使

用。這些基礎架構是學生們代代相傳的程式,可讓新生有個良好的起點來開發他們自己

的視覺應用程式,讓新生可以藉由之前的基礎來架構程式,而非從頭開發基本功能。

因此,OpenCV的構想,就是建立一個可讓全世界使用的電腦視覺基礎架構。在 Intel的Performance Library Team2的協助之下,OpenCV一開始是個已完成的程式核心與演算法規格,之後被送到 Intel的俄羅斯程式庫團隊。這就是 OpenCV的“起源”:來自 Intel研究實驗室的 Software Performance Libraries團隊的協助,並由俄羅斯的專家來負責實作與最佳化。

俄羅斯團隊的主管是 Vadim Pisarevsky,他為 OpenCV的管理、編程與最佳化付出許多心力,目前仍然是協助 OpenCV的核心人物。與他合作的 Victor Eruhimov協助開發早期的基礎架構,而 Valery Kuriakin負責管理俄羅斯實驗室,並大力地支援這項工作。OpenCV剛開始有幾個目標:

2 Shinn Lee 是主要的協助者。

簡介 | 7

• 提供開放且最佳化的視覺基礎架構程式碼來促進視覺研究,讓大家再也不用重新發明輪子。

• 傳播視覺知識,提供通用的基礎架構來讓開發者可進行開發,讓人更容易閱讀與流傳程式碼。

• 製作可攜、效能最佳化、免費使用的程式碼來促進視覺商業應用程式的發展,這個程式碼不強制要求商業程式必須開放原始碼,或是讓人免費使用。

這些目標,就是製作 OpenCV的“原因”。讓應用程式具備電腦視覺,可提升對於快速的處理器的需求。對 Intel而言,驅使人們升級更快速的處理器,會比銷售更多軟體創造更多收入。或許這就是這個開放且免費的程式來自硬體供應商而非軟體公司的原因。

有時,硬體公司的軟體比較有創新的空間。

對所有開放原始碼的專案而言,具備相當程度的群聚效應來讓專案可以自行維護是非常

重要的要素。現在 OpenCV大約有 1100萬次的下載次數,而且這個數字平均每個月成長 160,000次。OpenCV收到許多使用者的貢獻,而且大多數主要的開發都不是 Intel完成的 3。圖 1-3是 OpenCV的發展時間表。一路走來,OpenCV經歷網路公司的繁榮與蕭條,以及多次管理與方向的改變。在這些波動的期間,有時完全沒有 Intel的員工維護OpenCV。但是,隨著多核心處理器以及許多新的電腦視覺應用程式的問世,OpenCV的價值也愈來愈高。同樣的,機器人領域的快速成長也大力驅動這個程式庫的使用與開

發。在 OpenCV變成開放原始碼程式庫之後,Willow Garage花了好幾年的時間積極開發它,目前由 OpenCV基金會支援它(http://opencv.org)。目前這個基金會與一些公共

及私人機構還在積極地開發 OpenCV。要更深入瞭解 OpenCV的未來計畫,可參考第 23章。

3 在寫這本書時,機器人研究與培育單位 Willow Garage(http://www.willowgarage.com)正積極地支援一般的 OpenCV 維護,以及機器人應用領域的新開發。

8 | 第一章

v 3.0.0釋出(LTS)

v 2.4.0釋出

v 2.3.0釋出v 2.2.0釋出

v 2.1.0釋出v 2.0.0釋出(C++)

官方釋出 1.0版

Beta 5釋出

Beta 4釋出

Beta 3釋出

Beta 2釋出

Beta 1釋出,支援 Linux於 CVPR ’00釋出 Alpha

專案開始

圖 1-3 OpenCV發展時間表

OpenCV區塊圖OpenCV是以軟體層組成的。最上面的是運行 OpenCV的作業系統。接下來是語言綁定與示範應用程式。它的下面是在 opencv_contrib之中由別人貢獻的程式,多數都是高

階的功能。接下來是 OpenCV的核心,而最底下是硬體加速層(hardware acceleration

layer,HAL)的各種硬體最佳化程式。圖 1-4展示這個架構。

圖 1-4 OpenCV的區塊圖,包含所支援的作業系統

簡介 | 9

使用 IPP來加速 OpenCV如果你的 Intel處理器支援的話,OpenCV會利用 Intel免權利金的 Integrated Performance

Primitives(IPP)程式庫,IPP 8.x(IPPICV)的子集合。IPPICV 可在編譯期連結OpenCV內部,如此一來,它會將程式碼轉換成低階的最佳化 C程式(在 cmake,預設為 WITH_IPP=ON/OFF, ON)。使用 IPP可大幅改善速度。圖 1-5是使用 IPP時提升的速度。

OpenCV 3.0採用最佳化的 Intel® IPP 8.1.1/IPP-ICV時的速度提升狀況 Intel® Haswell處理器

使用

IPP-

ICV提升的速度

(愈大愈好)

圖 1-5 當 OpenCV在 Intel Haswell處理器上使用 IPPICV時提升的速度

OpenCV的擁有者是誰?雖然 OpenCV是 Gary Bradski在 Intel開發的,但這個程式庫的目的是促進商業與研究上的使用,也永遠如此,因為這是它的使命。因此它是開放且免費的,而且程式碼本身

可用於或嵌入(全部或部分)其他的應用程式,無論是商業或研究用途。它不強制你公

開或免費釋出應用程式碼。它不要求你將改善過的程式回饋給程式庫,雖然我們希望你

這麼做。

10 | 第一章

下載與安裝 OpenCV你可以從 OpenCV主網站(http://opencv.org)下載最新的完整原始碼,以及許多最近的

版本。你可以在下載網頁找到下載連結(http://opencv.org/downloads.html),但是,最新

的版本一定會被放在 GitHub(https://github.com/opencv/opencv),那裡也有正在開發的分

支版本。要取得最新的高階功能,你也可以下載與組建 opencv_contrib [opencv_contrib](https://github.com/opencv/opencv_contrib)。

安裝

近來 OpenCV使用 Git來作為開發版本控制系統,與使用 CMake來組建 4。多數情況

下,你不需要擔心組建上的問題,因為許多環境都有編譯過的程式庫。但是,當你成為

較進階的使用者之後,難免想要以自訂的選項來為你的應用程式重新編譯程式庫。

Windows

在 http://opencv.org/downloads.html,你會看到 Windows的最新版 OpenCV的下載連結。這個連結可下載與執行檔案,它是自動解壓縮的封存檔,裡面有為各種版本的 Visual Studio預先組建 OpenCV二進位檔。現在你幾乎已經可以開始使用 OpenCV了 5。

此外還有一個細節在於,你需要添加一個 OPENCV_DIR環境變數,來告知編譯器要在哪裡找到 OpenCV二進位檔。你可以在命令提示字元底下輸入以下的命令來設定它 6:

setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc10

如果你想要靜態連結 OpenCV,只要做這件事就可以了。如果你想要使用 OpenCV 動態

連結程式庫(DLLs),也必須告訴系統該到哪裡尋找二進位程式庫。你只要在程式庫路徑加上 %OPENCV_DIR%\bin即可(例如,在 Windows 10中,在電腦圖示按下滑鼠右鍵,選擇“內容”,再按下“進階系統設定”。最後,選擇“環境變數”,再將 OpenCV二進位路徑加到 Path變數)。

4 早期 OpenCV 開發者使用 Subversion 來控制版本,使用 automake 來組建。不過那段時光已經一去不復返了。

5 你需要知道的重點在於,雖然 Windows 版本含有釋出版本的二進位程式庫,但不包含這些程式庫的除錯組建版本。因此,在使用 OpenCV 來開發之前,你很可能需要打開解決方案檔案,自行組建這些程式庫。

6 當然,確切的路徑會根據你的安裝而有所不同,例如,如果你在 32 位元的機器上安裝,則路徑名稱會有 x86而非 x64。

簡介 | 11

OpenCV 3內建 IPP連結,所以你或多或少可以受益於現代的 x86與 x64 CPU帶來的效能好處。

你也可以用原始檔 tarball來組建 OpenCV:

1. 執行 CMake GUI。

2. 指定各個 OpenCV來源樹狀目錄的路徑,並組建目錄(它們必須不同!)

3. 按兩次 Configure(選擇合適的 Visual Studio產生器,或如果你使用 MinGW的話,MinGW makefiles),接著按下 Generate。

4. 在 Visual Studio內打開生成的解決方案,並組建它。如果你使用 MinGW,則使用以下的 Linux指令。

Linux

因為在各種版本裡面(SuSE、Debian、Ubuntu 等等)有各種不同的 GCC 與 GLIB 版本,所以 Linux版的 OpenCV不包含 Linux的預先組建二進位檔。但是,在許多情況下,你的版本都有 OpenCV。如果你的版本不提供 OpenCV,就需要與Windows版本一樣使用原始檔來組建。你可以從 http://opencv.org/downloads.html開始,但此時這個連結

會將你送到 SourceForge,你可以在那裡選擇目前的 OpenCV原始碼封包 tarball。

要組建程式庫與示範程式,你需要 GTK+ 2.x 或以上,包括 header。你也需要 gcc與

基本的開發套件 cmake和 libtbb(Intel執行緒建構元件),並選擇使用含有開發檔案的 zlib、libpng、libjpeg、libtiff與 libjasper(即,在套件名稱的結尾有 -dev的版本)。

你需要預先安裝 headers的 Python 2.6以上的版本(開發者套件),以及 NumPy來讓Python綁定可以動作。你也需要 libavcodec與其他來自 ffmpeg的 libav*程式庫(包括

headers)。

就後者而言,你可以安裝你的版本提供的 libav/ffmpeg 套件,或從 http://www.ffmpeg.

org下載 ffmpeg 。ffmpeg 程式庫有寬鬆公共授權條款(Lesser General Public License,

LGPL),但它有一些組件有較嚴格的通用公共授權條款(GPL)。要拿它來與非 GPL軟體(例如 OpenCV)一起使用,你要組建並使用一個共用的 ffmpg 程式庫:

$> ./configure --enable-shared$> make$> sudo make install

12 | 第一章

(當你動態連結 LGPL程式庫時,你不一定要為程式碼使用 GPL授權)。最後你會得到

/usr/local/lib/libavcodec.so.*、/usr/local/lib/libavformat.so.*、/usr/local/lib/libavutil.so.*,與

在各種 /usr/local/include/libav*路徑下的 include檔案。

要實際組建程式庫,你需要解壓縮 .tar.gz檔案,並前往建立出來的來源目錄進行以下的

動作:

mkdir releasecd releasecmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..makesudo make install # optional

第一個與第二個命令會建立一個新的子目錄,並將你移動到那裡。第二個命令會告訴

CMake該如何設置你的組建。範例內的選項或許可以讓你踏出第一步,但其他的選項可以讓你啟用各種功能、決定要組建哪些範例、加入 Python的支援、加入 CUDA GPU的支援,及其他。預設情況下,OpenCV的 cmake組態設定腳本會盡可能地尋找並使用

第三方程式庫。例如,如果它找到 CUDA SDK,它會啟用以 GPU來加速的 OpenCV功能。最後的兩個命令會實際組建程式庫,並將結果安裝到適當的地方。注意你不需要為

了在 CMake專案中使用 OpenCV而安裝它,你只需要指定路徑來產生 OpenCVConfig.

cmake 即可。在上述的情況下,檔案會被放在 release 目錄內。如果你改成執行 sudo make install,OpenCVConfig.cmake會被放在 /usr/local/share/OpenCV裡面。

如同在 Windows 的情況,Linux 版本的 OpenCV 會在安裝之後自動套用 IPP。從OpenCV 3.0 開始,OpenCV 的 cmake 組態腳本會自動下載與連結一個免費的 IPP(IPPICV)子集合。如果你不想要使用它,想明確地停用 IPP,可傳遞 -D WITH_IPP=OFF選項給 CMake。

Mac OS X

在 OS X安裝與 Linux很像,只不過 OS X內建了自己的開發環境 Xcode,它包含除了CMake之外,幾乎所有你需要的東西,你不需要 GTK+、TBB、libjpeg、ffmpeg等等:

• 預設情況下,Cocoa會被用來取代 GTK+。

• 預設情況下,QTKit會被用來取代 ffmpeg。

• Grand Dispatch Central(GDC)會被用來取代 TBB與 OpenMP。

接下來的安裝步驟是完全相同的。你可能想要傳遞 -G Xcode選項給 CMake來為 OpenCV(以及你的應用程式)生成 Xcode專案,以便在 Xcode裡面組建與除錯程式碼。

簡介 | 13

透過 Git來取得最新的 OpenCVOpenCV目前仍然處於積極開發的狀態,如果 bug回報資訊準確地描述 bug,並且附有可展示 bug的程式,那些 bug通常會被快速地修正。但是,正式的 OpenCV版本每年只會出現一或兩次。如果你要認真開發專案或產品,應該希望在程式的修正與更新出現時

馬上取得它們。為了取得它們,你得前往 OpenCV在 GitHub上的 Git存放區。

這本書不是教導 Git用法的地方。如果你曾經用過其他開放原始碼的專案,應該就已經很熟悉它了。如果沒有,可參考 Jon Loeliger寫的 Version Control with Git(O'Reilly)。你可以在 Linux、OS X與大多數的 UNIX系統使用 Git命令列用戶端。對於 Windows使 用 者, 我 們 推 薦 TortoiseGit(http://code.google.com/p/tortoisegit/); 對 於 OS X,SourceTree app應該很適合你。

在 Windows,如果你想要從 Git存放區取得最新版的 OpenCV,就要前往 https://github.

com/opencv/opencv.git的目錄。

在 Linux,你可以直接使用以下的命令:

git clone https://github.com/opencv/opencv.git

取得更多的 OpenCV文件OpenCV的主要文件是 http://opencv.org上的 HTML文件。除此之外,http://docs.opencv.

org/2.4.13/doc/tutorials/tutorials.html有許多主題的深度教學,另外還有一個 OpenCV wiki(目前位於 https://github.com/opencv/opencv/wiki)。

文件

OpenCV 2.x內含一個完整的參考手冊與一堆教學,全部都是 PDF格式,你可以查看opencv/doc。從 OpenCV 3.x開始就沒有離線的文件了。

線上文件與Wiki如上所述,http://opencv.org有廣泛的文件與一個 wiki可供使用。那裡的文件分成幾個主要的部分:

Reference(http://docs.opencv.org/)

這個部分含有函式、它們的引數,與一些關於如何使用它們的資訊。

14 | 第一章

Tutorials(http://docs.opencv.org/trunk/d9/df8/tutorial_root.html)

這裡有大量的教學課程,告訴你如何完成各種作品。這些教程包括基本的主題,例

如如何在各種平台上安裝 OpenCV或建立 OpenCV專案,及一些較進階的主題,例如在偵測物體時移除背景。

Quick Start(http://opencv.org/quickstart.html)

這是一個精心策劃的教學,只有可協助你在特定的平台上起步並執行的內容。

Cheat Sheet(http://docs.opencv.org/3.0-last-rst/opencv_cheatsheet.pdf)

這其實是個 .pdf檔案,裡面只有幾乎整個程式庫的濃縮版參考。當你將這精美的兩

頁紙張貼到隔間牆時,記得感謝 Vadim Pisarevsky提供這份優秀的參考資料。

Wiki(https://github.com/opencv/opencv/wiki)

這個 wiki含有幾乎你想要的所有東西,以及其他的東西。你可以在這裡找到地圖以及新聞、開放的議題、bug追蹤,及數不清的深入主題,例如如何成為 OpenCV的貢獻者。

Q&A(http://answers.opencv.org/questions)

這是個存有曾被問過的上千個問題的文件庫。你可以到那裡詢問 OpenCV社群問題,或回答別人的問題來協助他們。

你可以從 OpenCV.org首頁底下的 Documentation按鈕前往這些網頁。它們都是很棒的資源,其中有一個資源值得更深入地說明—Reference。Reference分成幾個小節,每一個都屬於程式庫內的一個模組。確切的模組清單會隨著時間而不同,但模組是程式庫的

主要結構。程式庫內的每一個函式都屬於一個模組。以下是目前的模組:

core

“core”是程式庫中含有所有基本物件型態及其基本操作的部分。

imgproc

這個影像處理模組含有基本的影像變換,包括過濾器與類似的摺積運算程式。

highgui(在 OpenCV 3.0被分為 imgcodecs、videoio與 highgui)

這個模組含有使用者介面函式,可用來顯示影像或接收簡單的使用者輸入。你可以

將它當成非常輕量的視窗 UI工具組。

簡介 | 15

video

這個影片程式庫包含讀取與寫入影片串流時需要用到的函式。

calib3d

這個模組含有校準相機與立體或多相機陣列時需要的演算法。

features2d

這個模組含有偵測、描述與匹配關鍵點特徵的演算法。

objdetect

這個模組含有偵測特定物體的演算法,例如人臉或行人。你也可以訓練偵測器來偵

測其他的物體。

ml

這個機器學習程式庫本身其實是個完整的程式庫,它裡面含有廣泛的機器學習演算

法,使用 OpenCV的自然資料結構。

flann

FLANN的意思是“Fast Library for Approximate Nearest Neighbors”。你應該不會直接使用這個程式庫裡面的方法,它們會被其他模組的函式用來在大型的資料集合中

做最近鄰點搜尋(nearest neighbor search)。

gpu(在 OpenCV 3.0分為多個 cuda*模組)

這個 GPU程式庫含有多數為 CUDA GPU的演算而最佳化的函式。也有一些只是為了讓 GPU演算而實作的函式。其中有些函式可提供很棒的結果,但需要較高的計算資源,所以在無 GPU的硬體較不實用。

photo

這是個比較新的模組,裡面含有適合用於計算攝影(computational photography)的工具。

stitching

這個模組實作一個精密的影像拼接管道。這是程式庫的新功能,但它與 photo模組一樣,是個有成長性的領域。

16 | 第一章

nonfree(在 OpenCV 3.0被移往 opencv_contrib/xfeatures2d)

OpenCV有一些演算法作品是有專利的,或有使用限制的(例如 SIFT演算法)。這些演算法都被分到它們自己的模組,來讓你知道你需要做一些特別的事情才能在商

業產品中使用它們。

contrib(在 OpenCV 3.0被併入一些 opencv_contrib模組)

這個模組裡面是尚未被併入整個程式庫的新事物。

legacy(在 OpenCV 3.0沒有了)

這個模組含有尚未被一併移出程式庫的舊東西。

ocl(在 OpenCV 3.0沒有了,換成 T-API技術)

這是一個較新的模組,你可以將它視為類似 GPU的模組,不過它實作了 Khronos OpenCL標準,來做開放平行編程(open parallel programming)。雖然目前 ocl 的功能比 GPU模組少,但它的目的是提供可在任何 GPU或其他採用 Khronos的平行設備上執行的程式(相較之下,gpu模組明確地使用 NVidia CUDA工具組,所以只能在 NVidia GPU設備上運作)。

雖然線上文件的品質在不斷地提升,但它的任務不包括讓使用者瞭解程式實作的演算

法,或這些演算法參數真正的意義。本書的目的是提供這些資訊,以及讓你更深入地瞭

解程式庫的所有基本建構元素。

OpenCV貢獻存放區在 OpenCV 3.0中,上述的程式庫已被分成兩個部分:成熟的 opencv,以及在 opencv_

contrib 中, 目 前 最 新 的 視 覺 技 術 功 能(https://github.com/opencv/opencv_contrib) [opencv_contrib]。前者由 OpenCV核心團隊負責維護,程式比較穩定(大部分)。而後者比較不成熟,大多是由社群進行維護與開發,或許有一些部分不屬於 OpenCV授權條款,也可能包含有專利的演算法。

以下是一些 opencv_contrib存放區的模組(附錄 B是我在寫這本書的期間的完整清單):

Dnn

深度類神經網路

簡介 | 17

face

人臉辨識

text

文字偵測與辨識,可選擇在後端使用開放原始碼的 OCR Tesseract

rgbd

處理 Kinect或其他深度感測器取得的 RGB +深度映射(或只是用立體對應演算法算出的圖片)

bioinspired

受生物啟發的視覺

ximgproc、xphoto

進階的影像處理與計算攝影演算法

tracking

現代的物體追蹤演算法

下載與組建貢獻模組

在 Linux與 OS X上,你可以直接使用以下的命令來下載 opencv_contrib:

git clone https://github.com/opencv/opencv_contrib.git

在 Windows,你可以將這個位址匯至 TortoiseGit或其他用戶端,再使用 CMake來重新設置 OpenCV:

cmake –D CMAKE_BUILD_TYPE=Release \ –D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules ..

並與之前一樣重新組建它。組建好的貢獻模組會被放到與一般的 OpenCV二進位檔相同的目錄,你不需要做其他事情就可以使用它們。

18 | 第一章

可攜性

OpenCV的設計也有考慮可攜性。它原本的寫法可讓任何相容的 C++編譯器編譯,這代表 C與 C++程式碼必須相當符合標準,來讓跨平台的支援更容易達成。表 1-1列出已知可讓 OpenCV運行的平台。它對於 Intel與 AMD 32-bit以及 64-bit(x86、x64)結構的支援是最成熟的,對 ARM的支援也在迅速提升中。在作業系統中,OpenCV完全支援Windows、Linux、OS X、Android與 iOS。

表 1-1未列出的架構或 OS,不代表沒有 OpenCV的移植。OpenCV已被移植到幾乎每一種商業系統上,從 Amazon Cloud與 40核心的 Intel Xeon Phi到 Raspberry Pi與機器狗。

表 1-1 OpenCV 1.0版的可攜性資訊

x86/x64 ARM 其他:MIPs, PPC

Windows SIMD, IPP, Parallel, I/O SIMD, Parallel (3.0), I/O N/A

Linux SIMD, IPP, Parallel,a I/O SIMD, Parallel,a I/O Parallel,a I/O*

Android SIMD, IPP (3.0), Parallel,b I/O SIMD, Parallel,b I/O MIPS—基本支援

OS X/iOS SIMD, IPP (3.0), Parallel, I/O SIMD, Parallel, I/O N/A

Other: BSD, QNX, ... SIMD SIMDa Linux 的平行演算是透過第三方程式庫,或啟用 OpenMP 來做的。b Android 的平行演算是透過 Intel TBB 來完成的。

以下是表 1-1的說明:

SIMD

用來提升速度的向量指令:x86/x64的 SSE,ARM的 NEON。

IPP

可使用 Intel IPP。從 3.0開始,有個免費的專用 IPP子集合可用(IPPICV)。

Parallel

使用一些標準或第三方執行緒框架來將處理程序分散至多個核心。

I/O

一些可用來抓取或寫入影片的標準或第三方 API。

簡介 | 19

總結

在這一章,我們說明 OpenCV [OpenCV]的歷史,從 1999年 Gary Bradski [Bradski]在Intel開創它,到目前由 Arraiy [Arraiy]支援的情況。我們也說明 OpenCV的動機,與一些它的內容。我們討論核心程式庫—OpenCV如何與 opencv_contrib(見附錄 B)的新功能切割,以及許多與 OpenCV有關的線上內容的連結。這一章也討論如何下載與安裝OpenCV,以及它的效能與可攜性。

練習題1. 下載並安裝最新版的 OpenCV。用 debug與 release模式來編譯它。

2. 使用 Git來下載並組建最新的 OpenCV主幹版本。

3. 指出至少三種將 3D輸入轉換成 2D畫面時,可能產生的不明確情形。你該如何處理這些不明確?