• 【Python计算机视觉】Python全栈体系(二十四)


    计算机视觉

    第四章 形态变换

    一、仿射变换

    1. 什么是仿射变换

    • 仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够保持图像的平直性和平行性。平直性是指图像经过仿射变换后,直线仍然是直线;平行性是指图像在完成仿射变换后,平行线仍然是平行线。
      在这里插入图片描述

    2. 平移

    • 改变图像的x和y坐标,将所有x坐标的像素增加就是向右平移,减小就是向左平移,将所有y坐标的像素增加就是向下平移,减小就是向上平移
      在这里插入图片描述

    3. 镜像

    • 水平镜像:改变的是每个像素的x坐标,x坐标关于y轴对称
    • 垂直镜像:保持x轴坐标不变,改变它的y坐标
      在这里插入图片描述

    4. 旋转

    在这里插入图片描述

    5. 透视变换

    • 透视变换是将图片投影到一个新的视平面,也称作投影映射。它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x’,y’)空间的映射。
    • 相对于仿射变换,它提供了更大的灵活性,将一个四边形区域映射到另一个四边形区域(不一定是平行四边形),透视变换可用于图像形状校正。
      在这里插入图片描述

    二、算数运算

    1. 图像加法

    在这里插入图片描述

    2. 图像减法

    • 图像减法是找出两幅图像的差异,可以在连续图像中实现消除背景和运动检测
      在这里插入图片描述

    三、图像缩放

    1. 缩放

    在这里插入图片描述

    2. 图像缩小

    • 图像缩小可以通过删除矩阵中的元素来实现,例如:下面的例子进行隔行、隔列删除后,高度、宽度均减小为原来的一半
      在这里插入图片描述

    3. 图像放大

    在这里插入图片描述
    在这里插入图片描述

    • 最邻近插值法放大后有锯齿状

    四、腐蚀与膨胀

    1. 图像腐蚀

    • 腐蚀是最基本的形态学操作之一,它能够将图像的边界点消除,使图像沿着边界向内收缩,也可以将小于指定结构体元素的部分去除。腐蚀用来“收缩”或者“细化”二值图像中的前景,借此实现去除噪声、元素分割等功能。
      在这里插入图片描述

    2. 图像膨胀

    • 图像膨胀是指根据原图像的形状,向外进行扩充。如果图像内两个对象的距离较近,那么在膨胀的过程中,两个对象可能会连通在一起。膨胀操作对填补图像分割后图像内所存在的空白相当有帮助。
      在这里插入图片描述

    3. 图像开运算

    • 开运算进行的操作是先将图像腐蚀,再对腐蚀的结果进行膨胀。开运算可以用于去噪、计数等。
      在这里插入图片描述
    • 开运算可用于取出主题图像之间细小的连接
      在这里插入图片描述

    4. 图像闭运算

    • 闭运算是先膨胀、后腐蚀的运算,它有助于关闭前景物体内部的小孔,或去除物体上的小黑点,还可以将不同的前景图像进行连接。
      在这里插入图片描述
      在这里插入图片描述

    5. 形态学梯度

    • 形态学梯度运算是用图像的膨胀图像减腐蚀图像的操作,该操作可以获取原始图像中前景图像的边缘。
      在这里插入图片描述

    6. 礼帽运算

    • 礼帽运算是用原始图像减去其开运算图像的操作。礼帽运算能够获取图像的噪声信息,或者得到比原始图像的边缘更亮的边缘信息。
      在这里插入图片描述

    7. 黑帽运算

    • 黑帽运算是用闭运算图像减去原始图像的操作。黑帽运算能够获取图像内部的小孔,或前景色中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。
      在这里插入图片描述

    五、图像形态操作

    1. 图像翻转

    # 图像翻转
    import cv2
    
    im = cv2.imread("../data/Linus.png")
    cv2.imshow("im", im)
    
    # 0-垂直镜像
    im_flip0 = cv2.flip(im, 0)
    cv2.imshow("im_flip0", im_flip0)
    
    # 1-水平镜像
    im_flip1 = cv2.flip(im, 1)
    cv2.imshow("im_flip1", im_flip1)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    2. 图像位置变换

    # 图像仿射变换(旋转、平移)
    import numpy as np
    import cv2
    
    
    def translate(im, x, y):
        """
        对图像进行平移变换
        :param im: 原始图像数据
        :param x: 水平方向平移的像素
        :param y: 垂直方向平移的像素
        :return: 返回平移后的图像数据
        """
        h, w = im.shape[:2]  # 取出原图像的高度、宽度
    
        # 定义平移矩阵
        M = np.float32([[1, 0, x],
                        [0, 1, y]])
        # 调用warpAffine函数实现平移变换
        shifted = cv2.warpAffine(im,  # 原始图像
                                 M,  # 平移矩阵
                                 (w, h))  # 输出图像大小
        return shifted
    
    def rotate(im, angle, center=None, scale=1.0):
        """
        图像旋转变换
        :param im: 原始图像
        :param angle: 旋转角度
        :param center: 旋转中心
        :param scale: 缩放比例
        :return: 返回经过旋转后的图像
        """
        h, w = im.shape[:2] # 获取图像高度、宽度
        # 计算旋转中心
        if center is None:
            center = (w / 2, h / 2)
        # 生成旋转矩阵
        M = cv2.getRotationMatrix2D(center, angle, scale)
    
        # 调用warpAffine函数实现旋转变换
        rotated = cv2.warpAffine(im, M, (w, h))
        return rotated
    
    if __name__ == "__main__":
        # 读取原始图像
        im = cv2.imread("../data/Linus.png")
        cv2.imshow("im", im)
    
        # 向下移动50像素
        shifted = translate(im, 0, 50)
        cv2.imshow("shifted_1", shifted)
    
        # 向左移动40像素,向下移动50像素
        shifted = translate(im, -40, 50)
        cv2.imshow("shifted_2", shifted)
    
        # 逆时针旋转45度
        rotated = rotate(im, 45)
        cv2.imshow("rotated_1", rotated)
    
        # 顺时针旋转90度
        rotated = rotate(im, -90)
        cv2.imshow("rotated_2", rotated)
    
        cv2.waitKey()  # 等待用户按某个按键
        cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 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
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    在这里插入图片描述

    3. 图像缩放

    # 图像缩放示例
    import cv2
    im = cv2.imread("../data/Linus.png")
    cv2.imshow("im", im)
    
    h, w = im.shape[:2] # 获取图像高度、宽度
    
    # 缩小
    dst_size = (int(w/2), int(h/2)) # 计算缩放后的图像宽度、高度
    resized = cv2.resize(im, dst_size)
    cv2.imshow("reduce", resized)
    
    # 放大
    dst_size = (200, 300) # 缩放尺寸,宽200,高300
    resized = cv2.resize(im,
                         dst_size,
                         interpolation=cv2.INTER_NEAREST) # 最邻近插值
    cv2.imshow("NEAREST", resized)
    
    resized = cv2.resize(im,
                         dst_size,
                         interpolation=cv2.INTER_LINEAR) # 双线性插值
    cv2.imshow("LINEAR", resized)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 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

    在这里插入图片描述

    4. 图像裁剪

    # 图像裁剪(利用数组切片操作实现)
    import numpy as np
    import cv2
    
    
    # 随机裁剪
    def random_crop(im, w, h):
        # 随机产生裁剪起点的x, y坐标
        start_x = np.random.randint(0, im.shape[1])  # 裁剪起始的x坐标
        start_y = np.random.randint(0, im.shape[0])  # 裁剪起始的y坐标
    
        new_img = im[start_y:start_y + h, start_x:start_x + w]  # 切片
        return new_img
    
    # 中心裁剪
    def center_crop(im, w, h):
        start_x = int(im.shape[1] / 2) - int(w / 2) # 裁剪起始的x坐标
        start_y = int(im.shape[0] / 2) - int(h / 2) # 裁剪起始的y坐标
    
        new_img = im[start_y:start_y + h, start_x:start_x + w]  # 切片
        return new_img
    
    if __name__ == "__main__":
        im = cv2.imread("../data/banana_1.png", 1)
        new_img = random_crop(im, 200, 200)  # 随机裁剪
        cv2.imshow("random_crop", new_img)
    
        new_img2 = center_crop(im, 200, 200)  # 随机裁剪
        cv2.imshow("center_crop", new_img2)
    
        cv2.waitKey()  # 等待用户按某个按键
        cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 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

    在这里插入图片描述

    5. 图像相加

    # 图像相加
    import cv2
    
    a = cv2.imread("../data/lena.jpg", 0)
    b = cv2.imread("../data/lily_square.png", 0)
    
    # 图像直接相加,会导致图像越加越白,越加越亮
    dst1 = cv2.add(a, b)
    cv2.imshow("dst1", dst1)
    
    # 图像按权重相加
    dst2 = cv2.addWeighted(a, 0.6,  # 图像1和权重
                           b, 0.4,  # 图像2和权重
                           0)  # 亮度调节量
    
    cv2.imshow("dst2", dst2)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    6. 图像相减

    # 图像相减
    import cv2
    
    a = cv2.imread("../data/3.png", 0)
    b = cv2.imread("../data/4.png", 0)
    
    dst = cv2.subtract(a, b) # 图像相减
    
    cv2.imshow("a", a)
    cv2.imshow("b", b)
    cv2.imshow("dst", dst)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    7. 图像透视变换

    # 透视变换
    import cv2
    import numpy as np
    
    im = cv2.imread("../data/pers.png")
    rows, cols = im.shape[:2]  # 取出高度、宽度
    print(rows, cols) # 206 184
    cv2.imshow("im", im)
    
    # 指定映射坐标
    pts1 = np.float32([[58, 2], [167, 9], [8, 196], [126, 196]])  # 原坐标点
    pts2 = np.float32([[16, 2], [167, 8], [8, 196], [169, 196]])  # 目标点坐标
    
    # 生成透视变换矩阵
    M = cv2.getPerspectiveTransform(pts1, pts2)
    
    # 执行变换
    dst = cv2.warpPerspective(im,  # 原始图像
                              M,  # 变换矩阵
                              (cols, rows))  # 输出图像大小
    
    cv2.imshow("dst", dst)
    
    # 将矩形变换成平行四边形
    M = cv2.getPerspectiveTransform(pts2, pts1)
    
    # 执行变换
    dst2 = cv2.warpPerspective(im,  # 原始图像
                               M,  # 变换矩阵
                               (cols, rows))  # 输出图像大小
    cv2.imshow("dst2", dst2)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 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

    在这里插入图片描述

    8. 图像腐蚀

    # 图像腐蚀
    import cv2
    import numpy as np
    
    im = cv2.imread("../data/5.png")
    cv2.imshow("im", im)
    
    # 腐蚀
    kernel = np.ones((3, 3), np.uint8)  # 腐蚀核
    erosion = cv2.erode(im,  # 原始图像
                        kernel,  # 腐蚀核
                        iterations=3)  # 迭代次数
    
    cv2.imshow("erosion", erosion)
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    9. 图像膨胀

    # 图像膨胀
    import cv2
    import numpy as np
    
    im = cv2.imread("../data/6.png")
    cv2.imshow("im", im)
    
    # 膨胀
    kernel = np.ones((3, 3), np.uint8)  # 膨胀核
    dilation = cv2.dilate(im,  # 图像
                          kernel,  # 膨胀核
                          iterations=5)  # 迭代次数
    cv2.imshow("dilation", dilation)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    10. 图像开运算

    # 图像开运算
    import cv2
    import numpy as np
    
    im1 = cv2.imread("../data/7.png")
    im2 = cv2.imread("../data/8.png")
    
    # 执行开运算
    k = np.ones((10, 10), np.uint8) # 计算核
    r1 = cv2.morphologyEx(im1, cv2.MORPH_OPEN, k)
    r2 = cv2.morphologyEx(im2, cv2.MORPH_OPEN, k)
    
    cv2.imshow("im1", im1)
    cv2.imshow("im2", im2)
    cv2.imshow("r1", r1)
    cv2.imshow("r2", r2)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    11. 图像闭运算

    # 图像开运算
    import cv2
    import numpy as np
    
    im1 = cv2.imread("../data/9.png")
    im2 = cv2.imread("../data/10.png")
    
    # 执行开运算
    k = np.ones((8, 8), np.uint8) # 计算核
    r1 = cv2.morphologyEx(im1, cv2.MORPH_CLOSE, k, iterations=2)
    r2 = cv2.morphologyEx(im2, cv2.MORPH_CLOSE, k, iterations=2)
    
    cv2.imshow("im1", im1)
    cv2.imshow("im2", im2)
    cv2.imshow("r1", r1)
    cv2.imshow("r2", r2)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    12. 形态学梯度

    # 形态学梯度:膨胀的图像减腐蚀的图像
    import cv2
    import numpy as np
    
    o = cv2.imread("../data/6.png")
    k = np.ones((3, 3), np.uint8)  # 计算核
    r = cv2.morphologyEx(o, cv2.MORPH_GRADIENT, k)  # 计算形态学梯度
    
    cv2.imshow("o", o)
    cv2.imshow("r", r)
    
    cv2.waitKey()  # 等待用户按某个按键
    cv2.destroyAllWindows()  # 销毁所有创建的窗口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

  • 相关阅读:
    【C语言】学数据结构前必学的结构体struct详细
    @Valid与@Validated区别和详细使用及参数注解校验大全
    java调用python文件的几种方式【超细讲解!】
    Vuex的使用
    21天学会C++:Day15----STL简介
    网站为什么要进行内容监控审核?国科云谈网站内容监控的必要性
    软件测试/测试开发丨利用人工智能ChatGPT自动生成架构图
    检测到 #include 错误。请更新 includePath。无法打开 源 文件xxx
    karmada v1.7.0安装指导
    位图BiMap
  • 原文地址:https://blog.csdn.net/sgsgkxkx/article/details/125863854