> 技术文档 > OpenCV 图像变换全解析:从镜像翻转到仿射变换的实践指南

OpenCV 图像变换全解析:从镜像翻转到仿射变换的实践指南


前言

        处理图像时,翻转、旋转、平移等操作很常用。OpenCV 提供了简单的方法实现这些变换,本文带你快速学会用它做图像翻转和仿射变换。

1 图像翻转(图像镜像旋转)

在OpenCV中,图片的镜像旋转是以图像的中心为原点进行镜像翻转的。

  • cv2.flip(img,flipcode)

  • 参数

    • img: 要翻转的图像

    • flipcode: 指定翻转类型的标志

      • flipcode=0: 垂直翻转,图片像素点沿x轴翻转

      • flipcode>0: 水平翻转,图片像素点沿y轴翻转

      • flipcode<0: 水平垂直翻转,水平翻转和垂直翻转的结合

示例:

import cv2 as cvface = cv.imread(\'../images/face.png\')cv.imshow(\'face\', face)# 翻转 镜像旋转 以图像中心为原点cv.filp(img, filpcode)# flipcode = 0垂直翻转 沿x轴 上下翻转flip_0 = cv.flip(face, 0)cv.imshow(\'flip_0\', flip_0)# flipcode = 1垂直翻转 沿y轴 左右翻转flip_1 = cv.flip(face, 1)cv.imshow(\'flip_1\', flip_1)# flipcode = -1垂直+水平翻转flip = cv.flip(face, -1)cv.imshow(\'flip_-1\', flip)cv.waitKey(0)cv.destroyAllWindows()

结果如下

2 图像仿射变换

        仿射变换(Affine Transformation)是一种线性变换,保持了点之间的相对距离不变。

  • 仿射变换的基本性质

    • 保持直线

    • 保持平行

    • 比例不变性

    • 不保持角度和长度

  • 常见的仿射变换类型

    • 旋转:绕着某个点或轴旋转一定角度。

    • 平移:仅改变物体的位置,不改变其形状和大小。

    • 缩放:改变物体的大小。

    • 剪切:使物体发生倾斜变形。

  • 仿射变换的基本原理

    • 线性变换

    • 二维空间中,图像点坐标为(x,y),仿射变换的目标是将这些点映射到新的位置 (x\', y\')。

    • 为了实现这种映射,通常会使用一个矩阵乘法的形式:

      (类似于y=kx+b)

      • a,b,c,d 是线性变换部分的系数,控制旋转、缩放和剪切。

      • t_x,t_y 是平移部分的系数,控制图像在平面上的移动。

      • 输入点的坐标被扩展为齐次坐标形式[x,y,1],以便能够同时处理线性变换和平移

  • cv2.warpAffine()函数

    • 仿射变换函数

      cv2.warpAffine(img,M,dsize)
      • img:输入图像。

      • M:2x3的变换矩阵,类型为np.float32

      • dsize:输出图像的尺寸,形式为(width,height)

2.1 图像旋转

        旋转图像可以将图像绕着某个点旋转一定的角度。

cv2.getRotationMatrix2D()函数

  • 获取旋转矩阵

    cv2.getRotationMatrix2D(center,angle,scale)
    • center:旋转中心点的坐标,格式为(x,y)

    • angle:旋转角度,单位为度,正值表示逆时针旋转负值表示顺时针旋转。

    • scale:缩放比例,若设为1,则不缩放。

    • 返回值M,2x3的旋转矩阵。

示例:

import cv2import cv2 as cv# 读图pig = cv.imread(\'../images/pig.png\')pig = cv.resize(pig, (520,520))# 获取旋转矩阵 cv2.getRotationMatrix2D(center,angle,scale)M = cv2.getRotationMatrix2D((260, 260), -45, 1)# 仿射变换函数cv.warpAffine(img,M,(w,h)dst = cv.warpAffine(pig, M, (pig.shape[1], pig.shape[0]))cv.imshow(\'pig\', pig)cv.imshow(\'pig_new\', dst)cv.waitKey(0)cv.destroyAllWindows()

2.2 图像平移

移操作可以将图像中的每个点沿着某个方向移动一定的距离。

  • 假设我们有一个点 P(x,y),希望将其沿x轴方向平移t_x*个单位,沿y轴方向平移t_y个单位到新的位置P′(x′,y′),那么平移公式如下:

    x′=x+tx

    y′=y+ty

    在矩阵形式下,该变换可以表示为:

        这里的t_x和t_y分别代表在x轴和y轴上的平移量。

示例:

import cv2import cv2 as cvimport numpy as np# 读图pig = cv.imread(\'../images/pig.png\')pig = cv.resize(pig, (520,520))# 定义偏移量tx = 80ty = 120# 定义平移矩阵M = np.float32([[1, 0, tx], [0, 1, ty]])# 仿射变换矩阵,找不到的就用黑色填充dst = cv.warpAffine(pig, M, (520, 520))cv.imshow(\'pig\', pig)cv.imshow(\'pig_new\', dst)cv.waitKey(0)cv.destroyAllWindows()

2.3 图像缩放

缩放操作可以改变图片的大小。

  • 假设要把图像的宽高分别缩放为0.5和0.8,那么对应的缩放因子sx=0.5,sy=0.8。

  • 点P(x,y)对应到新的位置P\'(x\',y\'),缩放公式为:

    x′=sx*x

    y′=sy*y

    在矩阵形式下,该变换可以表示为:

    相较于图像旋转中只能等比例的缩放,图像缩放更加灵活,可以在指定方向上进行缩放。

sx和sy分别表示在x轴和y轴方向上的缩放因子。

示例:

import cv2 as cvimport numpy as np# 读图pig = cv.imread(\'../images/pig.png\')pig = cv.resize(pig, (520,520))# 定义缩放移量sx = 0.6sy = 0.5# 定义缩放矩阵M = np.float32([[sx, 0, 0], [0, sy, 0]])# 仿射变换矩阵,找不到的就用黑色填充dst = cv.warpAffine(pig, M, (520, 520))cv.imshow(\'pig\', pig)cv.imshow(\'pig_new\', dst)cv.waitKey(0)cv.destroyAllWindows()

2.4 图像剪切(了解即可)

剪切操作可以改变图形的形状,以便其在某个方向上倾斜,它将对象的形状改变为斜边平行四边形,而不改变其面积

  • 想象我们手上有一张矩形纸片,如果你固定纸片的一边,并沿着另一边施加一个平行于该边的力,这张纸片就会变形为一个平行四边形。这就是剪切变换的一个直观解释。

  • 对于二维空间中的点P(x,y),对他进行剪切变换:

    沿x轴剪切:x\'=x+shy*y       y\'=y

    沿y轴剪切:x\'=x       y\'=shx*x+y

  • 当需要同时沿两个方向进行剪切时,x\'=x+shy*y , y\'=shx*x+y

  • 在矩阵形式下,该变换可以表示为:

  • 来一个图理解一下:

shy和shx分别对应沿x轴和y轴方向上的剪切因子。

  • 可以理解为,x不变,y偏移

总结:

        本文讲了 OpenCV 的两种图像变换。用cv.flip()能轻松实现图像的垂直、水平翻转。仿射变换里,通过矩阵设置,结合cv.warpAffine()可完成旋转、平移、缩放和剪切。这些基础操作是图像处理的必备技能,多练就能熟练掌握。