【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。
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三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。
发表评论