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