图像变换的基本模型
变换模型是指根据待匹配图像与背景图像之间几何畸变的情况,所选择的能最佳拟合两幅图像之间变化的几何变换模型。可采用的变换模型有如下几种:刚性变换、仿射变换、透视变换和非线形变换等,如下图:
刚体变换(图像旋转)
如果一幅图像中的两点间的距离变换到另一幅图像中后任然保持不变,则这种变换称为刚体变换(Rigid Transform).刚体变换仅局限于平移,旋转和镜像. 在二位控件中,点(x,y)经过刚体变换到点(x',y')的变换公式为:
上式中φ 为旋转角度,
为平移变量。
如何推导出这个公式的下面来说明一下:
先下个定义,图像旋转是指图像以某一点为中心旋转一定的角度,形成一幅新的图像的过程。当然这个点通常就是图像的中心。既然是按照中心旋转,自然会有这样一个属性:旋转前和旋转后的点离中心的位置不变.
根据这个属性,我们可以得到旋转后的点的坐标与原坐标的对应关系。由于原图像的坐标是以左上角为原点的,所以我们先把坐标转换为以图像中心为原点。假设原图像的宽为w,高为h,(x0,y0)为原坐标内的一点,转换坐标后的点为(x1,y1)。那么不难得到:
x1 = x0 - w/2; y1 = -y0 + h/2;
在新的坐标系下,假设点(x0,y0)距离原点的距离为r,点与原点之间的连线与x轴的夹角为b,旋转的角度为a,旋转后的点为(x1,y1), 如下图所示。
那么有以下结论:
x0=rcosb;y0=rsinb
x1 = rcos(b-a) = rcosbcosa+rsinbsina=x0cosa+y0sina;
y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa;
得到了转换后的坐标,我们只需要把这些坐标再转换为原坐标系即可。这里还有一点要注意,旋转后的图像的长和宽会发生变化,因此要计算新图像的长和宽。
python cv2 实现
def myrotate():
"""图像刚性转化的图形旋转Python实现"""
srcImage = cv2.imread("sunnys.jpg") # 读取源图片
sp = srcImage.shape
h=srcImage.shape[0] #高
w=srcImage.shape[1] #宽
radian=45/180*np.pi #旋转角度转弧度
cos_val=np.cos(radian)
sin_val=np.sin(radian)
w2=round(abs(cos_val)*w+h*abs(sin_val)) #旋转后的宽
h2=round(abs(cos_val)*h+w*abs(sin_val)) #旋转后的高
dx=-0.5*w2*cos_val-0.5*h2*sin_val+0.5*w #x位移坐标
dy=0.5*w2*sin_val-0.5*h2*cos_val+0.5*h #y位移坐标
map_x = np.zeros((h2,w2),np.float32)
map_y = np.zeros((h2,w2),np.float32)
for y in range(0,int(h2-1)): #坐标旋转遍历
for x in range(0,int(w2-1)):
xS = (x*cos_val + y*sin_val+dx)
yS = (-x*sin_val+y*cos_val+dy)
xS=round(xS)
yS=round(yS)
map_x[y,x]=xS
map_y[y,x]=yS
dstImg=cv2.remap(srcImage, map_x, map_y, cv2.INTER_LINEAR) #用cv2 重映射图像
while(True):
cv2.imshow('dstImg',dstImg)
c=cv2.waitKey(1) #按Esc键退出
if c==27:
break
原图:
效果图:
仿射变换
未完待续。。。。。。。