当前位置: 代码网 > it编程>游戏开发>ar > opencv warpPerspective透视变换实现原理与过程

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

2024年07月31日 ar 我要评论
opencv warpPerspective透视变换实现原理与过程

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

        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三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com