zoukankan      html  css  js  c++  java
  • 图像的几何变化


    一、基本概念

    在不改变图像的内容的前提下, 对图像的像素进行空间几何变化;
    包括 图像的平移、镜像变换、缩放和旋转等;
    假设原始图像的 f(x0, y0),经过几何变化产生的目标图像为 g(x1, y1), 则空间变换(映射)关系为:

    x1 = s(x0, y0)
    y1 = t(x0, y0)

    那么, s(x0, y0), t(x0, y0) 为由 f(x0, y0) 到 g(x1, y1) 的坐标变换函数;

    求解出坐标变换函数后,开始计算变换后的图像的像素为止,然后插值到变换后的图像上。


    二、插值法

    对于数字图像而言,像素的坐标是 离散型非负整数;在进行控件坐标转换的时候,可能会产生浮点坐标;
    例如 (11, 11) --> (5.5, 5.5), 这种坐标值是无效的,插值法就是用来处理这些浮点数的;
    常见的插值法:
    1、最邻近插值法
    2、双线性插值法
    3、二次立方插值法;
    4、三次立方插值法等


    最邻近插值法

    假设 u,v 是 0<u, v<1 的小数,(i+u, j+v)为输入的像素坐标,待求的像素灰度值 f(i+u, j+v), 根据 u,v 的值不同, f(i+u, j+v) 的值也是不同的;

    弊端:最近邻的计算量很小,但是会造成图像灰度上的不连续;在灰度变化密集的时候,会有锯齿的情况。


    双线性插值法

    对于目标像素,设置坐标通过反向变换得到浮点坐标 (i+u, j+v);
    其中 i, j 都是非负整数;u,v 是 [0,1) 区间的浮点数; 这个像素的值 f(i+u, j+v) 由原图坐标 (i,j), (i+1,j), (i, j+1), (i+1, j+1) 所对应的周围4个像素值决定。

    相比最近邻插值法,双线性的计算量很大,但是缩放之后的图像质量高,不会出现像素值不连续的情况。
    双线性插值法 具有 低通过滤器的特性,算是图像的高频分量,图像在轮廓上会变得模糊;


    差值算法的实现

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    img = cv2.imread('lena.jpg')
    
    # 封装方法来显示图片
    def cv_show(img):
        cv2.imshow('w title',img) 
        waitret = cv2.waitKey(2000) 
        # wait = cv2.waitKey()
        print(waitret)
        cv2.destroyAllWindows()
    

    resize

    resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst

    1. 默认差值算法为双线性插值;
    2. src:输入图像;
    3. 返回:输出图像
    4. dsize:输出图像的大小;如果当前参数为0,原始图像缩放的大小需要按照公式进行计算:dsize = Size(round(fx * src.cols), round(fy * src.rows))。fx 和 fy 是宽度和高度的缩放比例。
    5. interpolation 表示差值的方式
    cv2.resize()
     
    img.shape
    # (263, 263, 3)
    

    三、图像的缩放

    分为 水平缩放系数 和 垂直缩放系数;

    • < 1 变小
    • = 1 不变
    • > 1 变大

    缩放原理

    $ x = x_0 * fx ( ) y = y_0 * fy $

    • fx : 水平缩放系数
    • fy : 垂直缩放系数
    • $ (x_0, y_0) $ : 缩放之前的坐标
    • (x, y) : 缩放之后的坐标

    img1 = cv2.resize(img, (120, 120))
    plt.imshow(img1)
    

    output_14_1.png

    img2 = cv2.resize(img, (500, 500))
    plt.imshow(img)
    

    output_15_1.png

    img3 = cv2.resize(img, (500, 500), interpolation=cv2.INTER_LINEAR)
    plt.imshow(img3)
    

    output_17_1.png


    四、图像的平移

    warpAffine 方法

    warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst
    . @brief Applies an affine transformation to an image.

    • 插补方法的标志组合(见#InterpolationFlags) 和可选的标志 #WARP_INVERSE_MAP,这意味着M是逆变换 (( exttt{dst} ightarrow exttt{src}))

    • borderMode 像素外推方法(见#BorderTypes);当borderMode=#BORDER_TRANSPARENT时,它意味着目标图像中对应于源图像中的“异常值”的像素不被函数修改。


    调用

    cv2.warpAffine
    
    arr1 = np.array([[1,0, 100], [0,1,100]], np.float32)
    img4 = cv2.warpAffine(img, arr1, img.shape[:2])
    

    五、图像的旋转

    让图像按照某一点旋转到指定的角度,图像旋转之后不会变形,但是垂直对称轴和水平对称轴 会发生改变,旋转后的坐标 和 原始图像的坐标已经不能通过简单地加减乘除来得到映射;

    确定参数:图像的旋转中心,旋转角度,缩放因子;

    步骤:

    1. 得到变换矩阵
    2. 通过函数进行变换

    注意:

    1. 无论是平移还是旋转,都会出现图像被裁剪的问题(比如旋转 75°的时候);
      因此需要先计算输出图像的尺寸,来避免数据的损失。

    getRotationMatrix2D 方法

    getRotationMatrix2D(center, angle, scale) -> retval
    . @brief Calculates an affine matrix of 2D rotation.

    这个方法计算了下面的矩阵

    [egin{bmatrix} alpha & eta & (1- alpha ) cdot exttt{center.x} - eta cdot exttt{center.y} \ - eta & alpha & eta cdot exttt{center.x} + (1- alpha ) cdot exttt{center.y} end{bmatrix} ]

    [[egin{array}{l} alpha = exttt{scale} cdot cos exttt{angle} , \ eta = exttt{scale} cdot sin exttt{angle} end{array} ]

    这个变换将旋转中心映射到它自己。如果这不是目标,调整转换。

    • center:原始图片的旋转中心 Center of the rotation in the source image.
    • angle :旋转角度。正值表示逆时针旋转(假设坐标原点为左上角)。
    • scale :各向同性的比例因子。
    h,w,n = img.shape
     
    mat = cv2.getRotationMatrix2D((w/2, h/2), -90,1)
    img5 = cv2.warpAffine(img, mat, img.shape[:2])  # img.shape[:2] 取图片的宽高
    plt.imshow(img5)
    

    output_27_1.png


    mat = cv2.getRotationMatrix2D((w/2, h/2), -135,1)
    img6 = cv2.warpAffine(img, mat, (int(img.shape[0]*1.5), int(img.shape[1]*1.6)) 
     
    img.shape[0] * 1.5  # 394.5
     
    int(img.shape[1]*1.6)  #  420
    

    六、镜像变换

    理论

    分为 水平镜像和垂直镜像

    水平镜像以 图像垂直中线 为轴;

    垂直镜像以 水平中线为轴,将图像的上半部分和下半部分对调


    变换原理

    水平镜像 $ x = width - x, y = y_0 $

    垂直镜像 $ x = x_0, y = height - y_0 $


    flip 函数

    flip(src, flipCode[, dst]) -> dst

    • flipCode : 如何反转数组
      • 0 垂直反转
      • 1 水平翻转
      • 负数(如-1),同时翻转

    . @sa transpose , repeat , completeSymm


    使用

    img6 = cv2.flip(img,0)
    plt.imshow(img6)
    

    output_33_1.png

  • 相关阅读:
    linux下进程权限分析
    基于Token的身份验证——JWT
    hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(3)http://www.cnblogs.com/liugh/p/6624491.html
    hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(2)安装hadoop
    hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(1)安装jdk
    配置ssh无密钥登陆
    Linux实战案例(7)安装jdk
    Scala入门(1)Linux下Scala(2.12.1)安装
    Linux实战案例(6)yum查找、卸载、和安装软件
    Linux实战案例(5)关闭Centos的防火墙
  • 原文地址:https://www.cnblogs.com/fldev/p/14371246.html
Copyright © 2011-2022 走看看