文章目录
2D的点、线、面
这里的点都是齐次式
点在线上的条件:
求过两点
、
的直线的表达式:
求两条直接直线的交点:
这里是叉乘,得到的是齐次式,换成非齐次就是交点的坐标
另一种写法:
理想点和无穷远线
具有齐次坐标 的点,一般来说不会和二维平面中的有限点对应,求两个平行线的交点的时候就会有这样的结果,也和平行线相交于无穷远的概念相吻合。
这样的点也被称为理想点,或无穷远点,这些点的集合为
,都集合在无穷远线上,无穷远线为
,且:
二次曲线
二次曲线方程:
五个点定义一条二次曲线,设参数为$ c= (a,b,c,d,e,f)^T$,把五个点约束起来得到:
求过曲线
上的点
的切线
:
中心投影
中心投影把一张平面的点映射成另一张平面的点,就是连接原点、
、
会在一条直线上,这种情况下直线还是被映射成直线,也能用
来表示。
如果在两个平面建立的是直角坐标系,那么就会有比普通射影更多的约束,被称为透视映射
虽然直线被映射成直线,但是直线与直线之间的夹角变了
2D平面间的变换类型
交比(cross ratio)
关于交比的性质:
- 交比的值和各点的具体齐次值无关
- 如果每个点都是有限点,并且齐次表示中均选择 ,那么 就表示由 到 的带符号的距离
- 如果其中有一个理想点,交比的定义仍然有效
- 在任何直线的射影变换下,交比的值不变
等距变换(Isometries transformations)
很简单,旋转与平移,也就是欧式变换:
,表示等距变换是保向(+)的还是逆向(-1)的
自由度:三个自由度:旋转一个,平移两个
不变量:长宽、角度、面积
相似变换(Similarity transformations)
欧式变换和均匀缩放的复合:
自由度:比欧式变换多一个缩放,四个,可用两组点求出
不变量:夹角、长宽比例、面积比例
仿射变换(Affine transformations)
仿射变换是非奇异线性变换和一个平移变换的复合
其中 是一个 是一个非奇异矩阵
理解A:
可以把
看成两种基本变换(旋转和非均匀缩放)的复合,可以分解为:
左边的式子是SVD算来的,对应起来如下:
其中
和
分别表示转角为
和
的旋转,
是对角矩阵:
解释下A做了什么:
先进行
的旋转,再旋转的基础上对
分别进行比例因子
的缩放,然后再加一个回转
,再加一个旋转
,可以看下图:
为啥要旋转后再缩放再旋转回来?
缩放的方向是根据图像固定的吗,比如说垂直于坐标系?
答:应该是固定的,两个缩放轴还是正交的,和坐标系相关联,旋转到需要的角度,然后对着这个角度来进行缩放,一套组合拳
自由度:比相似变换多了两个自由度,一个是缩放方向的
,京一个是缩放
的比例
,所以是六个
不变量:
- 平行线。
- 平行线段的长度比。假定线段和正交缩放方向 轴的夹角是 ,那么缩放比例就是 ,那么平行的线段夹角相同,缩放也就一样了
- 面积比。面积被缩放了 倍,所有的都是。
射影变换(Projective transformations)
是仿射变换的一种推广
和仿射变换的区别:
仿射变换在无穷远点的情况:
射影变换在无穷远点的情况:
我的理解就是多了个“放躺”的操作,这样无穷远点就能被映射到有限点,所以能对消影点进行建模。
射影变换作用:
射影变换也叫单应(homography),将点从一个平面映射到另一个平面上,假设射影变换就是
,那么满足射影变换的条件为:当且仅当
共线的时候,
也共线。
构成 的充要条件:存在一个 非奇异矩阵 ,使得一平面上的任一个用矢量 表示的点都满足 , 是对应平面的点。
这个
是一个齐次矩阵,就是说和点的齐次一样,乘上任何非零的常数都不会改变射影变换的效果,在这九个元素中有八个独立比率,因为一个射影变换有八个自由度。
不变量:四共线点的交比。
总结
射影变换可以分解成一串变换链的复合:
其中
,
是行列式为1的归一化上三角矩阵。
分别是相似变换、仿射百年换、射影变换
一个分解的实例:
可以被分解为:
消除平面透视图象的摄影失真
有些东西形状的变化,比如原本是矩形,在图片中却变成了平行四边形,原本平行的线变得不平行,且相交于一个有限点。
此时,已知平面的中心投影图像和原来的图像是通过射影变换
相关联的,所以这个图像就是原景物的射影失真,通过求
的逆变换就能还原到原图,撤销射影变换的影响。
这是2D到2D,投影是3D到2D
方法:
找两个图片的对应坐标,但是咱也不知道点啊?是手动把照片跳过去,然后求 ? 坐标系按照 中心投影图 那样,从左下角开始,作为原点?
还是说找四个本应平行的点,设为平行?要不写个代码看看行否
答:需要四个点,可以再原图取四个点,然后根据想要的关系设置对应的点,例子可以看后面的代码
假设两个平面有一对匹配点
,对应的非齐次坐标是
,两个平面间的射影变换可写成如下非齐次形式:
一组点可以提供两个方程,简化后:
有八个参数,所以四个点就可以求出来 的解,但是这四个点不能太特殊,比如共线。
这是最一般的方法,使用最小二乘就能求出来,而且现在也能直接用opencv来求
代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('C:\\Users\\saber\\Desktop\\CS231A\\python\\aa.png')
fig, ax = plt.subplots(2,3)
rows,cols = img.shape[:2]
# 原图
ax[0][0].imshow(img)
ax[0][0].set_title('original')
# 等距变换
H = np.float32([[1,0,100],[0,1,50]])
# 注意行列顺序
iso_t = cv2.warpAffine(img,H,(cols,rows))
ax[0][1].imshow(iso_t)
ax[0][1].set_title('iso')
# 缩放
# 想直接用比例就要在第二个参数设置None,这个是控制resize后大小的
scale = cv2.resize(img,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)
ax[0][2].imshow(scale)
ax[0][2].set_title('scale')
# 旋转
# 参数为:旋转中心、旋转角度(逆时针)、缩放比例
rot_matrix = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
rot = cv2.warpAffine(img,rot_matrix,(cols,rows))
ax[1][0].imshow(rot)
ax[1][0].set_title('rot')
# 仿射
# 仿射需要三个点对应起来
# 109,50 对 109 50
# 63 272 对 109 272
# 256 50 对 256 50
point_1 = np.float32([[109,50],[63,272],[256,50]])
point_2 = np.float32([[109,50],[109,272],[256,50]])
Aff_mat = cv2.getAffineTransform(point_1,point_2)
Aff = cv2.warpAffine(img,Aff_mat,(cols,rows))
ax[1][1].imshow(Aff)
ax[1][1].set_title('Aff')
# 透视
# 透视需要四个点
poi_1 = np.float32([[109,50],[63,272],[256,50],[300,272]])
poi_2 = np.float32([[109,50],[109,272],[256,50],[256,272]])
Per_mat = cv2.getPerspectiveTransform(poi_1,poi_2)
Per = cv2.warpPerspective(img,Per_mat,(cols,rows))
ax[1][2].imshow(Per)
ax[1][2].set_title('Per')
plt.show()