Python 图像处理 OpenCV (5):图像的几何变换

前文传送门:
「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」
「Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理」
「Python 图像处理 OpenCV (4):图像算数运算以及修改颜色空间」
图像缩放
图像缩放只是调整图像的大小,为此, OpenCV 为我们提供了一个函数 cv.resize() ,原函数如下:
resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)
src 表示的是输入图像,而 dsize 代表的是输出图像的大小,如果为 0 ,则:
$$\texttt{dsize = Size(round(fxsrc.cols), round(fysrc.rows))}$$
dsize 和 fx 、 fy 不能同时为 0 。
fx 、 fy 是沿 x 轴和 y 轴的缩放系数,默认取 0 时,算法如下:
$$\texttt{fx=(double)dsize.width/src.cols}$$
$$\texttt{fy=(double)dsize.height/src.rows}$$
最后一个参数 interpolation 表示插值方式:
- INTER_NEAREST - 最近邻插值
- INTER_LINEAR - 线性插值(默认)
- INTER_AREA - 区域插值
- INTER_CUBIC - 三次样条插值
- INTER_LANCZOS4 - Lanczos插值
看一个简单的示例:
import cv2 as cv
#读取图片
src = cv.imread('maliao.jpg')
print(src.shape)
#图像缩放
result = cv.resize(src, (300, 150))
print(result.shape)
#显示图像
cv.imshow("src", src)
cv.imshow("result", result)
#等待显示
cv.waitKey()
cv.destroyAllWindows()
结果如下:

需要注意的是,这里的 (300, 150) 设置的是 dsize 的列数为 300 ,行数为 150 。
同理,我们可以通过设定一个比例进行缩放,可以是等比例缩放,也可以是不等比例缩放,下面是等比例缩放的示例:
import cv2 as cv
# 设定比例
scale = 0.5
#读取图片
src = cv.imread('maliao.jpg')
rows, cols = src.shape[:2]
#图像缩放
result = cv.resize(src, ((int(cols * scale), int(rows * scale))))
print(result.shape)
#显示图像
cv.imshow("src", src)
cv.imshow("result", result)
#等待显示
cv.waitKey()
cv.destroyAllWindows()
结果如下:

除了可通过设定 dszie 对图像进行缩放,我们还可以通过设定 fx 和 fy 对图像进行缩放:
import cv2 as cv
#读取图片
src = cv.imread('maliao.jpg')
print(src.shape)
#图像缩放
result = cv.resize(src, None, fx=0.5, fy=0.5)
print(result.shape)
#显示图像
cv.imshow("src", src)
cv.imshow("result", result)
#等待显示
cv.waitKey()
cv.destroyAllWindows()
结果如下:

图像平移
图像平移是通过仿射函数 warpAffine() 来实现的,原函数如下:
warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
在图像平移中我们会用到前三个参数:
- 需要变换的原始图像
- 移动矩阵M
- 变换的图像大小(如果这个大小不和原始图像大小相同,那么函数会自动通过插值来调整像素间的关系)。
图像的平移是沿着 x 方向移动 tx 距离, y 方向移动 ty 距离,那么需要构造移动矩阵:
$$ M = [\begin{matrix} 1 & 0 & tx \ 0 & 1 & ty \end{matrix}] $$
我们通过 Numpy 来产生这个矩阵(必须是float类型的),并将其赋值给仿射函数 warpAffine() ,下面来看个示例:
import cv2 as cv
import numpy as np
#读取图片
src = cv.imread('maliao.jpg')
rows, cols = src.shape[:2]
# 定义移动距离
tx = 50
ty = 100
# 生成 M 矩阵
affine = np.float32([[1, 0, tx], [0, 1, ty]])
dst = cv.warpAffine(src, affine, (cols, rows))
# 显示图像
cv.imshow('src', src)
cv.imshow("dst", dst)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()
结果如下:

注意:
warpAffine函数的第三个参数是输出图像的大小,我这里设置的大小是原图片的大小,所以结果会有部分遮挡。
图像旋转
图像旋转主要调用 getRotationMatrix2D() 函数和 warpAffine() 函数实现,绕图像的某一个中心点旋转,具体如下:
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
参数分别为:旋转中心、旋转度数、scale
rotated = cv2.warpAffine(src, M, (cols, rows))
参数分别为:原始图像、旋转参数、原始图像宽高
图像旋转:设( x0 , y0 )是旋转后的坐标,( x , y )是旋转前的坐标,( m , n )是旋转中心, a 是旋转的角度(顺时针),( left , top )是旋转后图像的左上角坐标,则公式如下:
$$ \begin{bmatrix}x0 & y0 & 1\end{bmatrix} = \begin{bmatrix}x & y & 1\end{bmatrix} \begin{bmatrix}1 & 0 & 0 \ 0 & -1 & 0 \ -m & n & 1\end{bmatrix} \begin{bmatrix}\cos a & -\sin a & 0 \ \sin a & \cos a & 0 \ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 \ 0 & -1 & 0 \ left & top & 1 \end{bmatrix}$$
上面这个公式具体的推导过程可以参考这篇文章:https://www.cnblogs.com/xuanyuyt/p/7112876.html 。
示例如下:
import cv2 as cv
#读取图片
src = cv.imread('maliao.jpg')
# 原图的高、宽
rows, cols = src.shape[:2]
# 绕图像的中心旋转
# 参数:旋转中心 旋转度数 scale
M = cv.getRotationMatrix2D((cols/2, rows/2), 90, 1)
#
dst = cv.warpAffine(src, M, (cols, rows))
# 显示图像
cv.imshow("src", src)
cv.imshow("dst", dst)
# 等待显示
cv.waitKey()
cv.destroyAllWindows()
结果如下:

