赞
踩
图像几何变换是指对图像进行缩放、平移、旋转、仿射变换、偏移变换等。首先明确一点,图像是以矩阵存储的,所以对图像的操作即是对矩阵的操作,对图像的平移、旋转、变换等就是对矩阵的平移、旋转、变换。
我们知道在线性代数中,要使得矩阵X变换到矩阵Y,需要一个变换矩阵设为M,偏移量设为B,可以用公式表示:
Y
=
M
⋅
X
T
+
B
Y=M·X^T+B
Y=M⋅XT+B
一下为常用的变换矩阵M(有可能和其他地方给出的矩阵不太一样,这取决于是
M
⋅
X
T
M·X^T
M⋅XT还是
X
T
∗
M
X^T*M
XT∗M):
当图像放大时,会有更多的屏幕点来表示图像,产生的新的点的像素值怎么办?就需要图像内插的方法
图像内插:用已知数据来估计未知位置的数值的处理。放大、收缩、旋转和几何校正等任务。基本的三种内插方法(放大图像像素增加)
a. 最邻近内插法:四个近邻的像素放大后产生田字区域,每个口中的像素值取该口顶点的值,将明显产生马赛克感觉
b. 双线性内插:用4领域估计给定位置灰度值用
a. 双三次内插,8邻域
来看openCV关于图像缩放的函数
插值方法 | 插值方法 |
---|---|
cv2.INTER_NEAREST | 最近邻插值 |
cv2.INTER_LINEAR | 双线性插值(默认) |
cv2.INTER_CUBIC | 双线性插值 |
cv2.INTER_AREA | 使用像素区域关系重新采样(推荐) |
import cv2
img=cv2.imread("color.jpg")
# 长*0.7,宽*0.7
img_small=cv2.resize(img,None,fx=0.7,fy=0.7,interpolation=cv2.INTER_AREA)
# 直接缩放到(256,256)
img_256=cv2.resize(img,(256,256),interpolation=cv2.INTER_AREA)
cv2.imshow("img",img)
cv2.imshow("img_small",img_small)
cv2.imshow("img_256",img_256)
cv2.waitKey(0)
如果沿(x,y)方向移动,移动的距离是
(
t
x
,
t
y
)
(t_x,t_y)
(tx,ty),则变换矩阵为:
M
=
[
1
0
t
x
0
1
t
y
]
M=\left[
我们只需要将img矩阵和M矩阵做运算即可,在这里我们使用:
如何定义矩阵M?使用numpy:
M = np.array([[1, 0, 100], [0, 1, 100]],dtype=np.float32)
import cv2
import numpy as np
img = cv2.imread("color.jpg")
size=img.shape[0:2] # 获取 图像的宽高
# 定义t_x=100 t_y=100的变换矩阵
M = np.array([[1, 0, 100], [0, 1, 100]],dtype=np.float32)
# 传入img和变换矩阵,定义输出图像的尺寸为size(size就是上面定义的原图大小)
res = cv2.warpAffine(img, M, size)
cv2.imshow("",res)
cv2.waitKey(0)
如果旋转角度为θ,则变换矩阵应该为:
M
=
[
c
o
s
θ
−
s
i
n
θ
0
s
i
n
θ
c
o
s
θ
0
]
M=\left[
import cv2 import numpy as np img = cv2.imread("color.jpg") size=img.shape[0:2] # np.pi:兀 theta=np.pi/3 # 60° sin=np.sin(theta) cos=np.cos(theta) M = np.array([[cos, -sin,0], [sin, cos,0]],dtype=np.float32) print(M) res = cv2.warpAffine(img, M, size) cv2.imshow("img",img) cv2.imshow("res",res) cv2.waitKey(0)
使用openCV提供的函数来定义矩阵M:
import cv2
import numpy as np
img = cv2.imread("color.jpg")
rows,cols=img.shape[0:2]
# 定义一个以图像中心为旋转点,旋转45°,缩放0.6倍的变换矩阵M
M=cv2.getRotationMatrix2D((rows/2,cols/2),45,0.6)
res = cv2.warpAffine(img, M,(rows,cols))
cv2.imshow("img",img)
cv2.imshow("res",res)
cv2.waitKey(0)
什么是仿射变换?仿射变换后的图像中,原来是平行的两条线现在任然是平行的。
由于透视效果,原本两队边应该平行,但拍摄出来不平行,所以仿射矫正后两队边依然不平行,但是已经有比较好的效果了(如果要做到极致当然需要其他方法)
现在假设我们有原图A图像和标准图B图像,那么如果通过仿射变换将A图转换为B图?
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread("QR.JPG") # 二维码原图像 rows, cols = img.shape[0:2] # 获取图像宽高 # 分别代表原图中三个位置探测图像的坐标 pts1 = np.float32([[132, 378], [83, 195], [256, 92]]) # 分别代表标准二维码中三个位置探测图像的坐标 pts2 = np.float32([[34, 395], [34, 34], [395, 34]]) M = cv2.getAffineTransform(pts1, pts2) #计算原图到标准图的变换矩阵M # 根据矩阵M将img转变到标准图像(但由于透视效果,原本两队边应该平行,但拍摄 # 出来不平行,所以仿射矫正后两队边依然不平行,但是已经有比较好的效果了) res = cv2.warpAffine(img, M, (rows*2, cols*2)) plt.rcParams['font.sans-serif']=['SimHei'] plt.subplot(121),plt.imshow(img),plt.title('原图像') plt.subplot(122),plt.imshow(res),plt.title('结果图') plt.show()
未完待续
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。