基于Opencv的圖像單應(yīng)性轉(zhuǎn)換實(shí)戰(zhàn)
點(diǎn)擊上方“小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)

同形轉(zhuǎn)換
我們所常見的都是以這樣的方式來處理圖像:檢測(cè)斑點(diǎn),分割感興趣的對(duì)象等。我們?nèi)绾螌⑺鼈儚囊环N形式轉(zhuǎn)換為另一種形式來處理這些圖像呢?通過單應(yīng)矩陣快速轉(zhuǎn)換圖像可以實(shí)現(xiàn)這個(gè)需求。
單應(yīng)性,也被稱為平面單應(yīng)性,是兩個(gè)平面之間發(fā)生的轉(zhuǎn)換。換句話說,它是圖像的兩個(gè)平面投影之間的映射。它由同構(gòu)坐標(biāo)空間中的3x3轉(zhuǎn)換矩陣表示。在數(shù)學(xué)上,同質(zhì)矩陣表示為:

在坐標(biāo)標(biāo)平面上:

如圖所示,圖像中的元素在同一個(gè)坐標(biāo)平面中投影到另一幅圖像,保留了相同的信息,但具有變換的透視圖。現(xiàn)在,讓我們使用Python代碼實(shí)現(xiàn)這一操作。與往常一樣,在我們實(shí)際執(zhí)行此操作之前。必須導(dǎo)入以下庫(kù):
from skimage.io import imread, imshowfrom skimage import transformimport matplotlib.pyplot as pltimport numpy as np
我們將在本文中使用多個(gè)圖像。通過單擊標(biāo)題中嵌入的鏈接來下載圖像。考慮一下這個(gè)棋盤:
chess = imread('chess.png')imshow(chess)

假設(shè)你們想改為看到木板及其零件的鳥瞰圖。是否可以僅使用圖像中的信息來做到這一點(diǎn)?在這種情況下,你們要做的就是找到木板的角并將其設(shè)置為原坐標(biāo)。之后,在要進(jìn)行單應(yīng)性投影的同一圖像中,選擇要顯示變換后的圖像的目標(biāo)坐標(biāo)。該代碼已實(shí)現(xiàn):
#source coordinatessrc = np.array([391, 100,14, 271,347, 624,747, 298,]).reshape((4, 2))#destination coordinatessrc = np.array([100, 100,100, 650,650, 650,650, 100,]).reshape((4, 2))#using skimage’s transform module where ‘projective’ is our desired parametertform = transform.estimate_transform('projective', src, dst)tf_img = transform.warp(chess, tform.inverse)#plotting the transformed imagefig, ax = plt.subplots()ax.imshow(tf_img)_ = ax.set_title('projective transformation')

既然我們已經(jīng)做到了,那么考慮到目標(biāo)圖像來自其他圖像的情況,我們又如何處理另一個(gè)圖像呢?讓我們來看這個(gè)例子??紤]一下這張圖像,一場(chǎng)籃球比賽。
still2 = imread('still2.png')imshow(still2)

假設(shè)我們有興趣通過單應(yīng)性法改變球場(chǎng)的一半。首先,從上面的圖像(即半場(chǎng)的角)確定原坐標(biāo)。然后,從另一幅與上述圖像完全不同的圖像中找到我們的目的地坐標(biāo)。我們正在談?wù)摰牧硪粋€(gè)圖像如下所示:
court = imread('court.png')plt.imshow(court)

讓我們通過代碼實(shí)際看到這一點(diǎn):
src_2 = np.array([440, 470,10, 750,1190, 490,1195, 785,]).reshape((4, 2))dst_2 = np.array([3, 7,3, 506,447, 7,447, 506,]).reshape((4, 2))fig, ax = plt.subplots(3, 1, figsize=(25, 15))ax[0].imshow(still2, )ax[0].scatter(src_2[:,0], src_2[:,1], c='red', s=30)ax[0].set_title('source coordinates')ax[1].imshow(court)ax[1].scatter(dst_2[:,0], dst_2[:,1], c='red', s=30)ax[1].set_title('destination coordinates')dst_2 = dst_2*2 #because image sizes are not the same.tform = transform.estimate_transform('projective', src_2, dst_2)tf_img = transform.warp(still2, tform.inverse)ax[2].imshow(tf_img)ax[2].scatter(dst_2[:,0], dst_2[:,1], c='red', s=10)



就這樣利用單應(yīng)矩陣來進(jìn)行變換圖像,現(xiàn)在,我們不僅可以從另一個(gè)角度來看待球場(chǎng)上的玩家,而且仍然保留了原始角度的相關(guān)信息。
交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請(qǐng)按照格式備注,否則不予通過。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~

