opencv warpPerspective透视变换实现原理与过程

9 篇文章 0 订阅
5 篇文章 0 订阅

【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。

        cv2.warpPerspective函数是OpenCV库中用于执行透视变换的函数之一。它可以将图像从一个透视投影转换为另一个透视投影,实现图像的旋转、缩放、平移等操作。该操作可表示为:

DST = M * SRC

        上式中SRC表示原图像,DST表示变换后图像,M表示透视变换矩阵(3x3)。

1 cv2.warpPerspective

        cv2.warpPerspective函数在OpenCV中用于执行透视变换,其计算过程和各个参数如下所示:

1.1 计算过程

        (1)定义目标图像的大小和数据类型(dtype)。

        (2)计算透视变换矩阵(3x3矩阵),可以通过cv2.getPerspectiveTransform函数获得。

        (3)应用透视变换矩阵到源图像上的每个像素,计算其在目标图像中的位置。

        (4)根据这个位置,使用插值方法估算目标图像中的像素值。

        在第三步中,其实现方式实际是依据M’ * DST = SRC,即根据目标尺寸计算其在源图中对应位置,然后获取原图相应位置的像素值。这里M’表示M的逆矩阵。

        1.2 参数说明

        src: 源图像,即待进行透视变换的图像。

        M: 变换矩阵,即3x3的透视变换矩阵。

        dsize: 目标图像的大小,以元组形式表示,例如(width, height)。

        flags: 插值方法的标志,用于指定插值方法,默认为cv2.INTER_LINEAR。

        borderMode: 边界模式,用于指定超出边界的像素处理方式,默认为cv2.BORDER_CONSTANT。

        borderValue: 当边界模式为cv2.BORDER_CONSTANT时,用于指定边界像素的值,默认为0。

        1.3 返回值

        dst: 目标图像,即经过透视变换后的图像。

2 示例程序

        示例程序如下所示。

import cv2
import numpy as np

if __name__ == '__main__':
    # 生成输入图像
    h, w = 200, 300  # 图像大小
    origin_image = np.zeros((h, w), dtype=np.uint8)
    pts = np.array([[50, 50], [100, 160], [250, 100]], np.int32)
    pts = pts.reshape((-1, 1, 2))
    origin_image = cv2.fillConvexPoly(origin_image, pts, 255, 100)
    # 透视变换矩阵
    M = np.array([[0.99, -0.11, 80], [-0.11, 0.99, 30], [0, 0, 1]])
    # opencv透视变换
    dst_opencv = cv2.warpPerspective(origin_image.copy(), M, (w, h))
    # 显示原始图像和经过透视变换后的图像
    cv2.imshow('original', origin_image)
    cv2.imshow('opencv', dst_opencv)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

        示例程序的原始图像和变换后图像如下所示。

3 自定义验证程序mdst

        基于公式验证M’ * DST = SRC变换过程,程序如下所示。

import cv2
import numpy as np


# warp_perspective验证,M' * DST = SRC
def m_dst(src, M, dsize):
    M = np.linalg.inv(M) # 求逆矩阵
    dst = np.zeros((dsize[1], dsize[0]), dtype=np.uint8)
    pos = np.array(np.meshgrid(range(dsize[0]), range(dsize[1]))).T.reshape(-1, 2)
    dpos = np.hstack((pos, np.ones((pos.shape[0], 1)))).T
    spos = M @ dpos
    spos = spos / spos[2, :]
    spos = spos.astype(np.int64).T[:, :2]
    mask = np.where((spos[:, 0] < dsize[0]) & (spos[:, 0] >= 0) & (spos[:, 1] < dsize[1]) & (spos[:, 1] >= 0))
    spos = spos[mask]
    dpos = pos[mask]
    dst[dpos[:, 1], dpos[:, 0]] = src[spos[:, 1], spos[:, 0]]
    return dst


if __name__ == '__main__':
    # 生成输入图像
    h, w = 200, 300  # 图像大小
    origin_image = np.zeros((h, w), dtype=np.uint8)
    pts = np.array([[50, 50], [100, 160], [250, 100]], np.int32)
    pts = pts.reshape((-1, 1, 2))
    origin_image = cv2.fillConvexPoly(origin_image, pts, 255, 100)
    # 透视变换矩阵
    M = np.array([[0.99, -0.11, 80], [-0.11, 0.99, 30], [0, 0, 1]])
    # M' * DST = SRC
    dst_mdst = m_dst(origin_image, M, (w, h))
    # 显示原始图像和经过透视变换后的图像
    cv2.imshow('original', origin_image)
    cv2.imshow('mdst', dst_mdst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

        原始图像和变换后图像如下所示。

4 自定义验证程序msrc

        基于公式验证DST = M * SRC变换过程,程序如下所示。

import cv2
import numpy as np


# warp_perspective验证,DST = M * SRC
def m_src(src, M, dsize):
    dst = np.zeros((dsize[1], dsize[0]), np.uint8)
    pos = np.where(src > 0)
    pos = np.vstack((pos[1], pos[0], np.ones_like(pos[0])))
    pos = M @ pos
    pos = pos / pos[2, :]
    pos = pos.astype(np.int64).T[:, :2]
    pos = pos[np.where((pos[:, 0]<dsize[0]) & (pos[:, 0]>=0) & (pos[:, 1]<dsize[1]) & (pos[:, 1]>=0))]
    dst[pos[:, 1], pos[:, 0]] = 255
    return dst

if __name__ == '__main__':
    # 生成输入图像
    h, w = 200, 300  # 图像大小
    origin_image = np.zeros((h, w), dtype=np.uint8)
    pts = np.array([[50, 50], [100, 160], [250, 100]], np.int32)
    pts = pts.reshape((-1, 1, 2))
    origin_image = cv2.fillConvexPoly(origin_image, pts, 255, 100)
    # 透视变换矩阵
    M = np.array([[0.99, -0.11, 80], [-0.11, 0.99, 30], [0, 0, 1]])
    # M' * DST = SRC
    dst_msrc = m_src(origin_image, M, (w, h))
    # 显示原始图像和经过透视变换后的图像
    cv2.imshow('original', origin_image)
    cv2.imshow('msrc', dst_msrc)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

        原始图像和变换后图像如下所示。

5 注意事项

        (1)自定义验证程序mdst和msrc未进行插值,仅仅实现了透视变换过程,可以明显看到边缘效果不如opencv版本。

        (2)mdst和msrc正常情况下结果趋向阈值,但是由于程序中存在一个取整的近似操作,所以二者所得结果不完全相同。在部分情况下,msrc经变换后会出现大量重叠,分辨率下降,效果差于mdst方法。

【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。
  

更多python与C++技巧、三维算法、深度学习算法总结、大模型请关注我的博客,欢迎讨论与交流:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。Python三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。

  • 37
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding的叶子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值