图像翻转
第一个图像翻转,这个可是制作表情包的利器。
图像翻转在 OpenCV 中调用函数 flip() 实现,原函数如下:
flip(src, flipCode, dst=None)
- src:原始图像。
- flipCode:翻转方向,如果 flipCode 为 0 ,则以 X 轴为对称轴翻转,如果 fliipCode > 0 则以 Y 轴为对称轴翻转,如果 flipCode < 0 则在 X 轴、 Y 轴方向同时翻转。
示例如下:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图片 由 GBR 转 RGB
img = cv.imread('maliao.jpg')
src = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 图像翻转
# flipCode 为 0 ,则以 X 轴为对称轴翻转,如果 fliipCode > 0 则以 Y 轴为对称轴翻转,如果 flipCode < 0 则在 X 轴、 Y 轴方向同时翻转。
img1 = cv.flip(src, 0)
img2 = cv.flip(src, 1)
img3 = cv.flip(src, -1)
# plt 显示图形
titles = ['Source', 'Ima1', 'Ima2', 'Ima3']
images = [src, img1, img2, img3]
for i in range(4):
plt.subplot(2, 2, i + 1)
plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([])
plt.yticks([])
plt.show()
结果如下:

示例代码
如果有需要获取源码的同学可以在公众号回复「OpenCV」进行获取。
参考
https://blog.csdn.net/Eastmount/article/details/82454335
https://www.cnblogs.com/korbin/p/5612427.html
Python 图像处理 OpenCV (5):图像的几何变换的更多相关文章
- Python 图像处理 OpenCV (6):图像的阈值处理
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (14):图像金字塔
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (15):图像轮廓
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (16):图像直方图
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 图像属性 图像 ...
- Python 图像处理 OpenCV (4):图像算数运算以及修改颜色空间
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (7):图像平滑(滤波)处理
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (9):图像处理形态学开运算、闭运算以及梯度运算
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (10):图像处理形态学之顶帽运算与黑帽运算
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
随机推荐
- Netty(六):NioServerSocketChannel源码解析
我们在Netty学习系列五的最后提出了一些问题还没得到回答,今天来通过学习NioServerSocketChannel的源码来帮我们找到之前问题的答案. 先看一下NioServerSocketChan ...
- 演示:配置日志发送到syslog日志服务器
演示目标:配置网络环境中的交换机和路由器将日志发送到syslog日志服务器. 演示环境:如下图10.54所示的演示环境. 演示背景:要求部署网络中的syslog服务器,集中的收集交换机S1和路由器R1 ...
- 数学--数论--HDU6919 Senior PanⅡ【2017多校第九场】
Description 给出一个区间[L,R][L,R],问该区间中所有以KK作为最小因子(大于11的)的数字之和 Input 第一行输入一整数TT表示用例组数,每组用例输入三个整数L,R,KL,R, ...
- P1790 矩形分割(隐含的电风扇)
描述:https://www.luogu.com.cn/problem/P1790 有一个长为a,宽为b的矩形(1≤a≤6,2≤b≤6).可以把这个矩形看作是a*b个小方格. 我们现在接到了这样的一个 ...
- Codeforces Round #577 (Div. 2) D. Treasure Hunting
Codeforces Round #577 (Div. 2) D. Treasure Hunting 这个一场div2 前面三题特别简单,这个D题的dp还是比较难的,不过题目告诉你了只能往上走,所以 ...
- 向Redis里存入数据
实现思路:1. 从Redis缓存获取URL统计网址清单2. 逐条拼凑SQL统计语句,暂时不能支持批量计算,因为按单个网址统计.3. 发送到HIVE JDBC执行SQL并等待返回结果4 ...
- 一些常见的pro文件配置
UI_DIR = ./ui #ui文件目录 TARGET = Test #最终生成目标名 DESTDIR = $$PWD/../test #目标生成目录,$$PWD表示当前目录下 DLLDESTDIR ...
- 图形学_Bezier曲线
Bezier曲线由n个控制点生成,举个例子:当n=2时,点$P_0$.$P_1$之间遵从计算: $P_0=(1-t)P_0+tP_1$ 而推广为n维时,有: $P^n_0=(1-t)P^{n-1}_0 ...
- Redis 学习笔记(一) 字符串 SDS
SDS 简单动态字符串. SDS的结构: struct sdshdr{ int len;//记录BUF数组中已使用字节的数量 ,等于SDS所八寸字符串的长度 int free;//记录BUF数组中未使 ...
- JDBC10 Blob二进制对象
//将图片输入到数据库中 // String sql="insert into t_user2 (username,headImg) values (?,?)"; // ps=co ...