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 几何变换的主要内容,如果未能解决你的问题,请参考以下文章

python opencv3 静态图片检测人脸

python opencv3 检测人

opencv配置(win10+VS2015+opencv3.1)

python opencv3 图像与原始字节转换

python opencv3 向图像里写字

python opencv3 轮廓检测