OpenCV图像处理
图像的几何变换
Opencv提供两种变换函数,cv2.warpAffine()和cv2.warpPerspective()。基于这两个函数可以得到所有类型的变换。
- cv2.warpAffine() 以一个 2 × 3 2 \times 3 2×3变换矩阵为输入
- cv2.warpPerspective() 以一个 3 × 3 3 \times 3 3×3变换矩阵为输入
转换
转换(Translation)是物体位置的转移。如果在
(
x
,
y
)
\left( x, y \right)
(x,y)方向上的偏移量为
(
t
x
,
t
y
)
\left( t_{x}, t_{y} \right)
(tx,ty),那么变换矩阵
M
M
M可如下定义。将
M
M
M以类型为np.float32的numpy数组表示,然后将其传入到cv2.warpAffine() 函数中
M
=
[
1
0
t
x
0
1
t
y
]
M = \left [ \begin{matrix} 1 & 0 & t_{x}\\ 0 & 1 & t_{y} \end{matrix} \right ]
M=[1001txty]
import cv2
import numpy as np
img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
# 偏移量为(100,50)
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
旋转
得到一个旋转角度为
θ
\theta
θ的图像的变换矩阵
M
M
M定义如下:
M
=
[
c
o
s
θ
−
s
i
n
θ
s
i
n
θ
c
o
s
θ
]
M = \left [ \begin{matrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{matrix} \right ]
M=[cosθsinθ−sinθcosθ]
OpenCV提供了可调整旋转中心的缩放旋转,以至于可以以任何位置为中心旋转。调整后的变换矩阵定义如下:
M
=
[
α
β
(
1
−
α
)
⋅
c
e
n
t
e
r
.
x
−
β
⋅
c
e
n
t
e
r
.
y
−
β
α
β
⋅
c
e
n
t
e
r
.
x
+
(
1
−
α
)
⋅
c
e
n
t
e
r
.
y
]
M = \left [ \begin{matrix} \alpha & \beta & \left( 1- \alpha \right) \cdot center.x - \beta \cdot center.y \\ -\beta& \alpha & \beta \cdot center.x + \left( 1- \alpha \right) \cdot center.y \end{matrix} \right ]
M=[α−ββα(1−α)⋅center.x−β⋅center.yβ⋅center.x+(1−α)⋅center.y]
其中
α
=
s
c
a
l
e
⋅
c
o
s
θ
β
=
s
c
a
l
e
⋅
s
i
n
θ
\begin{matrix} \alpha = scale \cdot cos \theta \\ \beta = scale \cdot sin\theta \end{matrix}
α=scale⋅cosθβ=scale⋅sinθ
Opencv提供了cv2.getRotationMatrix2D()函数寻找变换矩阵。
img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
# 没有缩放,旋转图像90度
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
仿射变换
仿射变换(Affine Transformation)是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。那么每个仿射变换可以由一个矩阵 A A A和一个向量 b b b给出,假设原图像为 X X X,目标图像为 Y Y Y,仿射变换可用公式表示为 Y = A ⋅ X + b Y = A \cdot X + b Y=A⋅X+b。
仿射变换,在原图中所有平行的线条在输入图像中仍然平行。OpenCV提供了cv2.getAffineTransform()函数得到一个 2 × 3 2 \times 3 2×3的变换矩阵,传送给cv2.warpAffine() 函数。
为了得到变换矩阵,需要原图中的三个点和这三个点在输出图像中的位置。
img = cv2.imread('drawing.png')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
透视变换
透视变换(Perspective Transformation)是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。 --百度百科
透视变换需要一个 3 × 3 3 \times 3 3×3大小的变换矩阵。为了得到变换矩阵,需要原图中的四个点和这三个点在输出图像中的相应位置。并且四个点中的三个不能在一条直线上。OpenCV提供cv2.getPerspectiveTransform() 函数得到变换矩阵,然后传送给cv2.warpPerspective() 函数。
img = cv2.imread('sudokusmall.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
边框矩形
边框矩形有两种形式,一种是直边矩形(Straight Bounding rectangle),一种是最小面积的边框矩形,被称为旋转矩形(Rotated Rectangle)。直边矩形不考虑物体的角度,因此,直边矩形的面积不是最小的。旋转矩形考虑物体的旋转角度。下图中的青色矩形就是直边矩形,红色矩形是旋转矩形。
直边矩形
OpenCV中提供了**cv2.boundingRect()**函数提供直边矩形。
# x,y是矩形的左上坐标,w,h是宽和高
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
旋转矩形
OpenCV中提供cv2.minAreaRect() 函数提供旋转矩形。返回左上坐标为 ( x , y ) \left( x,y\right) (x,y),宽和高为 ( w , h ) \left( w, h\right) (w,h),旋转角度为 θ \theta θ的2D边框。为了能够绘制矩形,需要借助cv2.boxPoints()函数得到矩形的4个角坐标。
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
im = cv2.drawContours(im,[box],0,(0,0,255),2)