美文网首页
图像的仿射变换

图像的仿射变换

作者: 原上的小木屋 | 来源:发表于2020-05-29 01:04 被阅读0次

图像的平移

  • 假定图像中初始坐标为(x,y),经过平移得到新坐标(x',y'),即我们可以得到变换因子
  • x方向上为dx=x'-x
  • y方向上为dy=y‘-y
  • 我们又知道,矩阵同时也代表着运动,上述描述,可以写为
    \left[\begin{matrix}x'\\y'\\1\end{matrix}\right]\=\left[\begin{matrix}1&0&dx\\0&1&dy\\0&0&1\end{matrix}\right]\*\left[\begin{matrix}x\\y\\1\end{matrix}\right]\
  • 即可以得到反变换公式
  • x=x'-dx
  • y=y'-dy
  • 同样地,图像旋转和图像缩放也可以用这个矩阵来表示了
  • 即每个原图像上的像素点均可以通过这样的一一映射关系得到,则代码就很容易实现咯
def bl_interpolate(img, dx=1, dy=1):
    H, W, C = img.shape  # 首先取得原图像的尺寸大小
    out = np.zeros((H, W, C), dtype=np.float)  # 重建图像
    for y in range(H):
        for x in range(W):
            for c in range(C):
                y1 = y - dy#取得原图像坐标
                x1 = x - dx#取得原图像坐标
                if ((y1 > H-1 or y1 < 0 or x1 > W-1 or x1 < 0)):
                    pass
                else:
                    out[y, x, c] = img[y1, x1, c]  # 根据上述推导的公式进行变换
    return out.astype(np.uint8)

平移伸缩

  • 如果想为图像加上放大缩小然后再平移,上面的变换矩阵就变为了\left[\begin{matrix}tx&0&dx\\0&ty&dy\\0&0&1\end{matrix}\right]\tx与ty即对应着x方向和y方向上的伸缩变换,同时dx与dy对应着x和y方向上的平移变换,让我们来看一下反变换公式即
  • x方向上变为x=(x'-dx)/tx
  • y方向上变为x=(y'-dy)/ty
def bl_interpolate(img, tx=1, ty=1, dx=1, dy=1):
    H, W, C = img.shape  # 首先取得原图像的尺寸大小
    aH = int(ty * H)  # 计算插值后的图像尺寸
    aW = int(tx * W)  # 计算插值后的图像尺寸
    out = np.zeros((aH, aW, C), dtype=np.float)  # 重建图像
    for y in range(aH):
        for x in range(aW):
            for c in range(C):
                y1 = int((y - dy) // ty)
                x1 = int((x - dx) // tx)
                if ((y1 > H - 1 or y1 < 0 or x1 > W - 1 or x1 < 0)):
                    pass
                else:
                    print(y, x, c)
                    print(y1, x1, c)
                    out[y, x, c] = img[y1, x1, c]  # 根据上述推导的公式进行变换
    return out.astype(np.uint8)

旋转操作

  • 旋转操作同样可以用一个矩阵来说明,举个最简单的例子,直角坐标系中有一点(x,y),当期沿着原点逆时针旋转\alpha时,我们可以轻松地写出变换之后的坐标(x',y')即
  • x'=xcos\alpha-ysin\alpha
  • y'=xsin\alpha+ycos\alpha
    矩阵形式即\left[\begin{matrix}cos\alpha&-sin\alpha&\\sin\alpha&cos\alpha&\end{matrix}\right]\
  • 反变换公式即为
  • x=x'cos\alpha+y'sin\alpha
  • y=y'cos\alpha-x'sin\alpha
  • 如果再把旋转中心加上的话,情况会稍稍复杂一点,但仍然可以通过简单的画图将式子推导出来,即假设旋转中心为(a,b),即根据简单变换即可得到
  • x'-a=(x-a)cos\alpha-(y-b)sin\alpha
  • y'-b=(x-a)sin\alpha+(y-b)cos\alpha
  • 此时矩阵可以表示为\left[\begin{matrix}cos\alpha&-sin\alpha&a-acos\alpha+bsin\alpha\\sin\alpha&cos\alpha&b-asin\alpha-bcos\alpha\\0&0&1\end{matrix}\right]\
  • 反变换公式即为
  • x-a=(x'-a)cos\alpha+(y'-b)sin\alpha
  • y-b=(y'-b)cos\alpha-(x'-a)sin\alpha
def affine(_img, a, b, c, d, tx, ty):
    H, W, C = _img.shape
    # temporary image
    img = np.zeros((H + 2, W + 2, C), dtype=np.float32)
    img[1:H + 1, 1:W + 1] = _img
    # get shape of new image
    H_new = np.round(H).astype(np.int)
    W_new = np.round(W).astype(np.int)
    out = np.zeros((H_new, W_new, C), dtype=np.float32)
    # get position of new image
    x_new = np.tile(np.arange(W_new), (H_new, 1))
    y_new = np.arange(H_new).repeat(W_new).reshape(H_new, -1)
    # get position of original image by affine
    adbc = a * d - b * c
    x = np.round((d * x_new - b * y_new) / adbc).astype(np.int) - tx + 1
    y = np.round((-c * x_new + a * y_new) / adbc).astype(np.int) - ty + 1
    # adjust center by affine
    dcx = (x.max() + x.min()) // 2 - W // 2
    dcy = (y.max() + y.min()) // 2 - H // 2
    x -= dcx
    y -= dcy
    x = np.clip(x, 0, W + 1)
    y = np.clip(y, 0, H + 1)
    # assign pixcel
    out[y_new, x_new] = img[y, x]
    out = out.astype(np.uint8)
    return out
# Read image
img = cv2.imread(r"C:\Users\root\Desktop\123.jpg")
# Affine
A = 30.
theta = - np.pi * A / 180.
out = affine(img, a=np.cos(theta), b=-np.sin(theta), c=np.sin(theta), d=np.cos(theta),
             tx=0, ty=0)

图像仿射变换使图像倾斜

  • 本质相当于在x方向或y方向单独施加一个力,让图像发生x方向或y方向上的形变,即当只在x方向上作用时,y坐标范围不发生变化,而x坐标由于受到力的作用,范围变大,x坐标随y坐标的变化而产生变化,变换矩阵为\left[\begin{matrix}1&tx\\0&1\\\end{matrix}\right]\在此不做过多叙述,原理与上述平移旋转原理一致
def affine(img, dx=30, dy=30):
    # get shape
    H, W, C = img.shape
    # Affine hyper parameters
    a = 1.
    b = dx / H
    c = dy / W
    d = 1.
    tx = 0.
    ty = 0.
    # prepare temporary
    _img = np.zeros((H+2, W+2, C), dtype=np.float32)
    # insert image to center of temporary
    _img[1:H+1, 1:W+1] = img
    # prepare affine image temporary
    H_new = np.ceil(dy + H).astype(np.int)
    W_new = np.ceil(dx + W).astype(np.int)
    out = np.zeros((H_new, W_new, C), dtype=np.float32)
    # preprare assigned index
    x_new = np.tile(np.arange(W_new), (H_new, 1))
    y_new = np.arange(H_new).repeat(W_new).reshape(H_new, -1)
    # prepare inverse matrix for affine
    adbc = a * d - b * c
    x = np.round((d * x_new  - b * y_new) / adbc).astype(np.int) - tx + 1
    y = np.round((-c * x_new + a * y_new) / adbc).astype(np.int) - ty + 1
    x = np.minimum(np.maximum(x, 0), W+1).astype(np.int)
    y = np.minimum(np.maximum(y, 0), H+1).astype(np.int)
    # assign value from original to affine image
    out[y_new, x_new] = _img[y, x]
    out = out.astype(np.uint8)
    return out
# Read image
img = cv2.imread(r"C:\Users\root\Desktop\123.jpg")
# Affine
out = affine(img, dx=0, dy=30)

相关文章

  • 图片处理-opencv-7.图像几何变换

    图像几何变换 1.图像仿射变换 图像仿射变换又称为图像仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一...

  • 几何变换之仿射---OpenCV-Python开发指南(12)

    仿射 在OpenCV中,仿射变换是指图像经过一系列的几何变换来实现的平移,旋转等多种操作。该变换能够保持图像的平直...

  • 1.9 openCV-python 几何变换

    几何变换 学习对图像进行各种几个变换,例如移动,旋转,仿射变换等。

  • 人脸活体检测

    人脸检测 深度学习 关键点检测 sift,surf 人脸对齐(仿射变换) OpenCV 对人脸图像进行仿射...

  • 图像的仿射变换

    图像的平移 假定图像中初始坐标为(x,y),经过平移得到新坐标(x',y'),即我们可以得到变换因子 x方向上为d...

  • OpenCV实现图像的几何变换

    图像的几何变换 几何变换主要包括缩放、平移、旋转、仿射变换、透视变换和图像裁剪等。执行这些几何变换的两个关键函数是...

  • 第四篇:CALayer能力之仿射变换和3D变换

    目录 一、UIView的仿射变换 1、单仿射变换 2、混合仿射变换 3、CGAffineTransformIden...

  • iOS 仿射变换

    一、iOS 仿射变换CGAffineTransform详解IOS开发UI篇--仿射变换(CGAffineTrans...

  • 计算机视觉(2) 图形几何变换

    图像几何变换 图片变换的本质就是对图片的矩阵进行操作 图片位移 矩阵仿射变换,是一系列变换的基础 图片缩放 图片缩...

  • 仿射变换

    参考资料: 马同学:如何通俗的解释仿射变换 1. 仿射变换的作用: 通过仿射变换对图片进行旋转、平移、缩放等操作以...

网友评论

      本文标题:图像的仿射变换

      本文链接:https://www.haomeiwen.com/subject/hwxtzhtx.html