隆振海 成都理工大學信息科學與技術學院
魚眼鏡頭指視角接近或等于180°的鏡頭。這類鏡頭一般焦距極短,在135底片格式下,16毫米或焦距更短的鏡頭通常即可認為是魚眼鏡頭,絕大部分的魚眼鏡頭均是定焦鏡頭,只有少部分是變焦鏡頭。依成像可分為圓形魚眼(Circular fisheye,又稱全周魚眼,畫面呈圓形)與對角線魚眼(Diagonal fisheye或Full-frame fisheye,畫面呈方形)其鏡面似魚眼向外凸出,所視的景物,像魚由水中看水面的效果。魚眼鏡頭一般用來拍攝廣闊的風景或于室內拍攝。不少攝影師喜歡使用魚眼鏡的夸張變形來營造透視感。歷史上,135畫幅最廣的魚眼鏡頭是藝康旗下的6毫米f/2.8,視角接近220°。而富士能研發了世界首臺用于五百萬像素CCD攝像機的185°廣角全方位鏡頭魚眼圖像的畸變矯正一直都是今年來的熱點問題,其中的代表性方法是球面透視投影矯正法該方法使用球形的投影面用于矯正魚眼圖像,以此為基礎的衍生或改進方法還有許多。
OpenCV中已經集成了一種基于球形投影面的魚眼鏡頭矯正算法函數,有需要的用戶只需要直接調用函數即可。但實際上,由于OpenCV的實現所依賴的公式的局限性,其函數不能處理視角大于180度的魚眼鏡頭所提供的圖像。
在OpenCV提供函數的基礎上,本文提出了一種改進算法,該算法可以對視角大于180°的魚眼鏡頭圖像進行高效處理且得到準確的矯正結果。
在OpenCV4.0預覽版的算法文檔中,可以看到OpenCV對其使用的魚眼鏡頭圖像矯正算法的細節描述。該算法首先將圖像平鋪在球心為原點的半球面上,矯正視點O位于原點;此時對于圖像上的每一個點P,都有一個三維坐標;定義點P的a,b值分別為a=x/z,b=y/z;其中x、y、z為點P的三維坐標值;定義r = a * a + b * b;定義θ = atan(r);使用公式θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)對θ進行矯正,其后可以得出P點矯正后的位置為x’,y’,其值為x′=(θd/r)a y′=(θd/r)b,如圖 2-1 所示。
由該定義可見,OpenCV的做法上是以半球面與z軸的交點為中心O‘,將球面上的點P按照與O’的球面距離展開在平面上,同時對距離進行矯正從而獲得矯正圖像的效果。如圖2-2所示,P為球面上一點,P‘為P點矯正后的位置,以點O’為圓心的圓即為半球面上圖像矯正后范圍,由于使用了反正切函數,該方法并不能正確處理另外半球的圖像。

圖2 -2 OpenCV算法原理示意圖
OpenCV算法使用了反正切函數以求得弧對應角度,從而求取弧長。但在具體實現上,OpenCV使用了反正切函數來求取弧PO‘的長度。反正切函數是一種反三角函數,是利用已知直角三角形的對邊和鄰邊這兩條直角邊的比值求出其夾角大小的函數,是一種基本特殊函數(Wiki)。在三角學中,反正切被定義為一個角度,也就是正切值的反函數,由于正切函數在實數上不具有一一對應的關系,所以不存在反函數,但可以限制其定義域。因此,反正切是單射和滿射也是可逆的,但不同于,反正弦和反余弦,由于限制正切函數的定義域在[-π/2,π/2],其值域是全體實數,因此可以得到反函數的定義域也是全體實數。
故而當弧PO’對應的圓心角大于90度,即此時需要對視角超過180度的圖像進行矯正時,反正切函數將不能得出準確的值。因而,這種方法也不能用于矯正視角超過180度的魚眼鏡頭圖像。為此,本文提出利用極坐標計算弧對應的圓心角,避免反正切函數的使用,從而將矯正范圍從[-π/2,π/2]擴大到[-π, π](如圖3-1所示)。

圖3 -1 改進算法流程圖
OpenCV中已經集成了一種基于球形投影面的魚眼鏡頭矯正算法函數,有需要的用戶只需要直接調用函數即可。但在具體實現上,OpenCV使用了反正切函數來求取弧PO‘的長度。由于限制正切函數的定義域在[-π/2,π/2],這種方法并不適用于矯正視角超過180度的魚眼鏡頭圖像。本文提出一種改進的魚眼鏡頭圖像矯正算法,利用像素點在球面上的極坐標直接計算出弧長,避免了正切函數的使用,從而將矯正范圍從[-π/2,π/2]擴大到[-π, π]。