OpenCV-Python -- Geometric Transformations of Images

学习目标

  • 对图像进行几何变换,比如平移,旋转,仿射变换,透视变换等。
  • 学习函数:cv2.getPerspectiveTransform

变换(Transformations)

OpenCV提供两种变换函数,cv2.warpAffinecv2.warpPerspective,它们可以生成所有种类的变换。cv2.warpAffine的输入是2x3变换矩阵, cv2.warpPerspective的输入为3x3变换矩阵。

缩放(Scaling)

缩放即是改变图像的大小,函数为cv2.resize()。输出的大小可以人为指定,也可以指定缩放因子。缩放的内部算法为不同的插值方法,常用的有cv2.INTER_AREA,用于将图像变小。cv2.INTER_CUBIC(该方法会慢一些)和cv2.INTER_LINEAR用于将图像放大。默认情况下,使用cv2.INTER_LINEAR方法。具体使用如下:

import cv2
import numpy as np

img = cv2.imread('messi5.jpg')

res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)

#OR

height, width = img.shape[:2]
res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
平移(Translation)

平移就是将目标对象移动。如果知道移动的方向为(x,y),令其为 ( t x , t y ) (t_x,t_y) (tx,ty),那么构造的平移矩阵M为:
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]
可以将其转为Numpy数组,然后传入函数cv2.warpAffine,见例子如下:

import cv2
import numpy as np

img = cv2.imread('messi5.jpg', 1)
rows, cols = img.shape[:2]
cv2.imshow('img', img)

M1 = np.float32([[1, 0, 100], [0, 1, 50]])
M2 = np.float32([[1, 0, -100], [0, 1, -50]])
# (cols, rows):输出图像的宽和高
dst1 = cv2.warpAffine(img, M1, (cols, rows))
dst2 = cv2.warpAffine(img, M2, (cols, rows))

cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

旋转(Rotation)

旋转图像为角度 θ \theta θ的 变换矩阵为如下形式:
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 & (1-\alpha)*center.x-\beta*center.y \\ -\beta & \alpha & \beta*center.x+(1-\alpha)*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{aligned} \alpha=&scale*cos\theta \\ \beta=&scale*sin\theta \end{aligned} α=β=scalecosθscalesinθ
为了生成变换矩阵,OpenCV提供了函数cv2.getRotationMatrix2D,下面的例子给出了如何操作,并且没有缩放:
cv2.getRotationMatrix2D(center,angle,scale)的参数如下:

  1. center:旋转中心。
  2. angle:旋转角度。
  3. scale:是否缩放。
import cv2
import numpy as np

img = cv2.imread('messi5.jpg', 1)
rows, cols = img.shape[:2]
# img_copy = img  # 二者共享内存,一个改变,另一个也发生改变
img_copy = img.copy()  # 一个改变,不会相互影响

a = np.array([[150, 150], [150, 200], [60, 80], [200, 180]])
print(a)
for i in range(4):
    cv2.circle(img_copy, (a[i][0], a[i][1]), 6, (0, 255, 0), -1)
cv2.imshow('img', img_copy)
cv2.waitKey(0)

# 旋转
center = (cols / 2, rows / 2)  # 不同的旋转中心得到的效果差别较大
M3 = cv2.getRotationMatrix2D(center, 30, 1)
print('M3\n', M3)

dst3 = cv2.warpAffine(img, M3, (cols, rows))

cv2.imshow('dst3', dst3)
cv2.waitKey(0)

将原图拷贝,并在拷贝图上画绿色点,见下图:
在这里插入图片描述
img_copy = img.copy() 拷贝方式,不会更改原图img,所以原图没有受影响,画原图的时候,没有出现绿色点,见下图:
在这里插入图片描述
img_copy = img,这种拷贝方式,使得原图受影响,虽然显示的是原图,但是出现绿色点,见下图:
在这里插入图片描述

仿射变换(Affine Transformation)

在仿射变换中,所有的平行线在输出图中仍然是平行线。为了生成变换矩阵,我们需要在输入和输出图中分别设置3个点的位置。那么,可以根据函数cv2.getAffineTransform 生成2x3变换矩阵,传入函数cv2.warpAffine,例子如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt

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)

透视变换需要3x3变换矩阵,变换前后直线仍是直线。为了生成变换矩阵,输入和输出图上分别设定4个点,并且任意三个点不能共线。生成变换矩阵的函数如下:

# 1. 生成变换矩阵
   cv2.getPerspectiveTransform()
# 2. 应用变换矩阵
   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()

结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值