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

    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目标图像:

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

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 黑色星期五
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    控件动态产生器(使用RegisterClasses提前进行注册)
    Delphi编写自定义控件以及接口的使用(做了一个TpgDbEdit)
    Log4delphi使用心得
  • 原文地址:https://www.cnblogs.com/wydxry/p/10894732.html
Copyright © 2011-2022 走看看