19年02月20日

OpenCV拼圖輔助程式(續)

這是一次成功用 Open-CV 拼圖的經驗的續篇,主要是想補充並紀錄一下之前沒提到的一些研究結果

OpenCV + Python

就如之前提到,我用的是 OpenCV 和 Python 這個組合,因為 OpenCV 3.0 支援的語言不多,所以我選了最容易上手的 Python,最近發現 OpenCV 4.0 開始支援 Node.js 了,可惡!

黑蘋果 hackintosh

系統方面,我的首選是 Linux,不考慮 Windows。但因為這次要用到大量 GPU,Linux 的支援比較弱,就決定用早就想試試的 hackintosh,還可以 build iOS 呢﹗

不過要安裝黑蘋果,首先要有蘋果電腦,詳情自己 Google 一下,不難找的

(´-ω-`)

建立 Python 虛構環境

裝好 Python 後先建立 python 的虛構環境,原理就像 NodeJS 的 node_modules,避免這項目的模組影響到其他項目。我的選擇是使用 virtualenv,沒甚麼原因只是第一個搜尋到就是這個,另一個替代方案是用 Conda

Copy Code

# 安裝 virtualenv
pip install virtualenv

# 在項目內建立虛構環境
cd ~/my-project
virtualenv jigsaw-env

# 啟用虛構環境
source jigsaw-env/bin/activate

# 最檢查pip路徑是否正確
pip -V

如果沒出錯會看到 pip 指向剛設定好的路徑

Copy Code

pip 19.0.3 from ../jigsaw-env/lib/python3.7/site-packages/pip (python 3.7)

使用這個指令離開虛擬環境

Copy Code

$ deactivate

安裝 OpenCV

3.0 跟 4.0 的安裝方法沒太大差別,兩者都需要連同 OpenCV extra modules 安裝,比較麻煩的是當中要用到的 SIFT 不是免費技術,所以在 compile 的時候需要同意一些條款,簡單來說就是不能用 pre-built 版本,只能自己 build 了…

以下是 OpenCV 4 的安裝流程,當中 Python 的設定請自行更改路徑,參考這篇 OpenCV: Installation in Linux

Copy Code

# 先 clone 這兩個項目
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git

# 建立 Build 資料夾
cd opencv
mkdir build
cd build

# build 需要自行更改 python 路徑
cmake -DOPENCV_ENABLE_NONFREE:BOOL=ON \
-DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-DPYTHON3_EXECUTABLE=/usr/bin/python3 \
-DPYTHON_INCLUDE_DIR=/usr/include/python3.7m \
-DPYTHON_LIBRARY=/usr/lib64/libpython3.7m.so \
-DPYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3.7/site-packages/numpy/core/include/ \
..

如果 Python 的設定正確,應該會看到類似這樣的字串,如果你沒看見Python 3,一定是有東西忘記輸入或輸入錯了

Copy Code

--   Python 3:
--     Interpreter:                 /usr/bin/python3 (ver 3.7.2)
--     Libraries:                   /lib64/libpython3.7m.so (ver 3.7.2)
--     numpy:                       /usr/lib/python3.7/site-packages/numpy/core/include/ (ver )
--     install path:                lib/python3.7/site-packages/cv2/python-3.7
--
--   Python (for build):            /usr/bin/python2

最後用 make compile 和安裝

Copy Code

make -j7

sudo make install

如果出現了這句

Copy Code

ModuleNotFoundError: No module named 'cv2'

就需要在~/.bashrc~/.zshrc的最後一行加上這句,讓 Python 能讀取site-packages這個資料夾

Copy Code

export PYTHONPATH=/usr/local/lib/python3.7/site-packages:$PYTHONPATH

整個過程我的 Xeon 處理器大概用了 10 分鐘,如果是 i5 或以下的有機會超過半小時,喝杯咖啡再回來吧

(´・ω・)つ旦

技術應用

這個項目我總共寫了

  • 一個 Python 伺服器
  • 一個用 React Native 寫的 iOS App

伺服器主要是 App 跟 OpenCV 的溝通,渠道是 socket.io,iOS App 的作用是拍照然後透過 socket.io 把圖片傳送到伺服器,沒甚麼特別我就不多講了,而且已經是 iOS 10 時候的事了,所以現在有 87% 機率是不能運行的了

OpenCV 圖像比對技術

除此之外就是圖像比對的技術,也就是這個項目的核心,俗語有講「貨比三家不吃虧」所以我幾乎把 OpenCV 內建的比對功能都試了一遍

Feature Matching 比較圖片特徵

Feature Matching (以下簡稱 FM) 是 OpenCV 的功能,Feature 即特徵,FM 即是找出兩件物件的相似特徵

如果是原圖與原圖的比較,我們可以用 Template Matching (TM),但要從拍照取得的 3D 拼圖塊跟 2D 的原圖比較,TM 就沒辦法處理了,因為拍下來的圖片一定是變形的

OpenCV 有幾種 Feature Matching 算法可以使用,以下就是我測試過的

SIFT Brute-Force Matching

Scale-invariant feature transform 是一個很常用的算法,初步測試讓我很驚訝,因為真的慢到一個點,單使用這個算法是不可能的了,混合其它算法出來的結果還可以

運算時間︰9 秒

p.s. 這速度光是運算 1000 張圖片就要花 2.5 小時了…

ORB Brute-Force Matching

Oriented FAST and Rotated BRIEF 是一個 SIFT 的替代方案,這個運算方法的優點是快和省電腦資源,重點是免費,可惜效果不是很理想,最後沒採用

運算時間︰1 秒

p.s. 真的很快

FLANN based Matcher

為了解決速度問題,我們會使用 FLANN (Fast Library for Approximate Nearest Neighbors)配搭 SIFT 使用,看到名字有個 Fast 字就知道是根速度問題有關了

運算時間︰5 秒

Homography

calib3d 的 Homography 是這次的主角,它可以修正圖片因拍攝而變形的問題,讓它比較接近原圖,當然拍攝的圖片也不能變形得太誇張

運算時間︰5 秒

Σ(゚ω゚)

運算速度太慢

這個項目遇到不少問題,雖然大部份都可以無視,反正我的目的就只是完成這副拼圖,但是速度的問題是一定要解決的,我把解決方法歸納於這兩點

選擇 macOS

第一個關鍵因素是系統,嘗試過三個主流系統後,發現 Linux 的圖像處理明顯比其他兩個慢,我不想花時間在效能提升方面上,所就直接轉用 hackintosh 了

p.s. 我的顯示卡是 GTX 960,因為慢得很誇張所以比較各系統時有很明顯的感覺

壓縮圖片大小到合理範圍

另一個因素是圖片大小,這裡指的圖片指的是拼圖原圖和手機拍的圖片,把原圖切割成多個部份可以運用多線程提升速度,我在這個項目就把它切成 9 等份

手機拍攝的圖片像素就縮減至 1000px,但不能太小因為會不準確,這個過程我在 Python 處理,不知道用 iOS 壓縮後再傳送會不會比較快,對於我的 6S 來說大概是不會吧,而且用 subnet 傳送一張圖片應該是以微秒作單位的

花了很多時間 build iOS

沒有太多 App 開發經驗,所以跟 OpenCV 比起來反而花了更多時間在 build iOS 那邊,除了要解決一堆權限問題之外,本來以為使用 Reactive Native 就不需要用 Xcode,最後發現是自己一廂情願…

準確率不太好

準確率嗯… 大概 50%吧,重新拍一次也只能提高至大約 70%,所以說有 30%還是要靠自己了,問題是我覺得這拼圖每一塊的獨特性已經很高了,這樣才只有 70%,很難想像能應用在其他比拼圖上…

p.s. 而且這程式其實也沒幫到多少,因為就算程式認到了我還要在拼圖板上猜那塊拼圖的位置 Orz,下次還是先列印 1:1 的原圖作為拼圖的底板好了

感想

後悔莫及

( ´•̥̥̥ω•̥̥̥` )

相關文章

一次成功用 Open CV 拼圖的經驗