美文网首页python
取经之旅第 55 天,Python OpenCV 透视变换前置知

取经之旅第 55 天,Python OpenCV 透视变换前置知

作者: 梦想橡皮擦 | 来源:发表于2021-12-22 08:11 被阅读0次

    Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。本篇博客是这个系列的第 55 篇。
    该系列文章导航参考:https://blog.csdn.net/hihell/category_10688961.html

    学在前面

    正式学习之前,先将上一篇 博客的内容回顾一下,通过一系列的轮廓操作,得到了目标图像的轮廓。

    20210320173715714[1].png

    本篇博客的目标将逐步实现对其进行透视变换。

    获取轮廓的四个顶点坐标

    上篇博客已经获取到了轮廓坐标,但是每个坐标对应的位置是不确定的,需要通过计算将其明确出来。
    轮廓坐标从三维修改为二维

    cv.drawContours(src, [screen_cnt], -1, (0, 0, 255), 2)
    
    print(screen_cnt)
    print(screen_cnt.shape)
    print(screen_cnt.reshape(4, 2))
    

    代码运行效果如下,图片不同得到的数值不同。

    [[[ 30  94]]
     [[ 17 273]]
     [[469 278]]
     [[462 106]]]
    (4, 1, 2)
    [[ 30  94]
     [ 17 273]
     [469 278]
     [462 106]]
    

    坐标转换之后,对应到图片的位置如下图所示。

    20210320174124215[1].png

    一般情况下,我们描述一个矩形区域,在 OpenCV 中,采用的是 左上,右上,右下,左下 顺时针顺序,所以接下来需要对这四个坐标进行转换。

    声明一个函数进行相应的计算工作。

    def change_points(input_points):
        pass
    
    # 函数调用
    change_points(screen_cnt.reshape(4, 2))
    

    计算 4 个点横纵坐标之和

    def change_points(input_points):
        s = input_points.sum(axis=1)
        print(s)
    

    核心用到的是 numpy 中的 sum 函数,注意 axis 轴参数,0 表示竖向,1 表示横向,这里的横向就是该点的横纵坐标之和。

    20210320174903730[1].png 20210320175002826[1].png

    对于一个矩形区域,左上点与右下点分别是横纵坐标之和最小的点与最大的点,基于此,继续完善代码。

    下述代码使用了 np.argmin()np.argmax() 函数,可以通过搜索引擎进行快速学习。

    def change_points(input_points):
        s = input_points.sum(axis=1)
        p1 = input_points[np.argmin(s)]
        p3 = input_points[np.argmax(s)]
        print(p1,p3)
    

    得到的数据如下:

    [[ 30  94]
     [ 17 273]
     [469 278]
     [462 106]]
    [30 94] [469 278]
    

    左下点与右上点的计算方式为,使用 np.diff() 函数,计算横纵坐标之差最小找到右上角的点,横纵坐标之差最大找到左下角的点。对应下图可以辅助理解,左下点 300-100 = 200,右上点 100-400 = -300

    20210320175815245[1].png
    def change_points(input_points):
        s = input_points.sum(axis=1)
        p1 = input_points[np.argmin(s)]
        p3 = input_points[np.argmax(s)]
        print(p1,p3)
    
        diff = np.diff(input_points,axis=1)
        p2 = input_points[np.argmin(diff)]
        p4 = input_points[np.argmax(diff)]
        print(p2,p4)
    

    此时,4 个坐标都已经获取到,最后声明一个空矩阵,赋值之后进行返回。

    def change_points(input_points):
        s = input_points.sum(axis=1)
        p1 = input_points[np.argmin(s)]
        p3 = input_points[np.argmax(s)]
    
        diff = np.diff(input_points, axis=1)
        p2 = input_points[np.argmin(diff)]
        p4 = input_points[np.argmax(diff)]
    
        # 声明一个所有元素都为 0 的矩阵
        rect = np.zeros((4, 2), dtype="float32")
        rect[0] = p1
        rect[1] = p2
        rect[2] = p3
        rect[3] = p4
        print(rect)
        return rect
    change_points(screen_cnt.reshape(4, 2))
    

    坐标数值与图片对应位置如下:


    20210320180718263[1].png

    橡皮擦的小节

    希望今天的 1 个小时(貌似不太够)你有所收获,我们下篇博客见~

    相关文章

      网友评论

        本文标题:取经之旅第 55 天,Python OpenCV 透视变换前置知

        本文链接:https://www.haomeiwen.com/subject/qexqqrtx.html