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

本文详细介绍了计算机视觉中的形态变换,包括仿射变换(平移、旋转、镜像、透视)、算数运算(加减法)、图像缩放、腐蚀膨胀及开闭运算,以及翻转、裁剪、相加减和透视变换等实例。这些技术在图像处理中具有广泛应用,如图像校正、特征提取和图像分析。
摘要由CSDN通过智能技术生成

计算机视觉

第四章 形态变换

一、仿射变换

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

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()  # 销毁所有创建的窗口

在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬小帽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值