计算机视觉学习(三):仿射变换将一幅图像放置到另一幅图像中
本例子為通過(guò)仿射扭曲變換將圖像放置到另一幅圖像中,使得它們能夠和指定的區(qū)域或者標(biāo)記物對(duì)齊。
? 運(yùn)行的代碼如下:
# test.py from PCV.geometry import warp, homography from PIL import Image from pylab import * from scipy import ndimage#放射扭曲im1到im2 #打開(kāi)兩張圖片 im1 = array(Image.open('D:\pythonxy\image/wen.jpg').convert('L')) im2 = array(Image.open('D:\pythonxy\image/yu.jpg').convert('L'))#設(shè)置映射的目標(biāo)點(diǎn) tp = array([[240,375,375,240],[143,145,275,275],[1,1,1,1]])#使用仿射變換將im1放置在im2上,使im1圖像的角和tp盡可能的靠近 im3 = warp.image_in_image(im1,im2,tp)#將圖像灰度顯示 figure() gray() subplot(131) axis('off') imshow(im1) subplot(132) axis('off') imshow(im2) subplot(133) axis('off') imshow(im3)#選定im1角上的一些點(diǎn) m,n = im1.shape[:2] fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])# 第一個(gè)三角形 tp2 = tp[:,:3] fp2 = fp[:,:3]# 計(jì)算仿射變換H,并且將其應(yīng)用于圖像im1 H = homography.Haffine_from_points(tp2,fp2)#affine仿射變換的方式把第一幅圖像變到第二幅圖像里面 im1_t = ndimage.affine_transform(im1,H[:2,:2], (H[0,2],H[1,2]),im2.shape[:2]) # 對(duì)圖像進(jìn)行alpha通道處理,三角形的alphy alpha = warp.alpha_for_triangle(tp2,im2.shape[0],im2.shape[1]) #創(chuàng)建alpha圖像 im3 = (1-alpha)*im2 + alpha*im1_t axis('off') show()? 運(yùn)行的結(jié)果圖如下:
圖二建筑物來(lái)源于集美大學(xué)?
其中主要用到了兩個(gè)函數(shù):warp 和 homography(單應(yīng))
? warp函數(shù)中又用到了兩個(gè)方法:image_in_image() 和?alpha_for_triangle()
? ? image_in_image() 方法的代碼如下:
#tp是齊次表示的,并且是按照從左上角逆時(shí)針計(jì)算的 #使用仿射變換將im1放置在im2上,使im1圖像的角和tp盡可能的靠近 def image_in_image(im1,im2,tp):# 扭曲的點(diǎn)m,n = im1.shape[:2]#點(diǎn)的坐標(biāo)fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])#算出兩個(gè)圖像間的變換關(guān)系,返回給定對(duì)應(yīng)點(diǎn)的最優(yōu)仿射變換,并用H表示H = homography.Haffine_from_points(tp,fp)#affine通過(guò)仿射變換的方式把第一幅圖像變到第二幅圖像里面im1_t = ndimage.affine_transform(im1,H[:2,:2],(H[0,2],H[1,2]),im2.shape[:2])#alpha通道對(duì)圖像進(jìn)行處理alpha = (im1_t > 0)return (1-alpha)*im2 + alpha*im1_t? ? 該方法的輸入?yún)?shù)為兩幅圖像和一個(gè)tp坐標(biāo),該坐標(biāo)為將第一幅圖像放置到第二幅圖像中的角點(diǎn)坐標(biāo),是齊次表示的。然后將扭曲的im1圖像和im2圖像融合,創(chuàng)建alpha圖像。該alpha圖像定義了每個(gè)像素從各個(gè)圖像中獲取的像素值成分的多少。扭曲的 圖像是在扭曲區(qū)域邊界以外用0來(lái)填充的圖像,以此來(lái)創(chuàng)建一個(gè)二值的alpha圖像。所以從嚴(yán)格意義上來(lái)說(shuō),我們需要在第一幅圖像中的潛在0像素上加上一個(gè)小的數(shù)值。
? ? alpha_for_triangle() 方法的代碼如下:
def alpha_for_triangle(points,m,n):#對(duì)于由角點(diǎn)定義的三角形創(chuàng)建大小為(m,n)的alpha映射(在歸一化齊次坐標(biāo)中給出) alpha = zeros((m,n))for i in range(min(points[0]),max(points[0])):for j in range(min(points[1]),max(points[1])):x = linalg.solve(points,[i,j,1])#如果所有系數(shù)為正if min(x) > 0:alpha[i,j] = 1#返回alpha的值return alpha? ? alpha通道是一個(gè)8位的灰度通道,該通道用256級(jí)灰度來(lái)記錄圖像中的透明度信息,定義透明、不透明和半透明區(qū)域,其中白表示不透明,黑表示透明,灰表示半透明。使用alpha通道來(lái)給圖像增加透明度。這里我們簡(jiǎn)單地為每個(gè)三角形創(chuàng)建了alpha圖像,然后將所有的圖像合并起來(lái)。該三角形的alpha圖像可以簡(jiǎn)單地通過(guò)檢查像素的坐標(biāo)能否寫(xiě)成三角形頂點(diǎn)坐標(biāo)的凸組合來(lái)計(jì)算得出。如果坐標(biāo)可以表示成這種形式,那么該像素就位于三角形的內(nèi)部。
??homography函數(shù)中用到了Haffine_from_points()方法
? ??Haffine_from_points()方法的代碼如下:
def Haffine_from_points(fp,tp): #對(duì)H進(jìn)行仿射變換,tp是fp的仿射輸注if fp.shape != tp.shape:raise RuntimeError('number of points do not match')#條件點(diǎn)m = mean(fp[:2], axis=1)maxstd = max(std(fp[:2], axis=1)) + 1e-9C1 = diag([1/maxstd, 1/maxstd, 1]) C1[0][2] = -m[0]/maxstdC1[1][2] = -m[1]/maxstdfp_cond = dot(C1,fp)# 條件點(diǎn)指向m = mean(tp[:2], axis=1)C2 = C1.copy() #must use same scaling for both point setsC2[0][2] = -m[0]/maxstdC2[1][2] = -m[1]/maxstdtp_cond = dot(C2,tp)# 條件點(diǎn)的平均值為零,所以平移為零A = concatenate((fp_cond[:2],tp_cond[:2]), axis=0)U,S,V = linalg.svd(A.T)# 創(chuàng)建B、C矩陣tmp = V[:2].TB = tmp[:2]C = tmp[2:4]tmp2 = concatenate((dot(C,linalg.pinv(B)),zeros((2,1))), axis=1) H = vstack((tmp2,[0,0,1]))# 仿射H = dot(linalg.inv(C2),dot(H,C1))return H / H[2,2]? ? 該方法會(huì)返回給定對(duì)應(yīng)點(diǎn)的最優(yōu)仿射變換。以本例子來(lái)說(shuō),對(duì)應(yīng)點(diǎn)為圖像和黑方塊的角點(diǎn),如果透視效應(yīng)比較弱,那么這種方法會(huì)返回很好的結(jié)果。
? ? 透視變換的本質(zhì)是將圖像投影到一個(gè)新的視平面。仿射變換可以理解為透視變換的特殊形式。
? ??一幅圖像就是一個(gè)像素坐標(biāo)系下的各個(gè)帶有像素值的坐標(biāo)點(diǎn),而透視變換可以理解為就是將一幅圖像中的這些坐標(biāo)點(diǎn)完成了一個(gè)坐標(biāo)轉(zhuǎn)換,將它們的坐標(biāo)變換到了其他位置,從而實(shí)現(xiàn)了變換了圖像視角的效果。因此,透視變換和相機(jī)標(biāo)定等概念其實(shí)并沒(méi)有什么內(nèi)在關(guān)系。在車道線檢測(cè)中的“相機(jī)標(biāo)定”過(guò)程,其實(shí)就是做了一個(gè)透視變換,即相機(jī)畫(huà)面圖像和一幅假想的地面圖像這兩幅圖像之間的變換關(guān)系,所謂假想的地面圖像,即將實(shí)際地面上各點(diǎn)距離(離車輛后軸中心點(diǎn))按一個(gè)設(shè)定的尺度放到一張圖像上(鳥(niǎo)瞰圖),此時(shí)只要是在這個(gè)地平面上的點(diǎn),通過(guò)透視變換都可以得到其在相機(jī)圖像上的點(diǎn)的坐標(biāo)。因?yàn)榧傧氲氖窃诘仄矫嫔系狞c(diǎn)做的透視變換,所以此時(shí)只有位于地平面上的物體,才具有真正的鳥(niǎo)瞰圖像素值,投影到圖像上才是正常的。
總結(jié)
以上是生活随笔為你收集整理的计算机视觉学习(三):仿射变换将一幅图像放置到另一幅图像中的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 开源=安全?RVN盗币事件复盘
- 下一篇: RuntimeError: Attemp