所谓仿,就是仿照、相似。仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。变换后,直线仍然是直线,平行线仍然是平行线。仿射可以将矩形映射为平行四边形,那么透视可以将矩形映射为任意四边形。

仿 射

基础知识及函数用法

仿射变换的基本原理示意

OpenCV中,提供了仿射函数cv2.warpAffine()实现对图像的旋转

dst = cv2.warpAffine(src, M, dsize, [, flags[, borderMode[, borderValue]]])
  • dst代表仿射后的输出图像,dsize决定输出图像的实际大小
  • src代表要仿射的原始图像
  • M代表一个2X3的变换矩阵。使用不同的矩阵,就可以实现不同的仿射变换
  • dsize表示输出图像的尺寸大小
  • flags表示差值方法,默认为INTER_LINEAR。当值为WARP_INVERSE_MAP时,意味着M为逆变换,实现从目标图像dst到src的逆变换。具体值见下表。
  • borderMode表示边类型。默认为BORDER_CONSTANT。当值为BORDER_TRANSPARENT时,意味着目标图像内的值不做改变,这些值对应着原始图像的异常值。
  • border表示边界值,默认为0

平移

$$
dst(x,y)=src(M_{11}x+ M_{12}y+ M_{13},M_{21}x+ M_{22}y+M_{23})
$$

假如将原始图像src向右移动100个像素点、像下移动20个像素点,则
$$
dst(x,y)=src(1\cdot x+ 0\cdot y+ 100 , 0\cdot x+ 1 \cdot y+200)
$$
根据上面的意思,得到转换矩阵M有:
$$
\begin{matrix}
M_{11} =1\\M_{12} =0
\\M_{13} =100
\\M_{21} =0
\\M_{22} =1
\\M_{23} =200
\end{matrix}
$$
转换为矩阵为:
$$
M=\begin{bmatrix}
1 &0 &100 \\
0 &1 &200
\end{bmatrix}
$$
在得到M的情况下,可以直接利用矩阵M调用函数进行仿射。

例1:完成一个图像的平移。

import cv2
import numpy as np
img = cv2.imread('hongmao.jpg')
height, width = img.shape[:2]
x = 100
y = 200
M = np.float32([[1, 0, x], [0, 1, y]])
move1 = cv2.warpAffine(img, M, (width, height))
cv2.imshow('PRIGINAL', img)
cv2.imshow('MOVE', move1)
cv2.waitKey()

实验结果

旋转

使用cv2.warpAffine对图像进行旋转时,可以通过cv2.getRotationMatrix2D()获得转换矩阵。该函数的基本用法:

retval = cv2.getRotationMatrix2D(center, angle, scale)

式中:

  • center是旋转的中心点
  • angle是旋转角度,正数表示逆时针旋转,负数表示顺时针旋转
  • scale为变换尺寸(缩放大小)

例1 : 完成一张图片的旋转。要求以图像中心为圆点,逆时针旋转45°,并将目标缩小为原始图像的0.6倍。

import cv2
img = cv2.imread('hongmao.jpg')
height, width = img.shape[:2]
M = cv2.getRotationMatrix2D((width/2, height/2), 45, 0.6)
rotation = cv2.warpAffine(img, M, (width, height))
cv2.imshow('PRIGINAL', img)
cv2.imshow('ROTATE', rotation)
cv2.waitKey()

实验结果文件

更加复杂的仿射变换

对于更加复杂的变换,OpenCV提供了cv2.getAffineTransform()来生成需要的转换矩阵M。

语法:

retval = cv2.getAffineTransform(src, dst)
  • src表示输入图像的三个点坐标
  • dst表示输出图像的三个点坐标

src和dst三个点坐标分别表示平行四边形的左上角、右上角、右下角的三个点。

函数cv2.warpAffine()函数以cv2.getAffineTransform(src, dst)获得的转换矩阵M为参数,将src中的点仿射到dst中,函数cv2.getAffineTransform(src, dst)对指定的点完成映射之后,将所有其他点的映射关系按照指定点的关系确定。

import cv2
import numpy as np
img = cv2.imread('hongmao.jpg')
rows, cols, ch = img.shape
p1 = np.float32([[0, 0], [cols-1, 0], [0, rows-1]])
p2 = np.float32(
    [[0, cols*0.33], [cols*0.85, rows*0.25], [cols*0.15, rows*0.7]])
M = cv2.getAffineTransform(p1, p2)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('PRIGINAL', img)
cv2.imshow('Result', dst)
cv2.waitKey()

仿射结果

原理上的简要说明

透 视

上面的仿射变换可以将矩形映射为任意平行四边形。透视变换可以将矩形映射成任意四边形。

透视变换通过函数cv2.warpPerspective()实现,该函数的语法是:

dst = cv2.warpPerspective(src, M, dsize, [, flags[, borderMode[, borderValue]]])
  • dst代表透视处理后的输出图像,dsize决定输出图像的实际大小
  • src代表要透视的图像
  • M为一个3X3的变换矩阵
  • dsize代表输出图像的尺寸大小
  • flags表示差值方法,默认为INTER_LINEAR。当值为WARP_INVERSE_MAP时,意味着M为逆变换,实现从目标图像dst到src的逆变换。具体值见下表。
  • borderMode表示边类型。默认为BORDER_CONSTANT。当值为BORDER_TRANSPARENT时,意味着目标图像内的值不做改变,这些值对应着原始图像的异常值。
  • border表示边界值,默认为0

与仿射变化一样,可以使用函数cv2.getPerspectiveTransform()来生成转换矩阵。

语法:

retval = cv2.getPerspectiveTransform(src, dst)
  • src表示输入图像的四个顶点坐标
  • dst表示输出图像的四个顶点坐标

例:将图像透视。

import cv2
import numpy as np
img = cv2.imread('hongmao.jpg')
rows, cols, ch = img.shape
p1 = np.float32([[0, 0], [cols-1, 0], [0, rows-1], [rows-1, cols-1]])
# 左上角,右上角,左下角,右下角
p2 = np.float32(
    [[0, cols*0.13], [cols*0.15, rows*0.7], [cols*0.85, rows*0.25], [rows-1, cols-1]])
M = cv2.getPerspectiveTransform(p1, p2)
dst = cv2.warpPerspective(img, M, (cols, rows))
cv2.imshow('PRIGINAL', img)
cv2.imshow('Result', dst)
cv2.waitKey()

透视结果图


博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2021/OpenCV16.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 05 月 16 日
如果觉得我的文章对你有用,请随意赞赏