• 三、图片的几何变换


    一、图片缩放

    1 - 等比缩放

    # 1 load 2 info 3 resize 4 check
    import cv2
    
    img = cv2.imread('image0.jpg', 1)
    imgInfo = img.shape
    print(imgInfo)
    height = imgInfo[0]
    width = imgInfo[1]
    mode = imgInfo[2] # 图片的颜色组成方式,3表示1个像素点由3个基本颜色组成
    # 1 放大 缩小 2 等比例 非等比例 2:3
    dstHeight = int(height * 0.5)
    dstWidth = int(width * 0.5)
    # 最近临域插值、双线性插值、像素关系重采样、立方插值
    # 默认是:双线性插值
    dst = cv2.resize(img, (dstWidth, dstHeight))
    cv2.imshow('image', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    2 - 最近领域插值

    • 最近领域插值原理
      • 假设我们有1个源图片src,大小为1020,我们希望缩放成目标图片dst,大小为510
      • 我们知道,目标图片dst上的每一个点都是来源于源图片src,例如dst的(1,2)来源于src(2,4)
      • 拿x坐标举例,dst的x=1,y=2的像素点,在源图src的计算公式为
        • newX = x*(src行 / dst行)=1 * (10 / 5)=2
        • newX = y*(src列 / dst列)=2 * (20 / 10)=4
      • 上面的计算都是整数的计算,如果计算结果为12.3,那么使用最近领域插值,就会使用12这个坐标的像素,这就是最近领域插值的算法
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    imgInfo = img.shape
    height = imgInfo[0]
    width = imgInfo[1]
    dstHeight = int(height / 2)
    dstWidth = int(width / 2)
    # 使用np创建空白模板
    dstImage = np.zeros((dstHeight, dstWidth, 3), np.uint8)  # 0-255
    for i in range(0, dstHeight):  # 行
        for j in range(0, dstWidth):  # 列
            iNew = int(i * (height * 1.0 / dstHeight))
            jNew = int(j * (width * 1.0 / dstWidth))
            dstImage[i, j] = img[iNew, jNew]
    cv2.imshow('dst', dstImage)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    3 - 双线性插值

    • 双线性插值原理
      • m(15,22)、n(15,23)、j(16,22)、k(16,23)代表的是4个像素点的坐标
      • 假设经过计算出来的结果是(15.2,22.3),这个点在源图像上实际上是不存在的
      • 按最近领域插值法的结果是(15,22)
      • 双线性插值计算,会使用X橙色方向的投影,和Y绿色方向的投影
        • 此时投影出交叉的4个点A1(15.2,22),A2(15.2,23),B1(15,22.3),B2(16,22.3)
        • A1距离m(15,22)是0.2,距离j(16,22)是0.8,可以使用权重表示分别是20%和80%
        • 同理B1距离m(15,22)是0.3=30%,距离n(15,23)是0.7=70%
        • A1 = m * 20% + j * 80%,A2 = n * 20% + k * 80%
        • B1 = m * 30% +n * 70%,B2 = j * 30% + k * 70%
        • 以上分析得出,最终坐标计算公式
          • 方法1:最终点 T = A1 30% + A2 70%
          • 方法2:最终点 T = B1 20% + B2 80%
            在这里插入图片描述

    4 - 矩阵缩放

    • 矩阵缩放原理
      • 2行3列矩阵:[[A1 A2 B1],[A3 A4 B2]]
      • 我们将这个2行3列的矩阵拆分成2个矩阵
        • 2行2列矩阵:[[A1 A2],[A3 A4]]
        • 2行1列矩阵:[[B1],[B2]]
      • 那么新的坐标计算公式为:
        • newX = A1x + A2y+B1
        • newY = A3x +A4y+B2
      • 例如:B1,B2偏移为0,图片缩放0.5,那么newX = x * 0.5
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    cv2.imshow('src', img)
    imgInfo = img.shape
    height = imgInfo[0]
    width = imgInfo[1]
    matScale = np.float32([[0.5, 0, 0], [0, 0.5, 0]])
    dst = cv2.warpAffine(img, matScale, (int(width / 2), int(height / 2)))
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    二、图片剪切与位移

    1 - 图片剪切

    • 需求:剪切原图片:x从100到200,y从100-300
    import cv2
    
    img = cv2.imread('image0.jpg', 1)
    dst = img[100:200, 100:300]
    cv2.imshow('image', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    2 - 图片位移

    • 图片向右位移100个像素
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    cv2.imshow('src', img)
    imgInfo = img.shape
    dst = np.zeros(img.shape, np.uint8)
    height = imgInfo[0]
    width = imgInfo[1]
    for i in range(0, height):
        for j in range(0, width - 100):
            dst[i, j + 100] = img[i, j]
    cv2.imshow('image', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    • 图片向右位移100像素,向下位移200像素
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    cv2.imshow('src', img)
    imgInfo = img.shape
    height = imgInfo[0]
    width = imgInfo[1]
    # 偏移矩阵
    matShift = np.float32([[1, 0, 100], [0, 1, 200]])  # 2行3列
    dst = cv2.warpAffine(img, matShift, (height, width))
    # 移位 矩阵
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    三、图片镜像

    • 将原始的图片进行上下翻转:上半部分为原图,下半部分为翻转的镜像图
      • 创建一个足够大的画板,宽度跟原图像相同,高度为原图像的2倍
      • 将图像分别从前向后,从后向前绘制
      • 绘制中心分割线
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    cv2.imshow('src', img)
    imgInfo = img.shape
    height = imgInfo[0]
    width = imgInfo[1]
    deep = imgInfo[2]
    newImgInfo = (height * 2, width, deep)
    dst = np.zeros(newImgInfo, np.uint8)  # uint8
    for i in range(0, height):
        for j in range(0, width):
            dst[i, j] = img[i, j]
            # x y = 2*h - y -1
            dst[height * 2 - i - 1, j] = img[i, j]
    # 分割线
    for i in range(0, width):
        dst[height, i] = (0, 0, 255)  # BGR
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    四、图片仿射变换

    • 图片仿射原理
      • 前提:我们知道2个点可以确定1条线,3个点可以确定1个唯一的平面
      • 图片仿射就是将原图片中的3个点(左上角、左下角、右上角),隐射到新图片的3个点上,这样就实现了图片的仿射变换
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    cv2.imshow('src', img)
    imgInfo = img.shape
    height = imgInfo[0]
    width = imgInfo[1]
    # src 3->dst 3 (左上角 左下角 右上角)
    matSrc = np.float32([[0, 0], [0, height - 1], [width - 1, 0]])
    matDst = np.float32([[50, 50], [300, height - 200], [width - 300, 100]])
    # 获得矩阵组合
    matAffine = cv2.getAffineTransform(matSrc, matDst)  # mat 1 src 2 dst
    dst = cv2.warpAffine(img, matAffine, (width, height))
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    五、图片旋转

    • 缩放系数为0.5的情况
    import cv2
    import numpy as np
    
    img = cv2.imread('image0.jpg', 1)
    cv2.imshow('src', img)
    imgInfo = img.shape
    height = imgInfo[0]
    width = imgInfo[1]
    # 旋转矩阵:2*3
    # getRotationMatrix2D:参数1 -> 旋转的中心点坐标,参数2 -> 旋转的角度,参数3 -> 缩放的系数
    matRotate = cv2.getRotationMatrix2D((height * 0.5, width * 0.5), 45, 0.5)
    # 100*100 25
    dst = cv2.warpAffine(img, matRotate, (height, width))
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    • 缩放系数为1.0的情况:我们可以看到缩放的系数设置可能会导致图片超出范围
      在这里插入图片描述
  • 相关阅读:
    MyBatis 事务源码分析
    Kubernetes(k8s)安装NFS动态供给存储类并安装KubeSphere
    ardupilot 日志分析《xKF1信息》
    汽车以太网IOP测试新利器
    高性能MySQL实战第11讲:如何做到MySQL高扩展性?
    vue+elementUi——实现层叠轮播图——技能提升
    信钰证券:pb指标代表什么意思?
    LVS集群
    『Java安全』XStream 1.4.15反序列化漏洞CVE-2021-21345复现与浅析
    Java 是否应该使用通配符导入( wildcard imports)
  • 原文地址:https://blog.csdn.net/qq23001186/article/details/127968231