1.1. OpenCV簡介
OpenCV 的全稱是 Open Source Computer Vision Library(開源計算機視覺庫),它是一個功能強大的跨平臺開源計算機視覺庫,可應用於人機互動、物體識別、圖像分割、人臉識別、運動跟蹤、機器人、運動分析、機器視覺、結構分析、汽車安全駕駛等諸多領域。
OpenCV以優化的 C/C++ 編寫, 提供C++,C,Python和Java接口,支持Windows,Linux,Mac OS, iOS和Android。
針對Julia語言,OpenCV官方提供了“Julia OpenCV Binding”,即OpenCV綁定,不過其官方也申明,該Bindings只在Ubuntu和Mac上進行了測試。Windows可能可以工作,但目前尚未正式測試和支持。而且據筆者測試,在Julia1.7及以上版本,安裝該綁定的OpenCV庫不成功,1.6.4可以安裝成功。(官方網址:https://docs.opencv.org/4.x/d8/da4/tutorial_julia.html)
另外一個途徑是使用第三方的OpenCV封裝(wraper),目前找到兩個https://github.com/JuliaOpenCV 和https://github.com/maxruby/OpenCV.jl。不過這兩個版本都不適用於當前版本的Julia,且已經停更多年。現在Julia使用OpenCV的最好方法是使用PyCall.jl爲OpenCV調用Python綁定。
1.2. 安裝OpenCV庫
在Python中安裝OpenCV庫,很簡單,只要運行下面的命令:
pip3 install opencv-python
通常情況下。安裝過程會非常順利。但是在Julia中安裝OpenCV會稍微複雜一點。通常通過Miniconda託管環境安裝。
首先打開Julia的REPL環境,按“]”鍵進入包管理器,輸入以下命令
(@v1.7) pkg> add PyCall
(@v1.7) pkg> add Conda
然後按“Ctrl+c”鍵,退出包管理器,輸入以下命令,安裝
using Conda
Conda.runconda(`install -c conda-forge opencv`)
注意括號中的包括字符串的字符不是單引號,是鍵盤左上角的“`“鍵。
安裝完後輸入以下命令:
using PyCall
const cv = pyimport("cv2")
如果出現以下反饋,說明安裝成功了。
PyObject <module 'cv2'from 'C:\\Users\\...\\.julia\\conda\\3\\lib\\site-packages\\cv2.cp39-win_amd64.pyd'>
1.3. OpenCV的Hello,world
從這裏開始學習OpenCV 編程。按照程序員的慣例,自然是從簡單的 hello, world程序開始編寫第一個OpenCV程序。
原書示例程序32-1是一個Python版的0penCV 的 hello, world 程序。該程序從本地磁盤的一個文件中讀取圖像,然後在圖像左上角輸出一個藍色的hello, world 文本,最後將該圖像顯示在一個窗口中。
現在我們用Julia版的PyCall來實現這段代碼:
① using PyCall
② cv2=pyimport("cv2")
#從文件中讀取圖像
③ img = cv2.imread("images/face1.jpg")
④ rimg = permutedims(img, ndims(img):-1:1)
⑤ pyimg = PyReverseDims(rimg)
#設置文件的位置、字體、顏色等參數
⑥ pos = (10, 50)
⑦ font = cv2.FONT_HERSHEY_SIMPLEX
⑧ color = (255, 0, 0)
#在圖像中顯示文本"hello, world"
⑨ cv2.putText(pyimg, "hello, world", pos, font, 2, color, 2)
#顯示圖像窗口
⑩ cv2.imshow("Image", pyimg)
#按任意鍵退出
⑪ cv2.waitKey(0)
#銷燬所有窗口
⑫ cv2.destroyAllWindows()
對比Python和Julia的代碼,可以看出雖然總體上差不多,本質上都是調用OpenCV庫的相關方法對圖片進行處理。但是從細節處我們可以發現還是有些不同的,Julia的代碼相比Python的代碼,對原始讀取圖片信息的img對象,進行了二次處理,這是爲什麼呢?下面我們逐一對上面的代碼進行解讀:
代碼①:引用PyCall才能與OpenCV交互
代碼②:利用PyCall提供的pyimport()方法導入OpenCV的cv2模塊。
代碼③:使用cv2.imread()方法從文件中讀取一個圖像,存放在變量img 中。文件路徑可以是相對路徑或者絕對路徑。如果給定的文件路徑是錯誤的,該方法並不會報錯,而是返回一個None值。
代碼④、⑤:變量img是以數組形式存儲圖像信息的,而Julia與Python的數組存儲方式不同,Julia是列主數組,Python是行主數組。假如有這樣一個數組:
按行優先存儲,內存中形式如下:
8 2 2 9 9 1 4 4 3 5 4 5
列優先,內存格式:
8 9 3 2 1 5 2 4 4 9 4 5
使用函數permutedims()和函數PyReverseDims()對列主數組img進行轉換,改變存儲格式,得到OpenCV可以接受的變量pyimg。
代碼⑥~⑨:先定義 pos、font 和 color 三個變量,分別用於設定文本的左上角座標、字體和顏色。然後使用cv2.putText()方法在pyimg圖像上輸出一個文本,該方法的參數依次爲像文本、左上角座標、字體、字體大小、顏色、字體粗細。
代碼⑩:使用cv2.imshow()方法將添加了 hello, world 文字的圖像pyimg 顯示在一個定的窗口中,窗口的名字爲 Image。
代碼⑪:調用cv2.waitKey(0)方法,讓窗口一直處於等待狀態,直到按下鍵盤的某個鍵時才結束。
代碼⑫:調用cv2.destroyAllWindows()方法,將銷燬所有打開的窗口。
打開VSCode,新建hello_world.jl文件,輸入以上代碼,在該文件上點擊右鍵,在出現的菜單中點擊下圖所示的菜單:
運行可能會出現下列錯誤:
cv::findDecoder imread_('images/face1.jpg'): can't open/read file: check file path/integrity
這是由於我們代碼中採用的是相對路徑,而Julia的運行環境與我們的代碼文件不在同一目錄導致的,這時候在hello_world.jl文件上再點擊右鍵,然後點擊如下圖的菜單:
再次象前次一樣運行,就可以了。下面是運行結果: