仿射变换、透视变换、图像配准

目录

一,仿射变换

1,前向映射

2,反向映射

二,常见的仿射变换

1,恒等变换

2,尺度变换(缩放)

3,旋转变换​

4,平移变换

5,偏移变换

三,透视投影

四,透视变换

五,图像配准

六,Opencv 配准+变换

七,其他变换

1,双线性变换

2,实现双线性变换和透视变换


一,仿射变换

仿射变换的映射方式有两种,前向映射和反向映射。

1,前向映射

扫描原图的每个像素(v,w),变换后的值填入对应的(x,y)处。

对于多个像素点映射到同一个(x,y)的情况,不太好处理,所以反向映射更有效。

2,反向映射

扫描变换后图像的每个像素(x,y),根据逆变换找到原图中对应的(v,w)

大概率找到的不是整点,所以需要使用图像插值 https://blog.csdn.net/nameofcsdn/article/details/118281568

二,常见的仿射变换

1,恒等变换

2,尺度变换(缩放)

3,旋转变换

4,平移变换

5,偏移变换

垂直偏移变换:

水平偏移变换:

三,透视投影

把三维图像透视投影到二维平面:

x' = x/z , y' = y/z

如,有3个垂直于z轴的正方形,分别是:

{6<=x<=12,6<=y<=12,z=1}、{6<=x<=12,6<=y<=12,z=2}、{6<=x<=12,6<=y<=12,z=3}

那么投影之后得到的正方形如图:

这么看着没什么感觉,但是如果旋转180度,再添加2条透视线:

显然,原点O就是透视点,对应z=∞的点。

四,透视变换

透视变换就是,把一个平面图形在三维空间中做仿射变换,然后再做透视投影变成平面图形。

三维仿射变换:

其中w可以取任意不为0的数,如w=1

然后透视投影:

注意到,这9个变量同时放大缩小是不影响的,所以不妨设a33 = 1,那么就剩下8个未知数。

五,图像配准

输入两幅图片,已知一副图像是另外一副图像变换得到,通过计算反推出变换。

常用的方法就是根据特征点,代入图像变换的公式求解。

特征点的最少数目,取决于变换的方式。而特征点越多,自然配准越容易,越准确。

PS:只有部分重合的图片,也能做配准,如全景照片就是配准之后拼接起来的。

六,Opencv 配准+变换

从未知数的数量来看,仿射变换有6个未知数,透视变换有8个未知数。

所以确定一个仿射变换需要3个点的前后坐标值,确定一个透视变换需要4个点的前后坐标值。

从几何意义来看,仿射变换是平面操作,所以需要3个点,透视变换是空间操作,所以需要4个点。

Opencv里面提供了仿射变换和透视变换的配准和变换的接口,先提供点的坐标匹配,根据坐标匹配自动配准,得到变换公式的对象,再用这个对象对整个图像进行变换。

仿射变换:(这里是旋转的示例)

image = cv2.imread("D:/im.jpg", 0)
image = cv2.resize(image,(500,500))
cv2.imshow("img",image)
p_src = numpy.float32([[0, 0],[0, 500],[500, 0]])
p_dst = numpy.float32([[300, 0],[0, 400],[700, 300]])
trans = cv2.getAffineTransform(p_src,p_dst)
image2 = cv2.warpAffine(image,trans,(700,700))
cv2.imshow("img2",image2)
cv2.waitKey(0)

变换结果:

透视变换:

image = cv2.imread("D:/im.jpg", 0)
image = cv2.resize(image,(500,500))
cv2.imshow("img",image)
p_src = numpy.float32([[0, 0],[0, 500],[500, 0],[500,500]])
p_dst = numpy.float32([[0, 0],[0, 500],[250, 0],[500,500]])
trans = cv2.getPerspectiveTransform(p_src,p_dst)
image2 = cv2.warpPerspective(image,trans,(500,500))
cv2.imshow("img2",image2)
cv2.waitKey(0)

变换结果: 

七,其他变换

1,双线性变换

显然这个也是需要4个点才能确定变换。

书中的这个式子卡住了我很久,因为我一直想不通这是什么变换,于是我举了一个简单的例子:

把正方形{(0,0)(0,500)(500,0){500,500}}变换为梯形{(0,0)(0,250)(500,0){500,500}}

如果是透视,那么变换就是x=500u/(1000-u), y=500v/(1000-u)

如果是双线性变换,那么就是x=u, y=v(u+500)/1000

2,实现双线性变换和透视变换

代码:

image = cv2.imread("D:/im.jpg", 0)
image = cv2.resize(image,(500,500))
cv2.imshow("img",image)
image2 = image.copy()
image3 = image.copy()
for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        image2[i, j] = 0
        image3[i, j] = 0
for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        image2[int(i * 500 / (1000 - i)) % image.shape[0], int(j * 500 / (1000 - i)) % image.shape[1]] = image[i, j]
        image3[i,int(j*(i+500)/1000)%image.shape[1]] = image[i,j]
cv2.imshow("image2",image2) #透视
cv2.imshow("image3",image3) #双线性
cv2.waitKey(0)

运行:

 可以看出来,图2是透视,物体在图片中的高度位置有变化,直线还是直线,

图3是双线性变换,高度没有变化,直线变得不直了。

PS:自己写的透视变换有点粗糙,中间有些黑线,如果是反向映射的话应该就不会这样了:

image = cv2.imread("D:/im.jpg", 0)
image = cv2.resize(image,(500,500))
cv2.imshow("img",image)
image2 = image.copy()
image3 = image.copy()
for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        image2[i, j] = 0
        image3[i, j] = 0
for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        j2 = int(j * 1000 / (i + 500))
        if j2 >= 500:
            image2[i, j] = 0
        else:
            image2[i,j] = image[int(i * 1000 / (i + 500)) % image.shape[0], j2]
        image3[i,int(j*(i+500)/1000)%image.shape[1]] = image[i,j]
cv2.imshow("image2",image2) #透视
cv2.imshow("image3",image3) #双线性
cv2.waitKey(0)

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像配准是指将两幅或多幅图像进行对齐,使它们在几何形状和外观上尽可能的相似。而透视变换是一种仿射变换的扩展,可以将一个平面上的任意四边形转换为另一个平面上的任意四边形。 基于OpenCV的图像配准之后,可以使用透视变换来实现图像的矫正、纠偏等操作。具体步骤如下: 1. 首先,通过图像配准的方法将待处理的图像对齐,得到对应的变换矩阵; 2. 然后,利用该变换矩阵进行透视变换,将图像进行矫正、纠偏等操作; 3. 最后,可以进行进一步的图像处理,如图像增强、目标检测等。 下面是一个基于OpenCV的透视变换示例代码: ``` import cv2 import numpy as np # 读取原始图像 img = cv2.imread('test.png') # 设置目标图像的四个顶点 dst_points = np.float32([[100, 100], [500, 100], [500, 500], [100, 500]]) # 设置原始图像的四个顶点 src_points = np.float32([[10, 10], [630, 10], [630, 470], [10, 470]]) # 计算透视变换矩阵 M = cv2.getPerspectiveTransform(src_points, dst_points) # 进行透视变换 dst_img = cv2.warpPerspective(img, M, (600, 600)) # 显示结果 cv2.imshow('src_img', img) cv2.imshow('dst_img', dst_img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 其中,dst_points 和 src_points 分别表示目标图像和原始图像的四个顶点坐标,通过 cv2.getPerspectiveTransform 方法计算透视变换矩阵 M,然后通过 cv2.warpPerspective 方法进行透视变换,最终得到矫正后的图像 dst_img。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值