python 圖像變換,根據仿射或單應性變換實現圖像扭曲、映射、融合


一、最小二乘法求解單應性變換矩陣

1、單應性:

 在計算機視覺中:對單應性最感興趣的部分只是其他意義的一個子集。平面的單應性被定義為從一個平面到另一個平面的投影映射。比如,一個二維平面上的點映射到攝像機成像儀上的映射就是平面單應性的例子。

 考慮圖1中所示的平面的兩個圖像(書的頂部)。紅點表示兩個圖像中的相同物理點。在計算機視覺術語中,我們稱這些對應點。圖1.用四種不同的顏色(紅色,綠色,黃色和橙色)顯示了四個對應的點。甲單應的是,在一個圖像中的點映射到另一圖像中的對應點的變換(3×3矩陣)。

使用OpenCV的單應性示例。 在兩個圖像中用四個不同顏色的四個對應點標記的圖像。
 圖1:3D平面的兩幅圖像(本書頂部)通過同形圖法進行關聯

 現在,由於單應性是一個3×3矩陣,我們可以將其寫為

  H = \ left [\ begin {array} {ccc} h_ {00}&h_ {01}&h_ {02} \\ h_ {10}&h_ {11}&h_ {12} \\ h_ {20}& h_ {21}和h_ {22} \ end {array} \ right]

 讓我們考慮第一組對應點- (x_1,y_1) 在第一張圖片中 (x_2,y_2)}在第二張圖片中。然后,同形異義詞H 按照以下方式映射它們

  \ left [\ begin {array} {c} x_1 \\ y_1 \\ 1 \ end {array} \ right]&= H \ left [\ begin {array} {c} x_2 \\ y_2 \\ 1 \ end { array} \ right]&= \ left [\ begin {array} {ccc} h_ {00}&h_ {01}&h_ {02} \\ h_ {10}&h_ {11}&h_ {12} \\ h_ {20}和h_ {21}和h_ {22} \ end {array} \ right] \ left [\ begin {array} {c} x_2 \\ y_2 \\ 1 \ end {array} \ right]

 使用單應影像進行圖像對齊

 對於所有對應點集,只要它們位於現實世界中的同一平面上,上述方程式就是正確的。換句話說,您可以將單應性應用於第一個圖像,第一個圖像中的書將與第二個圖像中的書對齊!

使用均譜法將同一平面上的一幅圖像與另一幅圖像對齊。
 圖2:使用Homography可以將3D平面的一幅圖像與同一平面的另一幅圖像對齊
 
2、算法代碼:H_from_points(fp,tp)函數

  

 直接使用cv2中的Homography函數:

import cv2
from matplotlib.pyplot import *

if __name__ == '__main__':
    # Read source image.
    im_src = cv2.imread('IMG_03.jpg')
    # Four corners of the book in source image
    pts_src = np.array([[141, 131], [480, 159], [493, 630], [64, 601]])

    # Read destination image.
    im_dst = cv2.imread('IMG_04.jpg')
    # Four corners of the book in destination image.
    pts_dst = np.array([[318, 256], [534, 372], [316, 670], [73, 473]])

    # Calculate Homography
    h, status = cv2.findHomography(pts_src, pts_dst)

    # Warp source image to destination based on homography
    im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1], im_dst.shape[0]))

    # Display images
    figure()
    subplot(1, 3, 1)
    axis('off')
    title(u'Source Image')
    imshow(im_src)

    subplot(1, 3, 2)
    axis('off')
    title(u'Destination Image')
    imshow(im_dst)

    subplot(1, 3, 3)
    axis('off')
    title(u'Warped Source Image')
    imshow(im_out)
    
    show()

3、運行結果

二、最小二乘法求仿射變換矩陣
1、仿射變換(Affine Transformation或 Affine Map)

  是指在幾何中,一個向量空間進行一次線性變換並接上一個平移,變換為另一個向量空間。

  仿射變換可以由以下基本變換復合而成:平移(Translation)、縮放(Scale)、翻轉(Flip)、旋轉(Rotation)和錯切(Shear),這些基本的變換可由下圖表示:

 

  下圖中變換矩陣將原坐標(x, y)變換為新坐標(x', y')

