图像变换,这里介绍了图像的放大缩小,平移变换,错切变换,镜面变换,旋转变换,透视变换。
原素材图像为:
1.图像的裁剪及放大和缩小
可以用图像所对应的矩阵本身进行裁剪
img2=bear[50:400,60:280,:]#y,x,通道
对图像的放缩变换可以使用OpenCV自带的函数:
img3=cv.resize(bear,(400,400),interpolation=cv.INTER_LINEAR)
img3=cv.resize(bear,(400,400))
img3=cv.resize(bear,(400,400),interpolation=cv.INTER_NEAREST)
#cv中resize方法第三个参量interpolation,是代表扩展时所用的插值方法,有线性插值,也有最近插值等,
2.平移变换
若记原像素位置坐标为
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0),变换后的坐标为
(
x
,
y
)
(x,y)
(x,y),
F
x
F_x
Fx代表水平平移距离,
F
y
F_y
Fy代表竖直平移距离,平移公式表示为:
{
x
=
x
0
+
F
x
y
=
y
0
+
F
y
\begin{cases} x=x_0+F_x\\ y=y_0+F_y \end{cases}
{x=x0+Fxy=y0+Fy
扩展得到矩阵变换方法为:
[
x
y
1
]
=
[
1
0
F
x
0
1
F
y
0
0
1
]
[
x
0
y
0
1
]
\left[ \begin{array}{ccc} x\\ y\\ 1 \end{array} \right]= \left[ \begin{array}{ccc} 1&0&F_x\\ 0&1&F_y\\ 0&0&1\\ \end{array} \right] \left[ \begin{array}{ccc} x_0\\ y_0\\ 1 \end{array} \right]
⎣⎡xy1⎦⎤=⎣⎡100010FxFy1⎦⎤⎣⎡x0y01⎦⎤
代码实现为:
M=np.array([
[1,0,100],
[0,1,100]
],dtype=np.float32)#dtype=np.float32变换时用浮点型
img2=cv.warpAffine(bear,M,(400,600))
show(img2)
#M为变换矩阵
#warpAffine为仿射变换,将原xy乘M矩阵后得到的矩阵
#(400,600)变换后的总尺寸
变换效果为:
3.错切变换
若记原像素位置坐标为
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0),变换后的坐标为
(
x
,
y
)
(x,y)
(x,y),
β
\beta
β代表错切角度,水平错切公式表示为:
{
x
=
x
0
+
t
a
n
β
y
0
y
=
y
0
\begin{cases} x=x_0+tan\beta y_0\\ y=y_0 \end{cases}
{x=x0+tanβy0y=y0
扩展得到矩阵变换方法为:
[
x
y
1
]
=
[
1
t
a
n
β
0
0
1
0
0
0
1
]
[
x
0
y
0
1
]
\left[ \begin{array}{ccc} x\\ y\\ 1 \end{array} \right]= \left[ \begin{array}{ccc} 1&tan\beta&0\\ 0&1&0\\ 0&0&1\\ \end{array} \right] \left[ \begin{array}{ccc} x_0\\ y_0\\ 1 \end{array} \right]
⎣⎡xy1⎦⎤=⎣⎡100tanβ10001⎦⎤⎣⎡x0y01⎦⎤
同理,竖直错切公式为:
{
x
=
x
0
y
=
y
0
+
t
a
n
β
x
0
\begin{cases} x=x_0\\ y=y_0+tan\beta x_0 \end{cases}
{x=x0y=y0+tanβx0
扩展得到矩阵变换方法为:
[
x
y
1
]
=
[
1
0
0
t
a
n
β
1
0
0
0
1
]
[
x
0
y
0
1
]
\left[ \begin{array}{ccc} x\\ y\\ 1 \end{array} \right]= \left[ \begin{array}{ccc} 1&0&0\\ tan\beta&1&0\\ 0&0&1\\ \end{array} \right] \left[ \begin{array}{ccc} x_0\\ y_0\\ 1 \end{array} \right]
⎣⎡xy1⎦⎤=⎣⎡1tanβ0010001⎦⎤⎣⎡x0y01⎦⎤
代码实现为:
beta=np.pi/6
#水平错切
M=np.array([
[1,np.tan(beta),0],
[0,1,0],
],dtype=np.float32)
img2=cv.warpAffine(bear,M,(700,500))
show(img2)
#竖直错切
M=np.array([
[1,0,0],
[np.tan(beta),1,0],
],dtype=np.float32)
img3=cv.warpAffine(bear,M,(333,700))
show(img3)
#M为变换矩阵
#warpAffine为仿射变换,将原xy乘M矩阵后得到的矩阵
变换效果为:
3.镜像变换
若记原像素位置坐标为
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0),变换后的坐标为
(
x
,
y
)
(x,y)
(x,y),
F
w
F_w
Fw代表图像宽度,以水平镜像为例,镜像错切公式表示为:
{
x
=
−
x
0
+
F
w
y
=
y
0
\begin{cases} x=-x_0+F_w\\ y=y_0 \end{cases}
{x=−x0+Fwy=y0
扩展得到矩阵变换方法为:
[
x
y
1
]
=
[
−
1
0
F
w
0
1
0
0
0
1
]
[
x
0
y
0
1
]
\left[ \begin{array}{ccc} x\\ y\\ 1 \end{array} \right]= \left[ \begin{array}{ccc} -1&0&F_w\\ 0&1&0\\ 0&0&1\\ \end{array} \right] \left[ \begin{array}{ccc} x_0\\ y_0\\ 1 \end{array} \right]
⎣⎡xy1⎦⎤=⎣⎡−100010Fw01⎦⎤⎣⎡x0y01⎦⎤
代码实现为:
w=333
M=np.array([
[-1,0,w],
[0,1,0]
],dtype=np.float32)
img2=cv.warpAffine(bear,M,(333,500))
show(np.hstack([bear,img2]))
OpenCV有自带的镜像变换方法:
img2=cv.flip(bear,0)
img3=cv.flip(bear,1)
img4=cv.flip(bear,-1)
show(np.hstack([bear,img2,img3,img4]))
#flipcode为0竖直,为1水平,为-1是180镜像
效果(原图,flipcode=0,flipcode=1,flipcode=-1)
4.旋转变换
若记原像素位置坐标为
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0),变换后的坐标为
(
x
,
y
)
(x,y)
(x,y),
β
\beta
β代表图像旋转角度。
{
x
0
=
r
c
o
s
a
y
0
=
r
s
i
n
a
x
=
r
c
o
s
(
a
−
β
)
y
=
r
s
i
n
(
a
−
β
)
\begin{cases} x_0=rcosa\\ y_0=rsina\\ x=rcos(a-\beta)\\ y=rsin(a-\beta) \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x0=rcosay0=rsinax=rcos(a−β)y=rsin(a−β)
由以上极坐标公式,推得旋转变换公式表示为:
{
x
=
x
0
c
o
s
β
+
y
0
s
i
n
β
y
=
−
x
0
s
i
n
β
+
y
0
c
o
s
β
\begin{cases} x=x_0cos\beta+y_0sin\beta\\ y=-x_0sin\beta+y_0cos\beta \end{cases}
{x=x0cosβ+y0sinβy=−x0sinβ+y0cosβ
扩展得到矩阵变换方法为:
[
x
y
1
]
=
[
c
o
s
β
s
i
n
β
0
−
s
i
n
β
c
o
s
β
0
0
0
1
]
[
x
0
y
0
1
]
\left[ \begin{array}{ccc} x\\ y\\ 1 \end{array} \right]= \left[ \begin{array}{ccc} cos\beta&sin\beta&0\\ -sin\beta&cos\beta&0\\ 0&0&1\\ \end{array} \right] \left[ \begin{array}{ccc} x_0\\ y_0\\ 1 \end{array} \right]
⎣⎡xy1⎦⎤=⎣⎡cosβ−sinβ0sinβcosβ0001⎦⎤⎣⎡x0y01⎦⎤
代码实现为:
beta=np.pi/4
M=np.array([
[np.cos(beta),np.sin(beta),0],
[-np.sin(beta),np.cos(beta),0]
],dtype=np.float32)
img2=cv.warpAffine(bear,M,(700,500))
show(img2)
OpenCV自带有旋转变换的方法:
h,w,c=bear.shape
M=cv.getRotationMatrix2D((w//2,h//2),45,1)
#通过自带方法得到变换矩阵M,其中(w//2,h//2)是图片旋转中心
img2=cv.warpAffine(bear,M,(500,500))
show(img2)
5.透视变换
透视变换需要获取原变换图形当中透视图形的四个端点(红点)和欲变换后的四个端点(绿点)得到M矩阵,进而处理图像。
代码实现为:
#原坐标
src=np.array([
[200,50],
[600,250],
[650,500],
[150,450]
],dtype=np.float32)
#目标坐标
dst=np.array([
[150,100],
[650,100],
[650,450],
[150,450]
],dtype=np.float32)
#根据原,目标坐标得到M矩阵
M=cv.getPerspectiveTransform(src,dst)#得到M矩阵
h,w,c=img.shape
img2=cv.warpPerspective(img,M,(w,h))
show(img2)
效果: