前言:Hello大家好,我是小哥谈。OpenCV中的几何变换是指改变图像的几何结构,例如大小、角度和形状等,让图像呈现出缩放、翻转、旋转和透视效果。这些几何变换操作都涉及复杂、精密的计算。OpenCV将这些计算过程都封装成了非常灵活的方法,开发者只需要修改一些参数,就可以看到图像的变换效果。本节课就介绍几种常见的几何变换效果及其实现方法。
史上最全OpenCV常用方法及使用说明汇总,建议收藏!
OpenCV基础知识(1)— OpenCV概述
OpenCV基础知识(2)— 图像处理的基本操作
OpenCV基础知识(3)— 图像数字化基础(像素、色彩空间)
OpenCV基础知识(4)— 绘制图形
目录
1.缩放
1.1 dsize参数实现缩放
1.2 fx参数和fy参数实现缩放
2.翻转
3.旋转
4.透视
“缩”表示缩小,“放”表示放大,通过OpenCV中提供的resize()方法就可以随意更改图像的大小比例,其语法格式如下:
dst = cv2.resize(src,dsize,fx,fy,interpolation)
参数说明:
src:原始图像
dsize:输出图像的大小,格式为(宽,高),单位为像素。
fx:可选参数。水平方向的缩放比例。
fy:可选参数。垂直方向的缩放比例。
interpolation:可选参数。缩放的插值方式,在图像缩小或者放大时需要删减或补充像素,该参数可以指定使用哪种算法对像素进行增减。建议使用默认值。
返回值说明:
dst:缩放之后的图像
resize()方法有两种使用方式,一种是通过dsize参数实现缩放,另一种是通过 fx 和 fy 参数实现缩放,下面分别进行介绍。
dsize参数的格式是一个元组,例如(100,200),表示将图像按照宽100像素、高200像素的大小进行缩放。如果使用dsize参数,则可以不写 fx 和 fy 参数。
代码如下:
import cv2
img = cv2.imread("1.jpg") # 读取图像
dst1 = cv2.resize(img, (300, 300)) # 按照宽300像素、高300像素的大小进行缩放
cv2.imshow("img", img) # 显示原图
cv2.imshow("dst1", dst1) # 显示缩放图像
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
原始图像:
缩放后图像:
使用 fx 参数和 fy 参数控制缩放的时候,dsize参数值必须使用None,否则 fx 和 fy 就会失效。
fx 参数和 fy 参数可以使用浮点值,小于1的值表示缩小,大于1的值表示放大。
代码如下:
import cv2
img = cv2.imread("1.jpg") # 读取图像
dst3 = cv2.resize(img, None, fx=1 / 3, fy=1 / 2) # 将宽缩小到原来的1/3、高缩小到原来的1/2
cv2.imshow("img", img) # 显示原图
cv2.imshow("dst3", dst3) # 显示缩放图像
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
原始图像:
缩放后图像:
水平线被称为X轴,垂直线被称为Y轴。图像沿着X轴或者Y轴翻转之后,可以呈现出镜面倒影的效果。OpenCV通过cv2.flip()方法实现翻转效果,其语法如下:
dst = cv2.flip(src,flipCode)
参数说明:
src:原始图像
flipCode:翻转类型,类型值如下表所示。
参数值 | 含义 |
0 | 沿着X轴翻转 |
正数 | 沿着Y轴翻转 |
负数 | 同时沿着X轴、Y轴翻转 |
返回值说明:
dst:翻转之后的图像
代码如下:
import cv2
img = cv2.imread("1.jpg") # 读取图像
dst1 = cv2.flip(img, 0) # 沿X轴翻转
dst2 = cv2.flip(img, 1) # 沿Y轴翻转
dst3 = cv2.flip(img, -1) # 同时沿X轴、Y轴翻转
cv2.imshow("img", img) # 显示原图
cv2.imshow("dst1", dst1) # 显示翻转之后的图像
cv2.imshow("dst2", dst2)
cv2.imshow("dst3", dst3)
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
效果如图所示:
让图像旋转也是通过M矩阵实现的,但得出这个矩阵需要做很复杂的运算,于是OpenCV提供了getRotationMatrix2D()方法来自动计算出旋转图像的M矩阵。其语法格式如下所示:
M = cv2.getRotationMatrix2D(center,angle,scale)
参数说明:
center:旋转的中心点坐标
angle:旋转的角度(不是弧度)。正数表示逆时针旋转,负数表示顺时针旋转。
scale:缩放比例,浮点类型。如果取值为1,表示图像保持原来的比例。
返回值说明:
M:方法计算出的仿射矩阵
比如让图像逆时针旋转30°的同时缩小到原来的80%,代码如下:
import cv2
img = cv2.imread("1.jpg") # 读取图像
rows = len(img) # 图像像素行数
cols = len(img[0]) # 图像像素列数
center = (rows / 2, cols / 2) # 图像的中心点
M = cv2.getRotationMatrix2D(center, 30, 0.8) # 以图像为中心,逆时针旋转30度,缩放0.8倍
dst = cv2.warpAffine(img, M, (cols, rows)) # 按照M进行仿射
cv2.imshow("img", img) # 显示原图
cv2.imshow("dst", dst) # 显示仿射变换效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
效果如图所示:
如果说仿射是让图像在二维平面中变形,那么透视就是让图像在三维空间中变形。从不同的角度观察物体,会看到不同的变形画面。例如,矩阵会变成不规则的四边形、直角会变成锐角或钝角、圆形会变成椭圆等,这种变形之后的画面就是透视图。
OpenCV通过warpPerspective()方法来实现透视效果,其语法如下:
dst = cv2.warpPerspective(src,M,dsize,flags,borderMode,borderValue)
参数说明:
src:原始图像
M:一个3行3列的矩阵,根据此矩阵中的值变换原图中的像素位置。
dsize:输出图像的尺寸大小
flags:可选参数,插值方式,建议使用默认值。
borderMode:可选参数,边界类型,建议使用默认值。
borderValue:可选参数,边界值,默认为0,建议使用默认值。
返回值说明:
dst:经过透视变换后输出图像
warpPerspective()方法也需要通过M矩阵来计算透视效果,但得出这个矩阵需要做很复杂的运算,于是OpenCV提供了getPerspectiveTransform()方法来自动计算M矩阵。getPerspectiveTransform()方法的语法格式如下所示:
M = cv2.getPerspectiveTransform(src,dst)
参数说明:
src:原图四个点坐标,格式为4行2列的32位浮点数列表,例如:[[0,0],[1,0],[0,1],[1,1]]。
dst:透视图的四个点坐标,格式与src一样。
返回值说明:
M:方法计算出的仿射矩阵
模拟从底部观察图像得到的透视效果,将图像顶部边缘收窄,底部边缘保持不变,代码如下:
import cv2
import numpy as np
img = cv2.imread("1.jpg") # 读取图像
rows = len(img) # 图像像素行数
cols = len(img[0]) # 图像像素列数
p1 = np.zeros((4, 2), np.float32) # 32位浮点型空列表,保存原图四个点
p1[0] = [0, 0] # 左上角点坐标
p1[1] = [cols - 1, 0] # 右上角点坐标
p1[2] = [0, rows - 1] # 左下角点坐标
p1[3] = [cols - 1, rows - 1] # 右下角点坐标
p2 = np.zeros((4, 2), np.float32) # 32位浮点型空列表,保存透视图四个点
p2[0] = [90, 0] # 左上角点坐标,向右移动90像素
p2[1] = [cols - 90, 0] # 右上角点坐标,向左移动90像素
p2[2] = [0, rows - 1] # 左下角点坐标,位置不变
p2[3] = [cols - 1, rows - 1] # 右下角点坐标,位置不变
M = cv2.getPerspectiveTransform(p1, p2) # 根据四个点的变化轨迹计算出M矩阵
dst = cv2.warpPerspective(img, M, (cols, rows)) # 按照M进行仿射
cv2.imshow('img', img) # 显示原图
cv2.imshow('dst', dst) # 显示仿射变换效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
效果如图所示: