熱線電話:0755-23712116
郵箱:contact@shuangyi-tech.com
地址:深圳市寶安區(qū)沙井街道后亭茅洲山工業(yè)園工業(yè)大廈全至科技創(chuàng)新園科創(chuàng)大廈2層2A
上面這副圖就是我們今天要處理的了,我們想把它從拍照視角變成鳥(niǎo)瞰圖,這是機(jī)器人導(dǎo)航中的常用手段,以便在該平面上進(jìn)行規(guī)劃和導(dǎo)航。
這種變換常常用到透視變換,但我們今天在講解透視變換時(shí),需要普及一下其他的變換,包括平移,旋轉(zhuǎn),錯(cuò)切,放縮,以及仿射變換。
綜述
所有復(fù)雜的東西,都是由基本的組成的。所以我們需要先了解一下基礎(chǔ)的變換有哪些:
平移
我們對(duì)矩形(圖像)平移,需要怎么做?
對(duì)每一個(gè)像素點(diǎn)坐標(biāo)平移。可以讓每一個(gè)像素點(diǎn)的x,y坐標(biāo)都加一個(gè)變量。
矩陣形式表示:
等式左邊[X,Y,1]是像素坐標(biāo)的齊次形式。等式右邊是平移之后的坐標(biāo)。
放縮
進(jìn)行放縮,就是將矩形(圖像)放縮n倍,也就是長(zhǎng)寬各乘一個(gè)變量。
旋轉(zhuǎn)
對(duì)矩形(圖片)進(jìn)行旋轉(zhuǎn),關(guān)于旋轉(zhuǎn)的數(shù)學(xué)推導(dǎo)在后面仿射會(huì)介紹:
錯(cuò)切
前面的都比較直觀,那錯(cuò)切是什么呢?
我們可以看下矩形關(guān)于y方向的錯(cuò)切:
看圖就很直觀了,那數(shù)學(xué)表達(dá)呢?
x軸上的錯(cuò)切就是同理了,公式如下:
然后兩者和起來(lái),就如下了:
好了,到此我們就了解了這四種變換了,那仿射變換是什么呢?可以看下圖公式:
等式右邊就是仿射變換矩陣,是由原圖像平移,旋轉(zhuǎn),放縮,錯(cuò)切之后得來(lái)的。
在書(shū)上往往將仿射變換和透視變換放一起講,這兩者各是什么呢?
在剛學(xué)仿射變換和透視變換時(shí),我是有些分不清的。印象最深刻的就是下圖:
可以看到,仿射變換(下)是將矩形變換成平行四邊形(即變換后各邊依舊平行),而透視變換(上)可以變換成任意不規(guī)則四邊形。
這樣看來(lái),好像仿射變換是透視變換的子集。
那到底是不是呢?其實(shí)是的。仿射變換屬于線性變換,而透視變換則不僅僅是線性變換。仿射變換可以看做是透視變換的一種特例。
直觀上感受,我們可以認(rèn)為:
仿射變換是單純對(duì)圖片進(jìn)行縮放,傾斜和旋轉(zhuǎn),因此圖片不論如何變化,線之間的平行性是不變的。如下圖。
可以感受到,右圖是可以通過(guò)左圖平移,旋轉(zhuǎn),錯(cuò)切,縮放之后得來(lái)。
而透視變換,則是當(dāng)觀察者的視角發(fā)生變化時(shí)物體發(fā)生的透視變換,此轉(zhuǎn)換允許造成透視形變。
我們看下圖的公路,近處寬遠(yuǎn)處窄,就是因?yàn)橐暯堑脑颍?/p>
而我們本文要做的,就是將視角改為鳥(niǎo)瞰,從而得到類似下圖的鳥(niǎo)瞰圖:
仿射變換原理
前文已經(jīng)說(shuō)了,仿射變換是單純對(duì)圖片進(jìn)行平移,縮放,傾斜和旋轉(zhuǎn),而這幾個(gè)操作都不會(huì)改變圖片線之間的平行關(guān)系。
opencv中給出了仿射變換的函數(shù)接口:
這個(gè)函數(shù)很好理解,輸入一個(gè)圖像,輸出這個(gè)圖像的仿射變換。
但第三個(gè)參數(shù)需要我們輸入2*3的仿射計(jì)算矩陣,這是什么鬼?
我們先看一下仿射計(jì)算矩陣長(zhǎng)什么樣子(可以去掉最后一行):
我們的輸出圖像G(x,y) = F(x,y)乘仿射矩陣。
我們可以看下圖推導(dǎo)出仿射計(jì)算矩陣。
一個(gè)點(diǎn)P在原始坐標(biāo)系下的坐標(biāo)是(Xsp,Ysp)。然后要完成旋轉(zhuǎn)操作,旋轉(zhuǎn)操作是基于原點(diǎn)的。如何得到旋轉(zhuǎn)之后的點(diǎn)的坐標(biāo),這里用到一個(gè)技巧:
坐標(biāo)系中某個(gè)點(diǎn)的旋轉(zhuǎn)可以等價(jià)地去旋轉(zhuǎn)坐標(biāo)軸。
所以有了上圖中以(Xs0,Ys0)為中心的虛線與屏幕水平垂直的坐標(biāo)系。在這個(gè)坐標(biāo)系中確定P的坐標(biāo),和在藍(lán)色坐標(biāo)系中確定旋轉(zhuǎn)之后P的坐標(biāo)是等價(jià)的。
基于這個(gè)結(jié)論,我們可以通過(guò)簡(jiǎn)單的立體幾何知識(shí)確定P在新坐標(biāo)系中的坐標(biāo)。P在新坐標(biāo)系中的X坐標(biāo)和Y坐標(biāo)分別是
進(jìn)而我們可以得到:
到此,我們完成了旋轉(zhuǎn)操作,如何平移呢??jī)H是加一個(gè)平移常數(shù)的事:
到此,我們的2*3大小的仿射變換便推導(dǎo)出來(lái)了。
推導(dǎo)知道了,但如何實(shí)現(xiàn)呢?
opencv同樣給我們提供了計(jì)算仿射矩陣的函數(shù)接口:
這個(gè)函數(shù)可以計(jì)算出我們想要圖像變換的矩陣,但需要我們輸入至少三對(duì)點(diǎn)集,點(diǎn)集是什么鬼?為什么是至少三對(duì)?
我們可以看到上面公式里有六個(gè)變量,因此自然需要至少列六個(gè)等式才可計(jì)算出該矩陣。
因此我們需要找輸入圖像和輸出圖像上一一對(duì)應(yīng)的三對(duì)點(diǎn)(3個(gè)x,y對(duì)應(yīng)計(jì)算式)來(lái)作為輸入。
這樣,我們就可以進(jìn)行仿射變換啦。
透視變換原理
我們說(shuō)仿射變換是在二維空間中的旋轉(zhuǎn),平移和縮放。而透視變換則是在三維空間中視角的變化。
opencv中同樣給出了透視變換的函數(shù)接口:
和仿射變換基本相同,不同的是輸入透視變換矩陣M大小為3*3:
上面矩陣的未知量比仿射變換的矩陣多了一個(gè)透視變換矩陣T3(兩個(gè)未知量),因此我們需要給下面計(jì)算透視變換矩陣的函數(shù)提供四對(duì)以上的點(diǎn)來(lái)求解
T1為線性變換完成旋轉(zhuǎn),錯(cuò)切和放縮,T2完成平移操作。T3就是設(shè)了兩個(gè)變量來(lái)表示映射關(guān)系。
編程實(shí)現(xiàn)
理解了透視變換的原理后,我們就著手來(lái)實(shí)現(xiàn)了(代碼可以順次復(fù)制即可運(yùn)行):
首先是讀取原圖片并顯示啦:
然后我們需要選取原圖上的四個(gè)點(diǎn),并計(jì)算出該四對(duì)點(diǎn)變換后的位置。
如何選點(diǎn)?我們可以選兩邊白條的四個(gè)定點(diǎn)。那變換后的位置就需要我們自己估算了,如下圖:
我們希望將藍(lán)色的透視變換為黃色的。
我們選取了如圖四個(gè)點(diǎn),首先計(jì)算透視變換矩陣:
然后進(jìn)行透視變換:
這樣,我們就得到鳥(niǎo)瞰圖啦。