OpenCV_06 图像仿射、透视变换

发布于:2023-01-06 ⋅ 阅读:(123) ⋅ 点赞:(0)

前言

本节主要是关于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()调整了图片,在对其进行透视操作。

结果展示:

请添加图片描述


本文含有隐藏内容,请 开通VIP 后查看