计算机视觉ch3 图像到图像的映射——单应性变换

文章目录

    • 原理
    • Python代码实现

环境准备: matplotlib库安装教程

对图像块应用仿射变换,本文将图像或者图像的一部分放在另一幅图像中,使得它们能够和指定的区域或者标记物对齐

原理

1.单应性变换
单应性变换是将一个平面内的点映射到另一个平面内的二维投影变换。
单应性变换具有很强的实用性,比如图像配准、图像纠正和纹理扭曲,以及创建全景图像。
按照下面的方程映射二维中的点:

点的齐次坐标是依赖于其尺度定义的,所以x=[x,y,w]=[αx,αy,αw]=[x/w,y/w,1]都表示同一个二维点。
因此,单应性矩阵H也仅依赖于其尺度定义,所以,单应性矩阵具有8个独立的自由度,这样点具有唯一的图像坐标x和y,这个额外的坐标使得我们可以简单的使用一个矩阵来表示变换。

进行点和变换的处理时,我们会按照列优先的原则存储这些点,因此n个二维点集将会存储为齐次坐标意义下的一个3×n数组,这会使得矩阵乘法和点的变换操作变得更加容易,对于聚类和分类的特征,我们将使用典型的行数组来存储数据。

2.仿射变换
在上述的投影变换中,有一些特别重要的变换,比如仿射变换。
计算机视觉ch3 图像到图像的映射——单应性变换_第1张图片
保持了w=1,不具有投影变换所具有的强大的变形能力。
仿射变换包含一个可逆矩阵A和一个平移向量t=[tx,ty]。

3.alpha通道
阿尔法通道是一个8位的灰度通道,该通道用256级灰度来记录图像中的透明度信息,定义透明、不透明和半透明区域,其中白表示不透明,黑表示透明,灰表示半透明。
阿尔法通道(Alpha Channel)是指一张图片的透明和半透明度。例如:一个使用16位存储的图片,可能5位表示红色,5位表示绿色,5位表示蓝色,1位是阿尔法。在这种情况下,它要么表示透明要么不是。一个使用32位存储的图片,每8位表示红绿蓝,和阿尔法通道。在这种情况下,就不光可以表示透明还是不透明,阿尔法通道还可以表示256级的半透明度。

alpha通道的值取值范围是0-255。0表示完全透明,255表示完全不透明。
我们将其将alpha通道值取值范围由0-255转换到0-1
alpha=1 当前图片完全不透明 得到前景(即当前图片)
alpha=0 当前图片完全透明 得到背景图
tp = array([[1350,2550,2550,1350],[2650,2650,3850,3850],[1,1,1,1]])中的四个1就表示四个角点的透明度为不透明,以此实现图像的完全覆盖

Python代码实现

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

im1 = array(Image.open('2.jpg').convert('L'))
im2 = array(Image.open('3.jpg').convert('L'))

# set to points
tp = array([[1350,2550,2550,1350],[2650,2650,3850,3850],[1,1,1,1]])
im3 = warp.image_in_image(im1,im2,tp)
figure()
gray()
subplot(221)
axis('off')
imshow(im1)
subplot(222)
axis('off')
imshow(im2)
subplot(223)
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(224)
imshow(im4)
axis('off')
show()
计算机视觉ch3 图像到图像的映射——单应性变换_第2张图片

坐标点解析

fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])
tp = array([[1350,2550,2550,1350],[2650,2650,3850,3850],[1,1,1,1]])

整个代码的作用是将图片im1贴到图片im2的对应位置上,那么这个位置靠的就是坐标点来确定
计算机视觉ch3 图像到图像的映射——单应性变换_第3张图片计算机视觉ch3 图像到图像的映射——单应性变换_第4张图片

我们可以将图片im2看作一个坐标轴,左上角为坐标原点,然后确定im1四个顶点在该坐标轴中的位置。
例如代码中的坐标点,对应的便是上图,我们将图片im1设置为1200×1200
因此可以调整代码中m,n的值来改变im1的大小

tp = array([[1350,1950,1950,1350],[2650,2650,3250,3250],[1,1,1,1]])

我们不改变左上角坐标的值,仅将图片大小修改为600×600
计算机视觉ch3 图像到图像的映射——单应性变换_第5张图片
甚至我们可以不按照图片原本的格式对坐标点进行设置

tp = array([[1350,2550,1950,1350],[2650,2650,3850,3850],[1,1,1,1]])

修改第三、四个点的y坐标差值为第一、二个点y坐标的一半,使其成为一个45°直角梯形
计算机视觉ch3 图像到图像的映射——单应性变换_第6张图片

解决No module named 'matplotlib.delaunay’问题
在运行代码前可能会出现ModuleNotFoundError: No module named 'matplotlib.delaunay’报错,解决方法可参考以下文章

https://blog.csdn.net/weixin_42648848/article/details/88667243

你可能感兴趣的:(计算机视觉ch3 图像到图像的映射——单应性变换)