图像几何变换之仿射变换原理及实现 您所在的位置:网站首页 二维图像 图像几何变换之仿射变换原理及实现

图像几何变换之仿射变换原理及实现

2024-07-12 20:51| 来源: 网络整理| 查看: 265

今天学习了仿射变换,将一张图片放置到另一张图片,感觉十分有趣,所以写了这篇博客,与大家一起分享一下!

一、仿射变换

1.什么是仿射变换

2.alpha通道

3.仿射变换的求解

二、仿射变换的实现

1.主函数

2.主要函数的介绍

一、仿射变换 1.什么是仿射变换

(1)放射变换的定义

仿射变换是将一个平面的点映射到另一个平面内的二维投影。仿射变换保持了二维图形的“平直性”,即原来是直线的地方还是直线。仿射变换具有很强的实用性,比如图像配准、图像纠正和纹理纠正,以及创建全景图像等。仿射变换的效果如下图所示:

(2)仿射变换的数学表示

仿射变换是一种二维坐标(x, y)到二维坐标(u, v)的线性变换,其数学表达式形式如下:

对应的齐次坐标矩阵表示形式为:

其中,取\bg_white h_2_0\bg_white h_2_1为0,\bg_white h_2_2为1。

坐标变换:

实现将一张图片放置到另一张图片上去,其实就是已知XH,而H中的3个变量已知,我们只需求另外6个变量即可。

(3)仿射变换的几何意义

仿射变换可以理解成一系列的原子变换复合实现的,具体暴扣:平移、旋转、尺度变换等。

a.平移

数学形式:

矩阵形式:

平移变换包含两个未知量,即t_xt_y。计算两个图形的平移量,其实就是求这两个未知量。

b.旋转

矩阵形式:

 

c.尺度变换

矩阵形式:

d.刚体运动:旋转平移缩放

矩阵形式:

2.alpha通道

alpha用来衡量一个像素或图像的透明度。在非压缩的32位RGB图像中,每个像素是由四个部分组成:一个alpha通道和三个颜色分量(R、G和B)。当Alpha值为0时,该像素是完全透明的,而当Alpha值为255时,则该像素是完全不透明。 

alpha用于图像m1经过仿射变换后,将图像m1放置到图像m2时,只有alpha大于0的区域才能放置到图像m2上,alpha为0的区域在融合的时候就变成透明了。

3.仿射变换的求解

(1)流程

a.输入两张图像m1和m2

b.设置所需要放置的区域矩阵tp

c.获取m1的宽m和高n,并设置原图区域矩阵为fp

d.根据fp和tp计算仿射变换参数矩阵H

e.将m1放置到m2上去

(2)仿射变换参数矩阵H的求解

放射变换求解的关键就是H的求解,我们已知原图区域矩阵fp和需要放置的tp,需要求得仿射变换参数矩阵H。

我们利用最小二乘法求解H,其基本步骤如下:

a.检查tp和fp大小是否一致,若不一致则报错

b.对fp进行归一化

c.对tp进行归一化

d.利用SVD进行奇异值分解,剔除异常值,求得H

二、仿射变换的实现 1.主函数: # -*- coding: utf-8 -*- from PCV.geometry import warp, homography from PIL import Image from pylab import * from scipy import ndimage # im1仿射到im2的例子 #打开两张图片 im1 = array(Image.open('D:/test/beatles.jpg').convert('L')) im2 = array(Image.open('D:/test/billboard_for_rent.jpg').convert('L')) # 选定一些目标点,数组tp表示目标区域,三行分别代表y、x和齐次,其中区域按从左上角逆时针旋转, tp = array([[120,260,260,120],[16,16,305,305],[1,1,1,1]])#将一些目标点存储到数组中 im3 = warp.image_in_image(im1,im2,tp) #使用仿射变换将m1放置到m2 figure() gray() subplot(141) axis('off') imshow(im1) subplot(132) axis('off') imshow(im2) subplot(133) axis('off') imshow(im3) show() 2.主要函数的介绍:

(1)wrap.image_in_image(im1,im2,tp)

函数的意义是通过方式变换将图像m1放置到图像m2的指定区域tp中

def image_in_image(im1,im2,tp): """使用仿射变换将m1放置到m2,使得m1图像的角和tp尽可能的靠近。 tp是齐次表示的,并且按照从左上角逆时针计算的""" # 扭曲的点 m,n = im1.shape[:2]#获取m1的高m宽n fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]]) #计算仿射变换,并且将其应用于图像im1 H = homography.Haffine_from_points(tp,fp)#返回给定点对的最优仿射变换求H im1_t = ndimage.affine_transform(im1,H[:2,:2], (H[0,2],H[1,2]),im2.shape[:2])#图像扭曲 alpha = (im1_t > 0) return (1-alpha)*im2 + alpha*im1_t

(2)homography.Haffine_from_points(tp,fp)

函数的意义是通过原图像矩阵fp和仿射变换后的图像矩阵tp求得H

def Haffine_from_points(fp,tp): """计算H,仿射变换,使得tp是fp经过仿射变换H得到的""" if fp.shape != tp.shape: raise RuntimeError('number of points do not match') # 对点进行归一化 # 映射起始点 m = mean(fp[:2], axis=1)#取fp的前两行,压缩列求平均值 maxstd = max(std(fp[:2], axis=1)) + 1e-9 #取fp的前两行,压缩列求标准差,取最大值 C1 = diag([1/maxstd, 1/maxstd, 1]) C1[0][2] = -m[0]/maxstd C1[1][2] = -m[1]/maxstd fp_cond = dot(C1,fp) # 映射对应点 m = mean(tp[:2], axis=1) C2 = C1.copy() #两个点集,必须都进行相同的缩放 C2[0][2] = -m[0]/maxstd C2[1][2] = -m[1]/maxstd tp_cond = dot(C2,tp) #因为归一化后点的均值为0,因此平移为0 A = concatenate((fp_cond[:2],tp_cond[:2]), axis=0)#数组拼接 U,S,V = linalg.svd(A.T)#奇异值分解,用小的多的数据集来表示原始数据集 #创建B和C矩阵 tmp = V[:2].T B = tmp[:2] C = tmp[2:4] #B的伪逆矩阵和C逐元素相乘,与zero(2,1)拼接 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]

效果如下图所示:

左边为图像m1,中间为图像m2,右边为仿射变换后的效果图。我们可以清楚的看到m1放到了m2的指定区域,实现了两张图片的融合。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有