• 计算机视觉之几何变换(实现图片缩放、剪切、移位、镜像、仿射变换、旋转等功能)


    1.图片的缩放

    图片是由许多基本的像素点组成的,一般来说彩色图像中的像素点由三个数值组成,分别是蓝色分量、红色分量和绿色分量。

    图片缩放分为:

    1. 普通的缩放,即确定下缩放后的尺寸大小,再进行缩放。
    2. 等比例缩放,即确定一个比例系数,长宽都乘以一个相同的比例系数,实现等比例缩放。

    一般来说,图片的缩放方法有:

    1. 最近临域插值
    2. 双线性插值(默认情况)
    3. 像素关系重采样
    4. 立方插值

    下面简单实现等比例缩放,用最近领域插值方法实现,测试代码如下:

     1 # encoding:utf-8
     2 # 基本实现步骤:
     3 # 1 load 读取图片
     4 # 2 info 获取图片信息
     5 # 3 resize 实现图片缩放即改变图片大小
     6 # 4 check 展示操作后的图像
     7 import cv2
     8 img = cv2.imread('image0.jpg', 1)
     9 # 图片的大小
    10 imgInfo = img.shape
    11 print(imgInfo)
    12 height = imgInfo[0]
    13 width = imgInfo[1]
    14 mode = imgInfo[2]  # 为3 表示一个像素点由三个数值组成
    15 cv2.imshow('src', img)
    16 # 1 放大 缩小
    17 # 2 等比例缩放 宽高比不变即为等比例缩放
    18 # 等比例缩放 长宽乘以一个相同的系数
    19 dstHeight = int(height*0.5)
    20 dstWidth = int(width*0.5)
    21 # 非等比例缩放
    22 # dstHeight = 500
    23 # dstWidth = 500
    24 # 缩放方法:最近临域插值 双线性插值(默认情况) 像素关系重采样 立方插值
    25 dst = cv2.resize(img, (dstWidth, dstHeight))
    26 cv2.imshow('image', dst)
    27 cv2.waitKey(0)

    运行效果如下:(src为原始图像,dst为目标图像即缩放后的图像)

    原始图像:

     缩放后的图像:

    下面简单的说下最近临域插值的双线性插值(默认情况)的原理:

     1 # 原图像src 10*20 目标图像dst 5*10
     2 # src-->dst
     3 # (2,4)-->(1,2)
     4 # 计算公式 dst x 1 -> src x 2 newX
     5 # newX=x*(src的行/dst的行) newX=1*(10/5)=2
     6 # newY=y*(src的列/目标的列) newY=2*(20/10)=4
     7 # 12.3 = 12 最近领域插值法 取最近的整数
     8 #
     9 # 双线性插值法
    10 # A1=20% 上+ 80% 下 A2
    11 # B1=30% 左+ 70% 右 B2
    12 # 1 最终点 = A1 30% + A2 70%
    13 # 2 最终点 = B1 20% + B2 80%

    简单的实现下最近领域插值算法,测试代码如下:

     1 # 最近临域插值算法代码实现
     2 import cv2
     3 import numpy as np
     4 img = cv2.imread('image0.jpg', 1)
     5 imgInfo = img.shape
     6 height = imgInfo[0]
     7 width = imgInfo[1]
     8 dstHeight = int(height/3)
     9 dstWidth = int(width/2)
    10 dstImage = np.zeros((dstHeight, dstWidth, 3), np.uint8)  # 0-255 创建一个空白模版
    11 for i in range(0, dstHeight):  #
    12     for j in range(0, dstWidth):  #
    13         iNew = int(i*(height*1.0/dstHeight))
    14         jNew = int(j*(width*1.0/dstWidth))
    15         dstImage[i, j] = img[iNew, jNew]
    16 cv2.imshow('dst', dstImage)
    17 cv2.waitKey(0)

    运行结果如下:(即展示缩放后的图像)

    图像的缩放再测试,代码如下:

     1 # 图片缩放
     2 import cv2
     3 import numpy as np
     4 img = cv2.imread('image0.jpg', 1)
     5 cv2.imshow('src', img)
     6 imgInfo = img.shape
     7 height = imgInfo[0]
     8 width = imgInfo[1]
     9 matScale = np.float32([[0.5, 0, 0], [0, 0.5, 0]])
    10 dst = cv2.warpAffine(img,matScale,(int(width/2),int(height/2)))
    11 cv2.imshow('dst',dst)
    12 cv2.waitKey(0)

    运行结果如下:(src为初始图像,dst为目标图像)

    src初始图像:

    dst缩放后的图像:

    2.图片的剪切

    图片剪切的大致原理,按照我的理解就是:确定两个点,连接两个的线段即为剪切矩阵的对角线,通过这两个的坐标,就可以确定需要剪切的矩阵的方位以及矩阵大小。

    更通俗一点的理解就是,你在用QQ截图的时候,总是先点一个起始点,最后再点一个终止点,最后形成一个矩阵,最后再输出这个矩阵中所有的像素值,即为剪切后的图片。

    图片的剪切,测试代码如下:

    1 # 实现图片的剪切
    2 import cv2
    3 img = cv2.imread('image0.jpg', 1)
    4 cv2.imshow('src', img)
    5 imgInfo = img.shape
    6 # dst = img[100:500, 200:500]
    7 dst = img[100:400, 100:500]  # 前面是纵向的范围 后面的是横向的范围
    8 cv2.imshow('image', dst)
    9 cv2.waitKey(0)

    运行结果如下:(src为原始图像,image为目标图像)

    src原始图像:

    image剪切后的图像:(剪了一朵大发发)

     3.图片的移位

    通过api调用实现图片的移位,测试代码如下:

     1 # 通过api调用实现图片的移位
     2 import cv2
     3 import numpy as np
     4 img = cv2.imread('image0.jpg', 1)
     5 imgInfo = img.shape
     6 height = imgInfo[0]
     7 width = imgInfo[1]
     8 img = cv2.resize(img,(int(height*0.5),int(width*0.5)))  # 原始图像长宽缩小一半
     9 cv2.imshow('src', img)
    10 # 移位矩阵
    11 matShift = np.float32([[1,0,50],[0,1,100]])  # 第一个移位矩阵
    12 matShift2 = np.float32([[1,0,200],[0,1,100]])  # 第二个移位矩阵
    13 # 目标矩阵
    14 dst = cv2.warpAffine(img,matShift,(height,width-200))  # 第一个目标矩阵
    15 dst2 = cv2.warpAffine(img,matShift2,(height,width-200))  # 第二个目标矩阵
    16 # 展示两个目标图像
    17 cv2.imshow('dst',dst)
    18 cv2.imshow('dst2',dst2)
    19 cv2.waitKey(0)

    运行结果如下:(src为测试图像,dst为第一个移位后的图像,dst2为第二个移位后的图像)

    src测试图像:

    dst第一个移位图像:

    dst2第二个移位图像:

    自行实现图片向右移动100个像素,测试代码如下:

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

    运行结果如下:(src为原始图像,image为移位后的图像)

    src原始图像:

    image移位后的图像:

     4.图片镜像

    图像镜像的实现步骤是:

    1. 先创建一个最够大的画板,能够“装得下”镜像化之后的图像
    2. 然后再将该图像分别从前向后、从后向前绘制
    3. 最后绘制中心分割线

    测试代码如下:

     1 import cv2
     2 import numpy as np
     3 img = cv2.imread('image0.jpg', 1)
     4 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.3)))
     5 cv2.imshow('src', img)
     6 imgInfo = img.shape
     7 height = imgInfo[0]
     8 width = imgInfo[1]
     9 deep = imgInfo[2]
    10 newImgInfo = (height*2, width, deep)
    11 dst = np.zeros(newImgInfo, np.uint8)
    12 for i in range(0, height):
    13     for j in range(0, width):
    14         dst[i, j] = img[i, j]
    15         # x y = 2*j - y- 1
    16         dst[height*2-i-1, j] = img[i, j]
    17 for i in range(0, width):
    18     dst[height, i] = (0, 0, 255)
    19 cv2.imshow('image', dst)
    20 cv2.waitKey(0)

    运行结果如下:(src为初始图像,image为镜像后的图像)

    src初始图像:

    image镜像后的图像:

    5.图片的放射变换

    放射变换融合了如下几点:

    • 位移
    • 旋转
    • 缩放

     测试代码如下:

     1 # 仿射变换:位移 旋转 缩放
     2 import cv2
     3 import numpy as np
     4 img = cv2.imread('image0.jpg', 1)
     5 cv2.imshow('src', img)
     6 imgInfo = img.shape
     7 height = imgInfo[0]
     8 width = imgInfo[1]
     9 # src 3->dst 3 (左上角 左下角 右上角)
    10 matSrc = np.float32([[0,0],[0,height-1],[width-1,0]])
    11 matDst = np.float32([[50,50],[300,height-200],[width-300,100]])
    12 # 组合
    13 matAffine = cv2.getAffineTransform(matSrc,matDst)
    14 dst = cv2.warpAffine(img,matAffine,(width,height))
    15 cv2.imshow('dst',dst)
    16 cv2.waitKey(0)

    运行结果如下:(src为初始图像,dst为目标图像)

    src初始图像:

    dst目标图像:

    6.图片的旋转

     调用api实现图片的旋转,测试代码如下:(主要有三个参数,旋转中心的坐标、旋转角度以及缩放系数(至于为什么有缩放系数,因为旋转的时候可能会触碰到图像矩阵框的边缘,所以需要缩放处理))

     1 # 图片旋转
     2 import cv2
     3 import numpy as np
     4 img = cv2.imread('image0.jpg', 1)
     5 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.5)))
     6 cv2.imshow('src', img)
     7 imgInfo = img.shape
     8 height = imgInfo[0]
     9 width = imgInfo[1]
    10 # 得到旋转矩阵 center angle sc 中心点 角度 缩放系数
    11 matRotate = cv2.getRotationMatrix2D((height*0.5,width*0.5),45,0.7)
    12 dst = cv2.warpAffine(img,matRotate,(height,int(width*1.5)))
    13 cv2.imshow('image',dst)
    14 cv2.waitKey(0)

    运行效果如下:(src为初始图像,image为目标图像)

    src初始图像:

    image目标图像:

     暂时先记下这么多,还有的话再更新。。。

  • 相关阅读:
    二叉苹果树|codevs5565|luoguP2015|树形DP|Elena
    没有上司的舞会|codevs1380|luoguP1352|树形DP|Elena
    NYOJ15|括号匹配(二)|区间DP|Elena
    AtCoder Beginner Contest 070|Elena|8.12|#471
    NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索
    7.26-STOIRegularMatch-08-#14
    跳石头|河中跳房子|NOIP2015提高组T4|二分法
    BZOJ2330: [SCOI2011]糖果
    BZOJ1295: [SCOI2009]最长距离
    BZOJ1263: [SCOI2006]整数划分
  • 原文地址:https://www.cnblogs.com/wydxry/p/10894732.html
Copyright © 2020-2023  润新知