前言
本节主要是关于OpenCV中图像变换的基本操作。
目录
一、图像变换
1.图像缩放
resize()
声明:void resize( InputArray src, OutputArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR );
参数:
src:需要缩放的图像
dst:输出参数与src类型相同,Python不需要
dsize:目标大小
fx, fy:x轴,y轴的缩放因子
interpolation:插值算法
注1:dsize和 fx, fy相冲突,如果都写,默认使用dsize。
注2:插值算法:
INTER_NEAREST:临近插值,速度快,效果差
INTER_LINEAR:双线性插值,计算原图中的4个点(默认)
INTER_CUBIC:三次插值,计算原图中的16个点
INTER_AREA:效果最好
代码案例:
import cv2
import numpy as np
cat = cv2.imread('./picture/cat.jpg')
# new = cv2.resize(cat, None, fx = 1.5, fy = 1.5) # 使用fx,fy进行缩放
new = cv2.resize(cat, (600, 600)) #使用dsize缩放
cv2.imshow('cat', cat)
cv2.imshow('new', new)
cv2.waitKey(0)
结果展示:
2.图像翻转
flip()
声明:void flip(InputArray src, OutputArray dst, int flipCode);
void rotate(InputArray src, OutputArray dst, int rotateCode);
参数:
src:需要翻转的图像
dst:输出参数与src类型相同,Python不需要
flipCode:翻转方式
flipCode ==0:上下翻转
flipCode > 0:左右翻转
flipCode < 0:上下+左右翻转
3.图像旋转
旋转角度为 90,180,270 度时,可以用 rotate() 函数实现,该方法实际上是通过矩阵转置实现的,因此速度很快。
rotate()
声明:void rotate(InputArray src, OutputArray dst, int rotateCode);
参数:
src:需要旋转的图像
dst:输出参数与src类型相同,Python不需要
rotateCode:
cv2.ROTATE_90_CLOCKWISE:顺时针旋转 90 度
cv2.ROTATE_180: 旋转 180 度
cv2.ROTATE_90_COUNTERCLOCKWISE:逆时针旋转 90 度
二、图像的仿射变换
仿射变换是图像旋转、缩放、平移的总称。
1.仿射API
warpAffine()
声明:void warpAffine( InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar& borderValue = Scalar());
参数:
src:图像
M:变换矩阵
dsize:目标大小(当目标尺寸小于原尺寸时,直接裁剪原图左上角)
flags:插值算法
borderMode:边界外推法标志
borderValue:边界外推法的值
2.平移矩阵
- 矩阵中的每个像素由(x,y)组成
- 因此,其变换矩阵是2x2的矩阵
- 平移向量为2x1的向量,所在平移矩阵为2x3的矩阵
代码案例:
import cv2
import numpy as np
cat = cv2.imread('./picture/cat.jpg')
h, w, ch = cat.shape
M = np.float32([[1, 0, 100], [0, 1, 0]])
new = cv2.warpAffine(cat, M, (w, h))
cv2.imshow('cat', cat)
cv2.imshow('new', new)
cv2.waitKey(0)
结果展示:
3.旋转变换矩阵
OpenCV提供了封装好的计算变换矩阵的API,只要提供必要的参数就可以得到相应的变换矩阵。
getRotationMatrix2D(center, angle, scale)
声明:Mat getRotationMatrix2D(Point2f center, double angle, double scale);
参数:
center:旋转的中心点
angle:旋转角度(逆时针)
scale:缩放比例
代码案例:
M = cv2.getRotationMatrix2D((225, 225), 45, 0.7)
结果展示:
变换后的图像尺寸仍与原图尺寸一致,周围的黑色部分也属于图片。要对图片尺寸进行修改要使用warpAffine或resize函数。
4.仿射变换矩阵
由于仿射变换相对复杂,要求得所需M矩阵一般很难求出。因为M矩阵联系着两幅图片,OpenCV提供了通过变换前后图片上三个点位置的对应关系自动求解M矩阵的函数:
getAffineTransform()
声明:Mat getAffineTransform( const Point2f src[], const Point2f dst[] );
参数:
src:源图像中三角形顶点的坐标,也就是在源图像中任找不在同一直线上的三个点,将三个点的坐标作为三个元素放到src对应列表中
dst:目标图像中相应三角形顶点的坐标,也就是三个点在变换后图像中的坐标列表,要求与源图像三个点一一对应。
返回值:从三对对应的点计算出来的仿射变换矩阵。
代码案例:
src = np.float32([[200, 200], [200, 250], [250, 250]])
dst = np.float32([[160, 200], [150, 270], [100, 230]])
M = cv2.getAffineTransform(src, dst)
结果展示:
三、透视变换
1.透视变换API
OpenCV提供的透视变换API与仿射变换非常相似:
warpPerspective()
声明:void warpPerspective( InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar& borderValue = Scalar());
参数:
src:图像
M:变换矩阵
dsize:目标大小
2.变换矩阵
同样与仿射变换获取变换矩阵类似,OpenCV也提供了相关函数,只不过需要提供4个点作为输入。
getPerspectiveTransform()
声明:Mat getPerspectiveTransform(InputArray src, InputArray dst, int solveMethod = DECOMP_LU);
参数:
src:源图像中所取子图像4个顶点的坐标
dst:目标图像中4个顶点的坐标
返回值:变换矩阵
代码案例:
import cv2
import numpy as np
img = cv2.imread('./picture/notebook.jpeg')
notebook = cv2.resize(img, None, fx = 0.2, fy = 0.2)
print(notebook.shape)
src = np.float32([[134, 87], [569, 160], [26, 710], [466, 782]])
dst = np.float32([[0, 0], [600, 0], [0, 800], [600, 800]])
M = cv2.getPerspectiveTransform(src, dst)
result = cv2.warpPerspective(notebook, M, (600,800))
cv2.imshow('notebook', notebook)
cv2.imshow('result', result)
cv2.waitKey(0)
由于图像是手机拍摄,像素过大,先使用resize()调整了图片,在对其进行透视操作。
结果展示: