美文网首页
OpenCV-Python学习(八):图像的几何变换及形态学操作

OpenCV-Python学习(八):图像的几何变换及形态学操作

作者: 星光下的胖子 | 来源:发表于2020-06-25 10:28 被阅读0次

    目录:

    • 1.resize/transpose/flip
    • 2.2.仿射变换(线性变换): 包括 平移、缩放、旋转、倾斜、翻转/镜像
    • 3.透视变换(非线性变换): 一般用于矫正变形的图像
    • 4.形态学操作:膨胀/腐蚀/开/闭/梯度/礼帽/黑帽

    一、resize/transpose/flip

    函数:

        1)图像缩放: resize()函数
            resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)
    
            dsize: 输出图像的大小,如 Size(width, height)。
                若dsize=0,则需指定fx和fy的值,且fx>0,fy>0。
                此时, dsize = Size(round(fx*src.cols), round(fy*src.rows))
                fx=0.5,fy=0.5与dsize=(cols//2, rows//2)效果一样。
            interpolation: 指定插值的方式。图像缩放后,需要重新计算像素,这个参数指定重新计算像素的方式。
                有以下几种插值类型:
                    INTER_LINEAR: 双线性插值(默认)
                    INTER_NEAREST: 最邻近插值
                    INTER_CUBIC: 基于4x4像素邻域内的三次样条插值
                    INTER_LANCZOS4: 基于8x8像素邻域内的Lanczos插值
    
        2)转置: transpose()函数
            transpose(src, dst=None)
    
        3)翻转/镜像: flip()函数
            flip(src, flipCode, dst=None)
    
            flipCode: 控制翻转效果。
                flipcode = 0:绕x轴翻转,即上下颠倒
                flipcode > 0(如1):绕y轴翻转,翻转
                flipcode < 0(如-1):绕x,y轴同时翻转,即上下+左右翻转
    
    1.图片缩放——resize():
    import cv2
    
    img = cv2.imread("image/1.jpg")
    rows, cols, channels = img.shape
    
    # 图片缩放: resize()
    resie_1 = cv2.resize(img, dsize=(cols // 2, rows //2))
    resie_2 = cv2.resize(img, dsize=(0, 0), fx=2, fy=2)
    
    # 几种插值方式:
    # 1.双线性插值(默认)
    linear = cv2.resize(img, dsize=(cols // 2, rows //2), interpolation=cv2.INTER_LINEAR)
    # 2.最邻近插值
    nearest = cv2.resize(img, dsize=(cols //2, rows //2), interpolation=cv2.INTER_NEAREST)
    # 3.基于4x4像素邻域内的三次样条插值
    cubic = cv2.resize(img, dsize=(cols//2, rows // 2), interpolation=cv2.INTER_CUBIC)
    # 4.基于8x8像素邻域内的Lanczos插值
    lanczos = cv2.resize(img, dsize=(cols//2, rows // 2), interpolation=cv2.INTER_LANCZOS4)
    
    cv2.imshow("image", img)
    cv2.imshow("resie_1", resie_1)
    cv2.imshow("resie_2", resie_2)
    cv2.imshow("linear", linear)
    cv2.imshow("nearest", nearest)
    cv2.imshow("cubic", cubic)
    cv2.imshow("lanczos", lanczos)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    2.转置——transpose():
    import cv2
    
    src = cv2.imread("image/1.jpg")
    dst = cv2.transpose(src)
    cv2.imshow("src", src)
    cv2.imshow("dst", dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    3.翻转/镜像——flip():
    import cv2
    
    src = cv2.imread("image/1.jpg")
    # 翻转: flipCode用来控制翻转效果
    dst1 = cv2.flip(src, flipCode=0)  # flipCode=0:绕x轴翻转,即上下颠倒
    dst2 = cv2.flip(src, flipCode=1)  # flipcode>0:绕y轴翻转,翻转
    dst3 = cv2.flip(src, flipCode=-1)  # flipcode<0:绕x,y轴同时翻转,即上下+左右翻转
    
    cv2.imshow("src", src)
    cv2.imshow("dst1", dst1)
    cv2.imshow("dst2", dst2)
    cv2.imshow("dst3", dst3)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    二、仿射变换(线性变换): 包括 平移、缩放、旋转、倾斜、翻转/镜像

    任意一个二维图像,乘以一个仿射矩阵,就能的得到仿射变换后的图像。
    仿射矩阵变换效果如下图所示:

    仿射变换效果图.png

    函数:

        1.调用warpAffine()函数进行仿射变换:
        dst = warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
        参数:
        M: 仿射变换矩阵
        dsize: 指定输出图片的大小
    
        2.对于旋转操作, 一般调用getRotationMatrix2D()函数获取仿射矩阵:
        M = getRotationMatrix2D(center, angle, scale)
        参数:
        center是旋转的中心点;
        angle是旋转角度(正数表示逆时针),如angle=15表示逆时针旋转15度;
        scale标量是缩放因子,0.5表示缩小,2表示放大一倍,-2表示放大一倍后再做(上下+左右)翻转。
    

    示例:

    import cv2
    import numpy
    
    img = cv2.imread("image/2.jpg")
    rows, cols, channels = img.shape
    
    # 1.创建仿射变换矩阵
    # 1)平移
    M1 = numpy.float32([[1, 0, 20], [0, 1, 80]])  # 沿x轴平移+20,沿y轴平移+80
    # 2)缩放
    M2 = numpy.float32([[0.8, 0, 0], [0, 0.5, 0]])  # x轴变为0.8倍,y轴变为0.5倍
    # 3)旋转:调用getRotationMatrix2D()获取仿射矩阵
    M3 = cv2.getRotationMatrix2D((cols//2, rows//2), 15, scale=0.5)  # angle=15表示逆时针旋转15度。scale=0.5表示缩小到原来的一半。
    # 4)倾斜
    M4 = numpy.float32([[1, 0.5, 0], [0, 1, 0]])# 沿x轴倾斜0.5倍
    M5 = numpy.float32([[1, 0, 0], [1, 1, 0]])# 沿y轴倾斜1倍
    # 5)翻转/镜像
    M6 = numpy.float32([[-0.5, 0, cols //2], [0, 0.5, 0]])  # x轴变为0.5倍并绕y转翻转,y轴变为0.5倍,最后沿x轴平移(cols//2)个像素单位
    M7 = numpy.float32([[-1, 0, cols], [0, -1, rows]])  # 绕y转翻转、绕x转翻转,最后沿x轴平移cols个像素单位、沿y轴平移rows个像素单位
    
    # 2.进行仿射变换
    dst1 = cv2.warpAffine(img, M1, dsize=(cols, rows))  # 平移
    dst2 = cv2.warpAffine(img, M2, dsize=(cols, rows))  # 缩放
    dst3 = cv2.warpAffine(img, M3, dsize=(cols, rows))  # 旋转
    dst4 = cv2.warpAffine(img, M4, dsize=(cols * 2, rows * 2))  # 倾斜
    dst5 = cv2.warpAffine(img, M5, dsize=(cols * 2, rows * 2))  # 倾斜
    dst6 = cv2.warpAffine(img, M6, dsize=(cols, rows))  # 翻转/镜像
    dst7 = cv2.warpAffine(img, M7, dsize=(cols, rows))  # 翻转/镜像
    
    cv2.imshow("img pic", img)
    cv2.imshow("dst1 pic", dst1)
    cv2.imshow("dst2 pic", dst2)
    cv2.imshow("dst3 pic", dst3)
    cv2.imshow("dst4 pic", dst4)
    cv2.imshow("dst5 pic", dst5)
    cv2.imshow("dst6 pic", dst6)
    cv2.imshow("dst7 pic", dst7)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    结果如下:

    三、透视变换(非线性变换): 一般用于矫正变形的图像

    函数:

        1.获取透视变换矩阵M:
        M = getPerspectiveTransform(src, dst, solveMethod=None)
        参数:
        src:源图像中四边形顶点的坐标。
        dst:目标图像中对应的四边形顶点的坐标。
    
        2.调用warpPerspective()函数进行透视变换:
        dst = warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)‘
        参数:
        M: 透视变换矩阵
        dsize: 指定输出图片的大小
    

    示例:

    import cv2
    import numpy
    
    src = cv2.imread("image/2.jpg")
    rows, cols, channel = src.shape
    print(cols, rows) # 200 201
    
    # 1.获取透视变换矩阵M: getPerspectiveTransform(src, dst)
    pts1 = numpy.array([[25, 30], [179, 25], [12, 188], [189, 190]], dtype=numpy.float32)
    pts2 = numpy.float32([[0, 0], [200, 0], [0, 200], [200, 200]])
    M = cv2.getPerspectiveTransform(pts1, pts2)
    # 2.进行透视变换: warpPerspective(src, M, dsize)
    dst = cv2.warpPerspective(src, M, dsize=(200, 200))
    
    cv2.imshow("src pic", src)
    cv2.imshow("dst pic", dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    结果如下:

    四、形态学操作:膨胀/腐蚀/开/闭/梯度/礼帽/黑帽

    函数:

        1.构造一个特定形状和大小的结构元素(核),用于形态学操作。
        kernel = getStructuringElement(shape, ksize, anchor=None)
        参数:
        shape: 核的形状。
            MORPH_RECT = 0: 矩形
            MORPH_CROSS = 1: 交叉形
            MORPH_ELLIPSE = 2: 椭圆形
        ksize: 核的结构大小
    
        2.膨胀: 原图部分区域(A)与核(B)进行卷积,求局部最大值,并将局部最大值赋值给指定像素,从而增长高亮区域。
        dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
        3.腐蚀: 与膨胀相反,用局部极小值替换当前像素,从而缩短高亮区域。
        erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    
        4.更多形态学操作
        morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
        参数:
        op: 形态学操作类型。
            cv2.MORPH_DILATE: 膨胀。-->增长高亮部分。
            cv2.MORPH_ERODE: 腐蚀。-->缩短高亮部分。
            cv2.MORPH_GRADIENT: 梯度,(膨胀-腐蚀)。-->提取轮廓。
            cv2.MORPH_OPEN: 开,先腐蚀在膨胀。-->去除噪点。
            cv2.MORPH_CLOSE: 闭,先膨胀再腐蚀。-->填补漏洞。
            cv2.MORPH_TOPHAT: 顶帽/礼帽,(原图-开)。-->获取噪点。
            cv2.MORPH_BLACKHAT: 黑帽,(闭-原图)。-->获取漏洞。
    

    示例:

    import cv2
    import matplotlib.pyplot as plt
    
    img1 = cv2.imread("image/3.jpg")
    img2 = cv2.imread("image/4.jpg")
    
    # 1.获取指定形状和大小的结构元素(核): getStructuringElement(shape, ksize)
    kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(3, 3))  # 矩形
    cross_kernel = cv2.getStructuringElement(shape=cv2.MORPH_CROSS, ksize=(3, 3))  # 交叉形
    ellipse_kernel = cv2.getStructuringElement(shape=cv2.MORPH_ELLIPSE, ksize=(3, 3))  # 椭圆形
    
    # 2.形态学操作
    dilate = cv2.dilate(img1, kernel)  # 膨胀
    erode = cv2.erode(img1, kernel)  # 腐蚀
    morph_dilate = cv2.morphologyEx(img1, cv2.MORPH_DILATE, kernel)  # 膨胀
    morph_erode = cv2.morphologyEx(img1, cv2.MORPH_ERODE, kernel)  # 腐蚀
    morph_gradient = cv2.morphologyEx(img1, cv2.MORPH_GRADIENT, kernel)   # 梯度: 膨胀-腐蚀, 用于提取轮廓
    
    morph_open = cv2.morphologyEx(img2, cv2.MORPH_OPEN, kernel)  # 开: 先腐蚀再膨胀,用于去噪
    morph_close = cv2.morphologyEx(img2, cv2.MORPH_CLOSE, kernel)  # 闭: 先膨胀后腐蚀,用于填补漏洞
    morph_tophat = cv2.morphologyEx(img2, cv2.MORPH_TOPHAT, kernel)  # 顶帽/礼帽: 原图-开,用于获取噪点
    morph_blackhat = cv2.morphologyEx(img2, cv2.MORPH_BLACKHAT, kernel)  # 黑帽: 闭-原图,用于填补漏洞
    
    # 结合matplotlib展示多张图片
    titles = ['Image', 'DILATE', 'ERODE', 'MORPH_DILATE', 'MORPH_ERODE', 'MORPH_GRADIENT']
    images = [img1, dilate, erode, morph_dilate, morph_erode, morph_gradient]
    for i in range(6):
        plt.subplot(2, 3, i + 1)
        plt.imshow(images[i], cmap="gray")
        plt.title(titles[i])
        plt.xticks([])
        plt.yticks([])
    plt.show()
    
    titles = ['Image', 'MORPH_OPEN', 'MORPH_CLOSE', 'MORPH_TOPHAT', 'MORPH_BLACKHAT']
    images = [img2, morph_open, morph_close, morph_tophat, morph_blackhat]
    for i in range(5):
        plt.subplot(2, 3, i + 1)
        plt.imshow(images[i], cmap="gray")
        plt.title(titles[i])
        plt.xticks([])
        plt.yticks([])
    plt.show()
    

    结果如下:

    相关文章

      网友评论

          本文标题:OpenCV-Python学习(八):图像的几何变换及形态学操作

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