Python OpenCV3:OpenCV 几何变换
Posted sxqczzxsh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python OpenCV3:OpenCV 几何变换相关的知识,希望对你有一定的参考价值。
1. 图像缩放
缩放是调整图像的大小,即放大或缩小。
cv2.resize(src, dsize, fx, fy, interpolation)
参数:
src 输入图像
dsize 绝对尺寸,直接指定调整后图像的大小
fx,fy 相对尺寸,将dsize设置为None,然后将fx和fy设置为比例因子即可
interpolation 插值方法:
cv.INTER_LINEAR 双线性插值
cv.INTER_NEAREST 最近邻插值
cv.INTER_AREA 像素区域重采样(默认)
cv.INTER_NEAREST 最近邻插值
例1:使用绝对和相对尺寸的方法缩放图片。
图片尺寸374*500
import cv2 as cv
import matplotlib
from matplotlib import pyplot as plt
font = {
"family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)
kids = cv.imread("./image/kids.jpg")
# 获取size
rows, cols = kids.shape[:2]
print(rows, cols)
# 绝对尺寸
res = cv.resize(kids, (2 * cols, 2 * rows))
plt.imshow(res[:, :, ::-1])
plt.title("指定像素放大2倍")
plt.show()
print(res.shape)
# 相对尺寸
res1 = cv.resize(kids, None, fx=0.5, fy=0.5)
plt.imshow(res1[:, :, ::-1])
plt.title("指定像素放大2倍")
plt.show()
print(res1.shape)
输出:
374 500
(748, 1000, 3)
(187, 250, 3)
2. 图像平移
将图像根据指定的方向和距离,移动到相应的位置。
cv.warpAffine(img, M, dsize)
参数:
img 输入图像
M 2∗*∗3移动矩阵
dsize 输出图像的大小
输出图像的大小是(宽度, 高度)的形式,width=列数,height=行数。空余部分用黑色填充。
对于(x,y)处的像素点,要把它移动到处时,M矩阵应如下设置:
注意:将M设置为np.float32类型的NumPy数组。
例2:平移图像。
import cv2 as cv
import matplotlib
import numpy as np
from matplotlib import pyplot as plt
font = {
"family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)
kids = cv.imread("./image/kids.jpg")
# 获取size
rows, cols = kids.shape[:2]
# 定义M矩阵
M = np.float32([[1, 0, 100], [0, 1, 50]])
# 移动
res2 = cv.warpAffine(kids, M, (2 * cols, 2 * rows))
plt.imshow(res2[:, :, ::-1])
plt.title("移动")
plt.show()
输出:
3. 图像旋转
图像旋转是指将图像按照一定的位置旋转一定的角度的过程,图像在旋转过程中仍然保持原来的大小。图像旋转后,水平对称轴、垂直对称轴和图像中心坐标的原点可能会发生变换,因此图像旋转中的坐标也需要进行相应的变换。
图像逆时针旋转θ,则根据坐标转换可得旋转转换为:
其中,
代入得:
或者写成旋转矩阵乘法的形式:
同时,必须修正原点的位置。 原图坐标原点在图像左上角,旋转后图像大小会发生变化,原点也需要修正。假设旋转时坐标原点为旋转中心,旋转后需要将坐标原点移动到图像的左上角。
在OpenCV中,图像旋转首先根据旋转角度和旋转中心得到旋转矩阵,然后根据旋转矩阵对图像进行变换,实现任意角度、任意中心的旋转效果。
cv.getRotationMatrix2D(center, angle, scale)
参数:
center 旋转中心 (col, row)
angle 旋转角度
scale 缩放比例
返回值:
旋转矩阵M。
然后,调用cv.warpAffine()完成图像的旋转。
例3:将上述图像逆时针旋转45°。
import cv2 as cv
import matplotlib
from matplotlib import pyplot as plt
font = {
"family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)
kids = cv.imread("./image/kids.jpg")
# 获取size
rows, cols = kids.shape[:2]
# 获取旋转矩阵M 旋转中心为图像中心,缩小为0.5倍
M = cv.getRotationMatrix2D((cols / 2, rows / 2), 45, 0.5)
print(M)
# 旋转
res3 = cv.warpAffine(kids, M, (cols, rows))
plt.imshow(res3[:, :, ::-1])
plt.title("旋转45°")
plt.show()
输出:
[[ 0.35355339 0.35355339 95.49716831]
[ -0.35355339 0.35355339 209.27386361]]
4. 仿射变换
图像的仿射变换涉及图像的形状、位置和角度的变化。仿射变换主要是图像的缩放、旋转、翻转和平移等操作的组合。
如下图所示,Image 1中的1、2、3点一一映射到Image 2中的三个点上,依旧是一个三角形,只是形状有了很大的变化。可以通过这两组的三个点进行模拟,然后对图像中的所有点进行仿射变换,完成图像的仿射变换。
在OpenCV中,仿射变换的矩阵是一个2×3的矩阵:
其中左边的2×2矩阵A是线性变换矩阵,右边的2×1矩阵B是平移项:
对于图像上的任一位置(x,y),仿射变换执行的是如下的操作:
在仿射变换中,原图中所有的平行线在结果图像中同样平行。
cv.getAffineTransform(pts1, pts2)
参数:
从原图像中找到3个点以及他们在输出图像中的位置。
输出:
变换矩阵M。
然后,调用cv.warpAffine()完成图像的仿射变换。
例4:将上述图像进行仿射变换。
import cv2 as cv
import matplotlib
import numpy as np
from matplotlib import pyplot as plt
font = {
"family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)
kids = cv.imread("./image/kids.jpg")
# 获取size
rows, cols = kids.shape[:2]
# 平移,使图像显示完整
M = np.float32([[1, 0, 150], [0, 1, 150]])
# 移动
res4 = cv.warpAffine(kids, M, (cols * 2, rows * 2))
# 原图像中3个点
pts1 = np.float32([[200, 200], [500, 200], [500, 500]])
# 变换后的这3个点
pts2 = np.float32([[200, 200], [600, 200], [700, 500]])
# 获得变换矩阵M
M = cv.getAffineTransform(pts1, pts2)
print(M)
res4 = cv.warpAffine(res4, M, (cols * 2, rows * 2))
plt.imshow(res4[:, :, ::-1])
plt.title("仿射变换")
plt.show()
输出:
[[ 1.33333333 0.33333333 -133.33333333]
[ 0. 1. 0. ]]
5. 透射变换
透射变换是视角变化的结果,指利用透视中心、像点、目标点的三点共线条件,按透视旋转定律使承载面(透视面)围绕迹线(透视轴)按一定角度旋转,破坏原有的投影光束,仍然保持承影面上投影几何图形不变的变换。
它的本质是将图像投影到一个新的视平面,其通用变换公式为:
其中,(u,v)是原始的图像像素坐标,w取值为1,(x=x'/z',y=y'/z')是透射变换后的结果。后面的矩阵称为透视变换矩阵,一般情况下,我们将其分为三部分:
其中:T1表示对图像进行线性变换,T2对图像进行平移,T3表示对图像进行投射变换,a22一般设为1。
cv.getPerspectiveTransform(pts1, pts2)
参数:
从原图像和变换后的图像找到对应的4个点,其中任意三个不共线。
返回值:
变换矩阵T。
然后,调用cv.warpAffine()完成图像的透射变换。
例5:将上述图像进行透射变换。
import cv2 as cv
import matplotlib
import numpy as np
from matplotlib import pyplot as plt
font = {
"family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)
kids = cv.imread("./image/kids.jpg")
# 获取size
rows, cols = kids.shape[:2]
pst1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pst2 = np.float32([[100, 145], [300, 100], [80, 290], [310, 300]])
# 变换矩阵T
T = cv.getPerspectiveTransform(pst1, pst2)
print(T)
res5 = cv.warpPerspective(kids, T, (cols, rows))
plt.imshow(res5[:, :, ::-1])
plt.title("透射变换")
plt.show()
输出:
[[ 3.98327670e-01 -2.09876559e-02 7.49460064e+01]
[-1.92233080e-01 4.29335771e-01 1.21896057e+02]
[-7.18774228e-04 -1.33393850e-05 1.00000000e+00]]
6. 图像金字塔
图像金字塔是图像的一种多尺度表示,主要用于图像分割。它是一种有效但简单的概念结构,可以解释具有多种分辨率的图像。
图像的金字塔是由相同的原始图像派生出来的、以金字塔形状排列且分辨率逐渐降低的图像的集合。它是通过逐步降采样得到的,直到达到某个终止条件才停止采样。金字塔的底部是要处理的图像的高分辨率表示,顶部是低分辨率的近似值。层级越高,图像越小,分辨率越低。
cv.pyrUp(img) 对图像进行上采样
cv.pyrDown(img) 对图像进行下采样
例6:将上述图像进行上采样和下采样变换。
import cv2 as cv
import matplotlib
from matplotlib import pyplot as plt
font = {
"family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)
kids = cv.imread("./image/kids.jpg")
# 获取size
rows, cols = kids.shape[:2]
imgup = cv.pyrUp(kids)
plt.imshow(imgup[:, :, ::-1])
plt.title("上采样变换")
plt.show()
imgdown = cv.pyrDown(kids)
plt.imshow(imgdown[:, :, ::-1])
plt.title("下采样变换")
plt.show()
输出:
以上是关于Python OpenCV3:OpenCV 几何变换的主要内容,如果未能解决你的问题,请参考以下文章