一文搞懂仿射变换
Posted 修炼之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文搞懂仿射变换相关的知识,希望对你有一定的参考价值。
导读
在图像处理中,我们经常需要对图像进行各种操作如平移、缩放、旋转、翻转等,这些其实都是图像的仿射变换
。通过本篇文章,你能够知道它们的实现原理以及如何应用它们。
仿射变换
仿射变换
也称仿射投影
,是指几何中,对一个向量空间进行线性变换并接上一个平移,变换为另一个向量空间。所以,仿射变换其实也就是再讲如何来进行两个向量空间的变换
假设有一个向量空间
k
k
k:
k
=
(
x
,
y
)
k=(x,y)
k=(x,y)
还有一个向量空间
j
j
j:
j
=
(
x
′
,
y
′
)
j=(x',y')
j=(x′,y′)
如果我们想要将向量空间由
k
k
k变为
j
j
j,可以通过下面的公式进行变换
j
=
k
∗
w
+
b
j = k* w + b
j=k∗w+b
将上式进行拆分可得
x
′
=
w
00
∗
x
+
w
01
∗
y
+
b
0
y
′
=
w
10
∗
x
+
w
11
∗
y
+
b
1
x'=w_00*x+w_01*y+b_0 \\\\ y'=w_10*x+w_11*y+b_1
x′=w00∗x+w01∗y+b0y′=w10∗x+w11∗y+b1
我们再将上式转换为矩阵的乘法
[
x
′
y
′
]
=
[
w
00
w
01
b
0
w
10
w
11
b
1
]
[
x
y
1
]
=
M
[
x
y
1
]
(3)
\\left[ \\beginmatrix x' \\\\ y' \\\\ \\endmatrix \\right] \\tag3= \\left[ \\beginmatrix w_00 & w_01 & b_0 \\\\ w_10 & w_11 & b_1\\\\ \\endmatrix \\right] \\left[ \\beginmatrix x \\\\ y \\\\ 1 \\endmatrix \\right]= M \\left[ \\beginmatrix x\\\\ y\\\\ 1 \\endmatrix \\right]
[x′y′]=[w00w10w01w11b0b1]⎣⎡xy1⎦⎤=M⎣⎡xy1⎦⎤(3)
通过参数矩阵
M
M
M就可以实现两个向量空间之间的转换,在进行仿射变换的时候我们也只需要一个矩阵
M
M
M就可以实现平移
、缩放
、旋转
和翻转
变换。
接下来,会先介绍原理然后利用OpenCV来实现相应的例子,这里主要利用OpenCV的warpAffine
函数来实现仿射变换
warpAffine函数参数:
src
:输入的图像数组M
:仿射变换矩阵dsize
:变换后图像的大小flags
:使用的插值算法borderValue
:边界的填充值
图像平移
在平面坐标系有点
P
(
x
,
y
)
P(x,y)
P(x,y)和点
P
′
(
x
′
,
y
′
)
P'(x',y')
P′(x′,y′),如果我们想要将
P
P
P点移动到
P
′
P'
P′通过下面的变换就可以实现
x
′
=
x
+
Δ
x
y
′
=
y
+
Δ
y
x'=x+\\Delta x \\\\ y' = y + \\Delta y
x′=x+Δxy′=y+Δy
其中
Δ
x
\\Delta x
Δx和
Δ
y
\\Delta y
Δy就是x方向上和y方向上的偏移量,我们将其转换为矩阵的形式
[
x
′
y
′
]
=
[
1
0
Δ
x
0
1
Δ
y
]
[
x
y
1
]
=
M
[
x
y
1
]
\\left[ \\beginmatrix x'\\\\ y'\\\\ \\endmatrix \\right]= \\left[ \\beginmatrix 1 & 0 & \\Delta x\\\\ 0 & 1 & \\Delta y\\\\ \\endmatrix \\right] \\left[ \\beginmatrix x\\\\ y\\\\ 1 \\endmatrix \\right]= M\\left[ \\beginmatrix x\\\\ y\\\\ 1 \\endmatrix \\right]
[x′y′]=[1001ΔxΔy]⎣⎡xy1⎦⎤=M⎣⎡xy1⎦⎤
上面的矩阵
M
M
M就是仿射变换的平移参数,接下来我们利用OpenCV中的warpAffine
函数来实现
import cv2
import numpy as np
import matplotlib.pyplot as plt
def show_compare_img(original_img,transform_img):
_,axes = plt.subplots(1,2)
#显示图像
axes[0].imshow(original_img)
axes[1].imshow(transform_img)
#设置子标题
axes[0].set_title("original image")
axes[1].set_title("warpAffine transform image")
plt.show()
def translation_img():
# 定义一个图像平移矩阵
# x向左平移(负数向左,正数向右)20个像素
# y向下平移(负数向上,正数向下)50个像素
M = np.array([[1, 0, -20], [0, 1, 50]], dtype=np.float)
# 读取需要平移的图像
img = cv2.imread("test.jpg")
# 将图片由BGR转为RGB
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 定义平移后图像的大小,保持和原图大小一致
dsize = img.shape[:2][::-1]
# 便于大家观察这里采用白色来填充边界
translation_img = cv2.warpAffine(img, M, dsize, borderValue=(255, 255, 255))
# 显示图像
show_compare_img(img, translation_img)
translation_img()
图像翻转
有时候我们我们需要对图像进行 以上是关于一文搞懂仿射变换的主要内容,如果未能解决你的问题,请参考以下文章水平翻转
、垂直翻转
、镜像翻转
(同时进行水平和垂直翻转),想要实现这个功能并不难,我们可以通过opencv
内置的flip
方法很容易实现,还可以通过numpy的索引
来实现,这里我们主要介绍通过仿射变换矩阵
来实现这个功能
上图中的
A
、
B
、
C
、
D
A、B、C、D
A、B、C、D表示图像的四个顶点,如果我们需要对图像进行水平翻转,那么我们就需要将
A
A
A点和
B
B
B点进行交换,
C