OpenCV Python 几何变换

【目标】

  • 学习平移、旋转、缩放、仿射变换、透视变换
  • cv2.getPerspectiveTransform

仿射变换是平面内的,是多次线性变换的结果,保留了平行性,用3个点就可得到对应的变换矩阵。
透视变换 2D-3D,必须用4个点才能得到变换矩阵;

  • 平移

opencv半透明效果 opencv透视变换python_仿射变换

  • 缩放

opencv半透明效果 opencv透视变换python_opencv_02

  • 旋转

opencv半透明效果 opencv透视变换python_opencv半透明效果_03

  • 错切

opencv半透明效果 opencv透视变换python_opencv半透明效果_04

  • 仿射变换

opencv半透明效果 opencv透视变换python_opencv_05

  • 透视变换

opencv半透明效果 opencv透视变换python_opencv_06

其中,假定 opencv半透明效果 opencv透视变换python_opencv_07

opencv半透明效果 opencv透视变换python_仿射变换_08

从上述公式可以看出,需要4个点

【代码】

  • OpenCV Python 图像缩放

opencv半透明效果 opencv透视变换python_仿射变换_09

import numpy as np
import cv2
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)

cv2.imshow("img", img)
cv2.imshow("res", res)

cv2.waitKey(0)
cv2.destroyAllWindows()
  • OpenCV Python 图像平移

opencv半透明效果 opencv透视变换python_python_10

import numpy as np
import cv2

img = cv2.imread('messi5.jpg', 0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img, M, (cols,rows))
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • OpenCV Python 图像旋转

opencv半透明效果 opencv透视变换python_python_11

import numpy as np
import cv2

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

rows,cols = img.shape
# cols-1 and rows-1 are the coordinate limits.
M = cv2.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv2.warpAffine(img,M,(cols, rows))

cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • OpenCV Python 仿射变换

opencv半透明效果 opencv透视变换python_仿射变换_12

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


img = cv2.imread('drawing.png')
rows,cols,ch = img.shape
pts1 = np.float32([[20,20],[110,20],[50,110]])
pts2 = np.float32([[10,50],[120,40],[30,150]])
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()
  • OpenCV Python 图像透视变换

opencv半透明效果 opencv透视变换python_opencv_13

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

img = cv2.imread('sudoku.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()

【接口说明】

  • cv2.warpAffine(img, M, (cols,rows))
void cv::warpAffine	(	InputArray 	src,
OutputArray 	dst,
InputArray 	M,
Size 	dsize,
int 	flags = INTER_LINEAR,
int 	borderMode = BORDER_CONSTANT,
const Scalar & 	borderValue = Scalar() 
);
cv2.warpAffine(	src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]	) ->	dst

对一个图像进行仿射变换
src: 输入图像
dst: 输出图像,像素类型和源图像一致,尺寸可以指定
M: 2x3的变换矩阵
dsize: 输出图像的尺寸
flags: 插值方法,见InterpolationFlags
borderMode: 边缘模式,见下面的BorderTypes
borderValue: 默认为0,当边缘模式为 constant时,填充的值

InterpolationFlags

opencv半透明效果 opencv透视变换python_缩放_14

BorderTypes

opencv半透明效果 opencv透视变换python_缩放_15

  • cv2.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
Mat cv::getRotationMatrix2D	(	Point2f 	center,
double 	angle,
double 	scale 
);
cv2.getRotationMatrix2D(	center, angle, scale	) ->	retval

通过 中心点,旋转角度和尺度 来计算仿射变换矩阵
center: 源图像的旋转中心
angle: 旋转角度
scale: 各项同性变化因子

opencv半透明效果 opencv透视变换python_opencv半透明效果_16

  • cv2.getAffineTransform(pts1,pts2)
// 
Mat cv::getAffineTransform(const Point2f 	src[],
const Point2f 	dst[] 
);

Mat cv::getAffineTransform(InputArray 	src,
InputArray 	dst 
);
cv2.getAffineTransform(	src, dst	) ->	retval

通过变换前的点和变换后的点计算仿射变换矩阵,提供3对点就可以了
src: 源图像的顶点
dst: 仿射变换后的顶点

  • cv2.getPerspectiveTransform(pts1, pts2)
Mat cv::getPerspectiveTransform	(	InputArray 	src,
InputArray 	dst,
int 	solveMethod = DECOMP_LU 
);

Mat cv::getPerspectiveTransform	(	const Point2f 	src[],
const Point2f 	dst[],
int 	solveMethod = DECOMP_LU 
);
cv2.getPerspectiveTransform(	src, dst[, solveMethod]	) ->	retval

计算透射变换矩阵, 至少4个点
src: 输入点集
dst: 变换后的点集
solveMethod: 矩阵分解类型

DecompTypes

opencv半透明效果 opencv透视变换python_仿射变换_17

  • cv2.warpPerspective(img, M, (300, 300))
void cv::warpPerspective	(	InputArray 	src,
OutputArray 	dst,
InputArray 	M,
Size 	dsize,
int 	flags = INTER_LINEAR,
int 	borderMode = BORDER_CONSTANT,
const Scalar & 	borderValue = Scalar() 
);
cv2.warpPerspective(	src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]	) ->	dst
透视变换
src: 输入图像
dst: 输出图像,像素类型和源图像一致,尺寸可以指定
M: 2x3的变换矩阵
dsize: 输出图像的尺寸
flags: 插值方法,见InterpolationFlags
borderMode: 边缘模式,见下面的BorderTypes
borderValue: 默认为0,当边缘模式为 constant时,填充的值

【参考】

  1. opencv 官网
  2. 【opencv实践】仿射变换和透视变换
  3. 几何变换中的仿射变换和透视变换的原理
  4. 番外篇: 仿射变换与透视变换