Opencv实现透视形变

小白学视觉

共 946字,需浏览 2分钟

 · 2022-01-24

点击上方小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

计算机视觉现在很流行,世界各地的人们都在从事某种形式的基于深度学习的计算机视觉项目。但在深度学习出现之前,图像处理技术已被用来处理和转换图像,以获得有助于我们完成任务的见解。今天,让我们看看如何实现一种简单而有用的技术,即透视投影来扭曲图像。


那么扭曲图像是什么意思?我可以用很多花哨的词和技术术语来解释它。但是,展示最终结果很容易,这样我们就可以通过观察来学习。


    

基础图像——主题图像——扭曲的输出

所以基本上,我们需要拍摄一个图像并剪切它以使其适合任何所需形状的画布。请注意,反过来也是可能的。现在,这已经不成问题了,让我们就来看看如何使用 OpenCV 和 Python 来实现这一点。


在进入代码的主要部分之前,我们必须首先导入必要的库。

import cv2import numpy as np

现在,让我们按如下方式读取基本图像和主题图像。

base_image = cv2.imread('base_img.jpg')base_image_copy = base_image.copy()subject_image = cv2.imread('subject.jpg')

   

                           基本图像(左)——主体图像(右)


初始化一个数组来存储我们想要覆盖主题图像的 4 个角的坐标,我们可以使用setMouseCallback()函数手动选择这 4 个点,如下所示。

def click_event(event, x, y, flags, params):    if event == cv2.EVENT_LBUTTONDOWN:        cv2.circle(base_image_copy, (x, y), 4, (0, 0, 255), -1)        points.append([x, y])        if len(points) <= 4:            cv2.imshow('image', base_image_copy)points = []base_image = cv2.imread('base_img.jpg')base_image_copy = base_image.copy()subject_image = cv2.imread('subject.jpg')
cv2.imshow('image', base_image_copy)cv2.setMouseCallback('image', click_event)cv2.waitKey(0)cv2.destroyAllWindows()

在上面给出的代码片段中,我们定义了一个名为click_event()的函数,并将其作为参数传递给setMouseCallback()函数。使用这种方法,我们将首先显示基础图像,然后我们可以手动选择图像中的四个点作为目标。我们的主题图像会扭曲到这个目标上,按下鼠标左键时记录坐标,这些存储在我们之前初始化的点数组中。选定的点以红点突出显示,如下所示。

选择角点

众所周知,我们每个人都可以按任意顺序选择 4 个点。因此需要在所选点之间保持恒定的排序。我选择以顺时针方式对点进行排序,即从左上到右上,再到右下然后到左下,这是通过如下所示的sort_pts()方法实现的。我们使用以下事实:x 和 y 坐标的总和在左上角最小,在右下角最大。同样,它们之间的差异在右上角最小,在左下角最大。请记住,对于图像,原点位于图像的左上角。

def sort_pts(points):    sorted_pts = np.zeros((4, 2), dtype="float32")    s = np.sum(points, axis=1)    sorted_pts[0] = points[np.argmin(s)]    sorted_pts[2] = points[np.argmax(s)]
diff = np.diff(points, axis=1) sorted_pts[1] = points[np.argmin(diff)] sorted_pts[3] = points[np.argmax(diff)]
return sorted_ptssorted_pts = sort_pts(points)

对点进行排序后,让我们用它们来计算变换矩阵。我们创建一个名为“pts1”的 numpy 数组,它保存了主题图像的四个角的坐标。同样,我们创建一个名为“pts2”的列表,其中包含已排序的点。“pts1”的坐标顺序应该与“pts2”坐标的顺序相匹配。

h_base, w_base, c_base = base_image.shapeh_subject, w_subject = subject_image.shape[:2]
pts1 = np.float32([[0, 0], [w_subject, 0], [w_subject, h_subject], [0, h_subject]])pts2 = np.float32(sorted_pts)

现在我们获得了扭曲对象图像所需的变换矩阵。这是使用函数cv2.getPerspectiveTransform() 获得的。由于我们希望以适合我们在基础图像中选择的框的方式变化主题图像,因此“ src ”应为“ pts1 ”,“ dst ”应为“ pts2 ”。生成的图像的大小可以指定为元组。我们确保生成的图像具有基本图像的尺寸。使用生成的矩阵,我们可以使用cv2.warpPerspective()方法扭曲图像,如给定的代码片段所示。

transformation_matrix = cv2.getPerspectiveTransform(pts1, pts2)
warped_img = cv2.warpPerspective(subject_image, transformation_matrix, (w_base, h_base))cv2.imshow('Warped Image', warped_img)

变形的图像看起来像这样:

变形的图像

下一步是创建一个蒙版,我们为其创建一个具有基本图像形状的空白图像。

mask = np.zeros(base_image.shape, dtype=np.uint8)
初始蒙版

在这个空白蒙版上,我们绘制一个具有由“ sorted_pts ”指定的角的多边形,并使用cv2.fillConvexPoly()方法将其填充为白色,生成的蒙版将如下所示。

roi_corners = np.int32(sorted_pts)
cv2.fillConvexPoly(mask, roi_corners, (255, 255, 255))
填充蒙版

现在我们使用cv2.bitwise_not()方法反转蒙版颜色。

mask = cv2.bitwise_not(mask)
倒置蒙版

现在我们使用cv2.bitwise_and()方法获取蒙版和基础图像并执行按位与运算。

masked_image = cv2.bitwise_and(base_image, mask)

这将为我们提供如下所示的图像。我们可以看到单独放置对象图像的区域是黑色的。

蒙面基础图像

最后一步是使用cv2.bitwise_or()方法获取变形图像和蒙版图像并执行按位或运算,这将生成我们想要完成的融合图像。

output = cv2.bitwise_or(warped_img, masked_image)cv2.imshow('Fused Image', output)cv2.imwrite('Final_Output.png', output)cv2.waitKey(0)cv2.destroyAllWindows()

我们做到了!我们已经成功地将一张图片叠加到另一张图片上。

融合图像

这是透视变换的一个非常简单的用例。当我们跟踪框架中物体/人物的运动时,可以使用它来生成区域的鸟瞰图。



Github代码连接:

https://github.com/GSNCodes/Image_Overlaying_Using_Perspective_Transform




下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲
小白学视觉公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲
小白学视觉公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群


欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~


浏览 25
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报