逆透视变换——变换矩阵的Python实现

Reference

透视变换原理和变换矩阵的python实现
个人理解,可能有误,欢迎讨论。
进行透视变换,需要选择四个点,这些点定义了一个长方形,但是在原始图像中由于照相角度等问题,它并没有呈现出是一个长方形,为了变换视角,我们需要进行透视变换。
透视变换本质上是将图片从一种视角通过四个点之间的线性变换得到另一种视角。

计算公式

透视变换矩阵:

在这里插入图片描述
我们定义目标点矩阵为在这里插入图片描述,定义源点矩阵为在这里插入图片描述
这是从二维像素坐标映射到三维世界坐标,我们这里的主要还是想把像素坐标映射到另一个像素坐标。
采用在这里插入图片描述
对于每一对在这里插入图片描述都满足下列等式
在这里插入图片描述
因此,我们可以得到公式(1)
在这里插入图片描述
上下相乘,继续推导可得:
在这里插入图片描述
我们需要求得在这里插入图片描述,另为未知数,将方程转换为矩阵 A X = 0 AX=0 AX=0
在这里插入图片描述
此时有9个未知数,我们需要用9个方程来求解,对于一对匹配点在这里插入图片描述我们可以得到两个方程。
为啥我们只需要4对匹配点就能求解上面的方程勒。

8未知数

我们发现对于公式(1)可以写成以下形式,结果不会改变。
在这里插入图片描述其中 α \alpha α为不为0的数
此时,将上述公式映射回矩阵形式,我们可以得到在这里插入图片描述
因此,我们可以得到
在这里插入图片描述
此时就只有8个未知数了,我们就只需要找4组对应点就可以求解方程。
反应到求解公式上就如下所示。
在这里插入图片描述
最后一位为常数1,我们可以修改公式为 公式(3)在这里插入图片描述

代码求解——自己实现

# 此处的src是原坐标数组,dst是目标坐标数组
def WarpPerspectiveMatrix(src, dst):
    assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4

    nums = src.shape[0]
    # 4组对应点,每组2行8列
    # 总共8行8列的数组,对应公式(3)中最左边的矩阵
    A = np.zeros((2 * nums, 8))
    # 4组对应点,每组2行1列
    # 总共8行1列,对应公式(3)中最右边的矩阵
    B = np.zeros((2 * nums, 1))
    # 矩阵赋值,0下标为x值,1下标为y值
    for i in range(0, nums):
        A_i = src[i,:]
        B_i = dst[i,:]
        A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0, -A_i[0]*B_i[0], -A_i[1]*B_i[0]]
        B[2*i] = B_i[0]

        A[2*i+1, :] = [0, 0 , 0, A_i[0], A_i[1], 1, -A_i[0]*B_i[1], -A_i[1]*B_i[1]]
        B[2*i+1] = B_i[1]

	# 转换为矩阵
    A = np.mat(A)
    # 求解未知数值,.I表示求逆
    warpMatrix = A.I * B

	# 矩阵后处理,主要是将a33的1值赋值回去
    warpMatrix = np.array(warpMatrix).T[0]
    warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0)
    warpMatrix = warpMatrix.reshape((3, 3))
    return warpMatrix

代码求解——Opencv实现

# 注意,这里的src和dst,本人验证,使用np.float32()定义可以不出错
M = cv2.getPerspectiveTransform(src, dst)
src = np.float32([[34 * 720 / 160, 113 * 1280 / 288], [34 * 720 / 160, 186 * 1280 / 288], [157 * 720 / 160, 50 * 1280 / 288], [157 * 720 / 160, 244 * 1280 / 288]])
dst = np.float32([[150, 50], [150, 490], [780, 50], [780, 490]])


def WarpPerspectiveMatrix(src, dst):
    assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4

    nums = src.shape[0]
    A = np.zeros((2 * nums, 8))
    B = np.zeros((2 * nums, 1))
    for i in range(0, nums):
        A_i = src[i,:]
        B_i = dst[i,:]
        A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0, -A_i[0]*B_i[0], -A_i[1]*B_i[0]]
        B[2*i] = B_i[0]

        A[2*i+1, :] = [0, 0 , 0, A_i[0], A_i[1], 1, -A_i[0]*B_i[1], -A_i[1]*B_i[1]]
        B[2*i+1] = B_i[1]

    A = np.mat(A)
    warpMatrix = A.I * B

    warpMatrix = np.array(warpMatrix).T[0]
    warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0)
    warpMatrix = warpMatrix.reshape((3, 3))
    return warpMatrix

M = WarpPerspectiveMatrix(src, dst)
print(M)
M = cv2.getPerspectiveTransform(src, dst)
print(M)
# 自己实现的
[[ 6.41178433e+00  0.00000000e+00 -7.04158205e+02]
 [ 1.54253726e+00  2.50298025e+00 -1.40077892e+03]
 [ 5.52700641e-03  0.00000000e+00  1.00000000e+00]]
# opencv官方的
[[ 6.41178433e+00  0.00000000e+00 -7.04158205e+02]
 [ 1.54253726e+00  2.50298025e+00 -1.40077892e+03]
 [ 5.52700641e-03 -1.08420217e-19  1.00000000e+00]]
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
透视变换(Inverse Perspective Mapping,简称IPM)是一种将透视图像转换为俯视图像的技术。在透视变换中,远离摄像机的物体会显得更小,而在俯视图像中,物体的大小与其在水平面上的实际大小相对应。使用透视变换可以纠正透视畸变,将透视图像转换为具有匀称比例的俯视图像,从而实现更准确的测量和分析。 在Python中,你可以使用OpenCV库来实现IPM透视变换。下面是实现透视变换的步骤: 1. 确定透视变换的源图像和目标图像的四个关键点。这些点应该组成一个四边形,表示源图像中的一个区域,以及目标图像中的相应区域。 2. 使用cv2.getPerspectiveTransform()函数计算透视变换矩阵。该函数需要输入源图像和目标图像的关键点,然后返回透视变换矩阵。 3. 使用cv2.warpPerspective()函数将源图像进行透视变换。该函数需要输入源图像、透视变换矩阵和目标图像的大小,然后返回透视变换后的图像。 下面是一个实例代码,展示了如何使用Python和OpenCV来进行IPM透视变换: ```python import cv2 import numpy as np # 定义源图像和目标图像的关键点 src_points = np.float32([[x1, y1], [x2, y2], [x3, y3], [x4, y4]]) dst_points = np.float32([[x1, y1], [x2, y1], [x2, y2], [x1, y2]]) # 计算透视变换矩阵 M = cv2.getPerspectiveTransform(src_points, dst_points) # 执行透视变换 result = cv2.warpPerspective(image, M, (width, height)) # 显示结果图像 cv2.imshow("Result", result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 请注意,上述代码中的`x1, y1, x2, y2, x3, y3, x4, y4`是源图像和目标图像的关键点坐标。你需要根据实际情况进行替换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值