2、仿射變換最小二乘法

 景物在成像過程中產生的扭曲,會使圖像的比例失調,可用仿射變換來校正各種畸變。而仿射變換的參數可以用最小二乘法進行估算。

 設原圖像為f(x,y),畸變后的圖像為F(X',Y'),要將F(X',Y')恢復為f(x,y),就是要找到(X',Y')坐標與(x,y)坐標的轉換關系,這個轉換關系稱為坐標變換,表示為(x,y)=T(X',Y')。

 景物在成像過程中產生的扭曲,會使圖像的比例失調,可用仿射變換來校正各種畸變。先計算出坐標變換的系數,仿射變換的表達式為:R(x)=Px+Q, x=(x,y)是像素的平面位置,P是2*2的旋轉矩陣,Q是2*1的平移向量,P、Q即為仿射變換參數,即:

       x= AX' + BY' + C

       y= DX' + EY' + F

 因此,幾何畸變的校正歸根結底為坐標轉換系數A,B,C,D,E,F的求解。

 為了防止出現空像素,一般采用反向映射,由最小二乘法得(matlab):

       vec1 = inv([X Y I]'*[X Y I])*[X Y I]'*U;

       vec2 = inv([X Y I]'*[X Y I])*[X Y I]'*V;

 其中vec1=[A B C]'; vec2 =[D E F]'; X Y U V I分別是x,y,X', Y', 1構成的向量。

 最小二乘法估計就是估計原始坐標點與經過變換后的坐標點之間的關系,從通過這種關系進行矯正圖像,大體步驟如下:

   

 

3、算法代碼:Haffine_form_points(fp,tp)函數

 

 

 

 

三、圖像扭曲

 1.定義及原理

 對圖像塊應用仿射變換,我們將其稱為圖像扭曲(或者仿射扭曲)。

 仿射變換能夠保持圖像的“平直性”,包括旋轉,縮放,平移,錯切操作。對於三個點,仿射變換可以將一副圖像進行扭曲,使得三對對應點對可以完美地匹配上。仿射變換具有6個自由度,有三個對應點對可以給出6個約束條件(對於這三個對應點對,x和y坐標必須都要匹配)

 

 仿射變換是在幾何上定義為兩個向量空間之間的一個仿射變換或者仿射映射。由一個非奇異的線性變換(運用一次函數進行的變換)接上一個平移變換組成。在有限維的情況,每個仿射變換可以由一個矩陣A和一個向量b給出,它可以寫作A和一個附加的列b。一個仿射變換對應於一個矩陣和一個向量的乘法,而仿射變換的復合對應於普通的矩陣乘法,只要加入一個額外的行到矩陣的底下,這一行全部是0除了最右邊是一個1,而列向量的底下要加上一個1。

 2、代碼

from array import array
from scipy import ndimage
from PIL import Image
from pylab import *

im = array(Image.open('..//images//02.jpg').convert('L'))
H = array([[1.4,0.05,-100],[0.05,1.5,-100],[0,0,1]])
im2 = ndimage.affine_transform(im,H[:2,:2],(H[0,2],H[1,2]))

figure()
gray()
subplot(121)
axis('off')
imshow(im)
subplot(122)
axis('off')
imshow(im2)
show()

 3.運行結果

 

 

 

四、圖像的映射融合(圖像中的圖像)

 仿射扭曲的一個簡單例子是將圖像或者圖像的一部分放置在另一幅圖像中,使得他們能夠和指定的區域或者標記物對齊。

 以下函數的輸入參數為兩幅圖像和一個坐標。該坐標為將一副圖像放置到第二幅圖象中的角點位置:

 • 流程

  ① 針對兩張/多張圖像提取特征
  ② 特征匹配
  ③ 根據圖像變換特點,選取合適的變換結構
  ④ 根據DLT等方法計算變換結構
  ⑤ 采用正向/逆向映射,利用插值方式實現圖像映射變換

1.代碼

from array import array
from PCV.geometry import warp, homography
from PIL import Image
from pylab import *
from scipy import ndimage

# example of affine warp of im1 onto im2
im1 = array(Image.open('../images/01.jpg').convert('L'))
im2 = array(Image.open('../images/02.jpg').convert('L'))
# set to points
tp = array([[164,538,540,264],[40,36,405,405],[1,1,1,1]])
im3 = warp.image_in_image(im1,im2,tp)
figure()
gray()
subplot(141)
axis('off')
imshow(im1)
subplot(142)
axis('off')
imshow(im2)
subplot(143)
axis('off')
imshow(im3)

# set from points to corners of im1
m,n = im1.shape[:2]
fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])
# first triangle
tp2 = tp[:,:3]
fp2 = fp[:,:3]
# compute H
H = homography.Haffine_from_points(tp2,fp2)
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
# alpha for triangle
alpha = warp.alpha_for_triangle(tp2,im2.shape[0],im2.shape[1])
im3 = (1-alpha)*im2 + alpha*im1_t
# second triangle
tp2 = tp[:,[0,2,3]]
fp2 = fp[:,[0,2,3]]
# compute H
H = homography.Haffine_from_points(tp2,fp2)
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
# alpha for triangle
alpha = warp.alpha_for_triangle(tp2,im2.shape[0],im2.shape[1])
im4 = (1-alpha)*im3 + alpha*im1_t
subplot(144)
imshow(im4)
axis('off')
show()

2.運行結果:

 

 實驗用了仿射變換在圖像的使用,使原圖像通過仿射變換放置到目標圖像中,因為在Python中關於仿射變換的具體代碼已經集合封裝到warp.py和homography.py中,只需要導入直接使用里面的函數,就可以跑出結果。

 

參考:

https://www.cnblogs.com/bingdaocaihong/p/7003581.html

https://blog.csdn.net/yf_0707/article/details/88668171


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM