OpenCV 為啥勾搭上 OpenGL?
如果讀者留意 OpenCV 2.3 之后的版本,那么會發現 cv::ogl namespace,ogl 自然是 OpenGL了。一個三維計算機圖形庫為何出現在計算機視覺中,傳統的 CV 開發者是否需要學習它,這些問題待我一一來回答。
問題一:為何引入 OpenGL?
在 2.3 之前 OpenCV 的渲染部分都是由 CPU 來實現的,不論是畫線還是把圖片顯示到屏幕上。這有兩個問題,速度慢,同時沒法畫三維物體。引入 OpenGL 是為了借助 顯卡的力量,顯卡比 CPU 更擅長渲染,同時顯卡和 CPU 可以同時干活。比方說,CPU 在獲取攝像頭畫面然后檢測人臉時,顯卡在渲染三維的人臉網格模型和高精度抗鋸齒的二維界面。
另外,隨着民用深度傳感器的普及,cv::VideoCapture 第一時間增加了對 Kinect、華碩 Xtion、Intel Perceptual Computing SDK 等的支持。傳統的視覺計算中,深度圖只能當做單通道的灰度圖進行處理。想實現隔空的多點觸摸是綽綽有余,但是如果想實現三維重建(比如 Kinect Fushion)那么我們必須將算法升級到三維空間。相應的,三維空間的算法也需要三維的 API 進行渲染,也就是 OpenGL。
想開啟該功能,需要在配置 CMake 時選上 WITH_OPENGL=ON,然后重新編譯完整的 OpenCV 庫。我簡要介紹下幾個組件:
- ogl::Buffer 是 OpenGL 中的緩存區,可以用於保存多邊形的頂點和顏色等。
- ogl::Texture2D 是保存在顯卡中的二維貼圖,可以認為是得到 GPU 加速的 cv::Mat。
前面這兩個類都只是保存數據,要把數據畫出來,還要用到 ogl::render 函數。
void ogl::render(const Texture2D& tex, Rect_<double> wndRect=Rect_<double>(0.0, 0.0, 1.0, 1.0), Rect_<double> texRect=Rect_<double>(0.0, 0.0, 1.0, 1.0))
問題二:是否應該學習 OpenGL?
It depends.
如果你開發的是命令行程序並不顯示任何圖像,或者顯示的圖片很簡單,那么不需要轉換到 cv::ogl 下。
如果你的應用耗費了大量時間在圖片的顯示上,或是希望擁有高質量的界面系統,那么你可以借助 cv::ogl::Texture2D 加速圖像的渲染。
如果你開發的是增強現實應用,你肯定已經擁有了自己的三維渲染模塊,可以考慮與 cv::ogl::Buffer 整合。
如果你已經在使用 CUDA 模塊,對於渲染的時候數據需要回傳到 CPU 表示多此一舉,那么你可以使用 CUDA 與 OpenGL 的協同功能去除多余的數據傳輸。
另一方面,如果你不是 OpenCV 的用戶但是你正在開發虛擬現實應用,你可以考慮將視覺計算引入到你的系統中,實現類似 HoloLens 的設備。
未來展望:OpenCV 與顯卡的關系
由於顯卡能力的增強以及硬件公司的支持,OpenCV 逐漸展露出新的形態,大量的視覺計算位於顯卡上。
- 運算通過 CUDA 模塊或 OpenCL 模塊,這兩個模塊分別得到 NVIDIA 與 AMD 的大力支持。
- 渲染通過 OpenGL 模塊。
這意味着除了文件讀寫(highgui 模塊)外,視覺應用可以逐漸脫離 CPU。
---------------------------------