• 《数字图像处理-OpenCV/Python》连载(44)图像的投影变换


    《数字图像处理-OpenCV/Python》连载(44)图像的投影变换


    本书京东优惠购书链接:https://item.jd.com/14098452.html
    本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html

    在这里插入图片描述


    第 6 章 图像的几何变换


    几何变换分为等距变换、相似变换、仿射变换和投影变换,是指对图像的位置、大小、形状和投影进行变换,将图像从原始平面投影到新的视平面。OpenCV图像的几何变换,本质上是将一个多维数组通过映射关系转换为另一个多维数组。


    本章内容概要

    • 介绍仿射变换,学习使用仿射变换矩阵实现图像的仿射变换。
    • 学习使用函数实现图像的平移、缩放、旋转、翻转和斜切。
    • 介绍投影变换,学习使用投影变换矩阵实现图像的投影变换。
    • 介绍图像的重映射,学习使用映射函数实现图像的自定义变换和动态变换。

    6.6 图像的投影变换

    透视变换(Perspective Transformation)是OpenCV中常用的投影变换,是指将图像投影到一个新的视平面。投影变换的特点是原始图像中的平行关系和比例关系都可以改变,但图像中的直线在投影变换后仍然能保持直线。
    投影变换可以通过对三维空间中的物体旋转进行校正,主要用于图像拼接和校正透视投影导致的图像失真。
    投影变换的方法是在原始图像上确定不共线的4个点,给定这4个点在变换图像中的位置,就确定了一个投影变换,其变换关系可以由如下的3×3矩阵来描述。

    [ x ~ y ~ z ~ ] = M P [ x y z ] , M P = [ M 11 M 12 M 13 M 21 M 22 M 23 M 31 M 32 M 33 ]

    [x~y~z~]" role="presentation" style="position: relative;">[x~y~z~]
    = M_P
    [xyz]" role="presentation" style="position: relative;">[xyz]
    ,\hspace{1em} M_P=
    [M11M12M13M21M22M23M31M32M33]" role="presentation" style="position: relative;">[M11M12M13M21M22M23M31M32M33]
    x~y~z~ =MP xyz ,MP= M11M21M31M12M22M32M13M23M33

    仿射变换是在二维平面进行变换的,而投影变换是在三维坐标系进行变换的。仿射变换是3点变换,投影变换是4点变换。比较仿射变换与投影变换的描述公式,仿射变换可以被视为z轴不变的透视变换。

    在OpenCV中,先由函数cv.getPerspectiveTransform计算投影变换矩阵 M P M_P MP,再由函数cv.warpPerspective根据投影变换矩阵 M P M_P MP 计算得到投影变换图像。

    函数cv.getPerspectiveTransform能根据图像中不共线的4个点在变换前后的对应位置坐标,求解得到投影变换矩阵 M P M_P MP


    函数原型

    cv.getPerspectiveTransform(src, dst[,solveMethod]) → MP

    参数说明

    • src:原始图像中不共线4个点的坐标,是形状为(4,2)的Numpy数组。
    • dst:投影变换图像中对应的不共线4个点的坐标,是形状为(4,2)的Numpy数组。
    • solveMethod:矩阵分解方法。
      • DECOMP_LU:选择最佳轴的高斯消元法,默认方法。
      • DECOMP_SVD:奇异值分解(SVD)方法。
      • DECOMP_EIG:特征值分解方法,必须与src对称。
      • DECOMP_CHOLESKY:Cholesky LLT分解方法。
      • DECOMP_QR:正交三角(QR)分解方法。
      • DECOMP_NORMAL:使用正则方程,与前述方法联合使用。
    • MP:投影变换矩阵,是形状为(3,3)、类型为np.float32的Numpy数组。

    注意问题

    • (1)虽然参数src、dst通常表示输入、输出图像,但在函数cv.getPerspectiveTransform中是指原始图像与变换图像中不共线的4个点,也被称为四边形的顶点。
    • (2) 参数src、dst是形状为(4,2)的Numpy数组,数值是图像中4个顶点的坐标(x,y)。

    函数cv.warpPerspective可通过投影变换矩阵计算投影变换图像。

    函数原型

    cv.warpPerspective (src, M, dsize[, dst, flags, borderMode, borderValue]) → dst

    由投影变换矩阵M计算投影变换图像的公式为

    参数说明

    • src:原始图像,是Numpy数组。
    • dst:投影变换输出图像,类型与src相同,图像尺寸由参数dsize确定。
    • M:投影变换矩阵,是形状为(3,3)、类型为np.float32的Numpy数组。
    • dsize:输出图像大小,格式为元组(w,h)。
    • flags:插值方法与逆变换标志,可选项。
      • INTER_LINEAR:双线性插值,默认方法。
      • INTER_NEAREST:最近邻插值。
      • WARP_INVERSE_MAP:逆变换标志。
    • borderMode:边界扩充方法,可选项,默认为cv.BORDER_CONSTANT。
    • borderValue:边界填充值,可选项,默认值为0,表示黑色填充。

    注意问题

    • (1) 输出图像大小dsize的格式为(w,h),与OpenCV中图像形状(h,w)的顺序相反。
    • (2) 通过函数cv.warpPerspective计算投影变换,投影变换矩阵M的形状为(3,3),数据类型必须是np.float32。
    • (3) 当flags设为WARP_INVERSE_MAP时,先由投影变换矩阵计算逆投影变换矩阵,再计算输入图像的逆投影变换图像。

    【例程0606】基于投影变换实现图像校正

    手机或相机拍摄的照片,通常都存在投影变形。本例程通过投影变换实现图像校正。

    先用鼠标在图像中依次选取矩形的4个顶点,获取4个顶点的坐标,再根据长宽比计算4个顶点在投影变换后的坐标,进行投影变换,就可以实现图像校正。


    # 【0606】基于投影变换实现图像校正
    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    
    def onMouseAction(event, x, y, flags, param):  # 鼠标交互 (单击选点,右击完成)
        setpoint = (x, y)
        if event == cv.EVENT_LBUTTONDOWN:  # 单击
            pts.append(setpoint)  # 选中一个多边形顶点
            print("选择顶点 {}:{}".format(len(pts), setpoint))
    
    if __name__ == '__main__':
        img = cv.imread("../images/Fig0602.png")  # 读取彩色图像(BGR)
        imgCopy = img.copy()
        height, width = img.shape[:2]
    
        # 鼠标交互从输入图像选择 4 个顶点
        print("单击左键选择 4 个顶点 (左上-左下-右下-右上):")
        pts = []  # 初始化 ROI 顶点坐标集合
        status = True  # 进入绘图状态
        cv.namedWindow('origin')  # 创建图像显示窗口
        cv.setMouseCallback('origin', onMouseAction, status)  # 绑定回调函数
        while True:
            if len(pts) > 0:
                cv.circle(imgCopy, pts[-1], 5, (0,0,255), -1)  # 绘制最近的一个顶点
            if len(pts) > 1:
                cv.line(imgCopy, pts[-1], pts[-2], (255, 0, 0), 2)  # 绘制最近的一段线段
            if len(pts) == 4:  # 已有 4个顶点,结束绘制
                cv.line(imgCopy, pts[0], pts[-1], (255,0,0), 2)  # 绘制最后的一段线段
                cv.imshow('origin', imgCopy)
                cv.waitKey(1000)
                break
            cv.imshow('origin', imgCopy)
            cv.waitKey(100)
        cv.destroyAllWindows()  # 释放图像窗口
        ptsSrc = np.array(pts)  # 列表转换为 (4,2),Numpy 数组
        print(ptsSrc)
    
        # 计算投影变换矩阵 MP
        ptsSrc = np.float32(pts)  # 列表转换为Numpy数组,图像4个顶点坐标为 (x,y)
        x1, y1, x2, y2 = int(0.1*width), int(0.1*height), int(0.9*width), int(0.9*height)
        ptsDst = np.float32([[x1,y1], [x1,y2], [x2,y2], [x2,y1]])  # 投影变换后的 4 个顶点坐标
        MP = cv.getPerspectiveTransform(ptsSrc, ptsDst)
    
        # 投影变换
        dsize = (450, 400)  # 输出图像尺寸为 (w, h)
        perspect = cv.warpPerspective(img, MP, dsize, borderValue=(255,255,255))  # 投影变换
        print(img.shape, ptsSrc.shape, ptsDst.shape)
    
        plt.figure(figsize=(9, 3.4))
        plt.subplot(131), plt.axis('off'), plt.title("1.Original")
        plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
        plt.subplot(132), plt.axis('off'), plt.title("2.Selected vertex")
        plt.imshow(cv.cvtColor(imgCopy, cv.COLOR_BGR2RGB))
        plt.subplot(133), plt.axis('off'), plt.title("3.Perspective correction")
        plt.imshow(cv.cvtColor(perspect, cv.COLOR_BGR2RGB))
        plt.tight_layout()
        plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    程序说明:
    (1) 本例程设置了回调函数,通过鼠标交互从输入图像选择了4个顶点。鼠标交互操作的使用方法详见4.9节。
    (2) 投影变换后4个顶点的坐标是用户设定的,可以根据需要修改。
    (3) 基于投影变换实现图像校正的运行结果如图6-6所示,图6-6(1)所示为原始图像,图6-6(2)所示为用鼠标在原始图像上选定棋盘的4个顶点,图6-6(3)所示为投影变换后的图像。可以看出,原始图像中透视拍照的倾斜棋盘被校正为矩形。


    在这里插入图片描述

    *图6-6 图像的投影变换


    版权声明:
    youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/134487182)
    Copyright 2023 youcans, XUPT
    Crated:2023-11-20

    欢迎关注本书CSDN独家连载专栏
    《数字图像处理-OpenCV/Python》连载: https://blog.csdn.net/youcans/category_12418787.html

  • 相关阅读:
    找x。。。
    PCL直通滤波和统计滤波算法
    开源框架简介
    NodeMCU ESP8266 的PWM波形输出教程(图文并茂)
    【Go 编程实践】从零到一:创建、测试并发布自己的 Go 库
    Web前端——用CSS的常用样式制作一个炫酷的按钮
    【项目测试报告】博客系统 + 在线聊天室
    深度学习数据集的文本制作和读取
    Vue系列之数组更新检测
    【JavaEE初阶】计算机是如何工作的
  • 原文地址:https://blog.csdn.net/youcans/article/details/134487182