Python 计算机视觉—— OpenCV 进行图像几何变换
Posted 一马归一码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 计算机视觉—— OpenCV 进行图像几何变换相关的知识,希望对你有一定的参考价值。
几何变换不改变图像的像素值,只是实现图像像素点的重新安排;恰当的进行图像的几何变换,可以减小甚至避免由于角度等一些因素造成的图像失真问题,有利于我们在识别图像时将注意力集中到图像的有效信息中而不至于被位置、角度等因素影响
目录
1. 平移变换
此处参考:知乎文章
平移原理
图像的平移就是将图像沿着某一个方向或者多个方向进行移动,通常会是向二维中的 x 轴或者 y 轴的方向进行移动
OpenCV 提供函数 warpAffine(img, mat, size)
各个参数含义:img -- 移动的图像
mat -- 平移矩阵,决定平移的方向和距离
size -- 决定平移后显示图像的大小,不改变窗口大小
在进行移动时首先需要构造一个移位矩阵 mat,通过该矩阵可以确定图像的移动方向和移动距离;构造的矩阵是一个两行三列的矩阵:
通过 x&y 来决定移动的方向以及距离
读取原图信息
"""
Author:XiaoMa
date:2021/10/19
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('E:\\From Zhihu\\For the desk\\de.jpg') #读取原图
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #调整原图大小
cv2.namedWindow("W0")
print(img1_1.shape) #读取图像信息
cv2.imshow("W0", img1)
cv2.waitKey(delay = 0)
获得图像:
获得图像信息:(487, 720, 3)
该图像为一幅分辨率为 487*720 的三通道图像,当然这是经过缩放后的分辨率,原分辨率应该为 (487/0.6)*(720/0.6) 的三通道图像
可以试一下:
print(img1.shape) #读取原图信息
获得的信息为:(811, 1200, 3)
构造移动矩阵
在此处需要使用到 numpy 库
mat = np.float32([[1, 0, 0], [0, 1, 20]]) #构造平移矩阵,对 y 轴进行移动
上面的代码是使原图 x 轴不发生移动,y 轴移动20个单位
平移图像
"""
Author:XiaoMa
date:2021/10/19
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('E:\\From Zhihu\\For the desk\\de.jpg') #读取原图
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #调整原图大小
cv2.namedWindow("W0")
print(img1_1.shape) #读取图像信息
cv2.imshow("W0", img1_1)
cv2.waitKey(delay = 0)
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #构造平移矩阵,对 y 轴进行移动
img1_1_1 = cv2.warpAffine(img1_1, mat, (487, 720))
cv2.namedWindow("W1")
cv2.imshow("W1", img1_1_1)
cv2.waitKey(delay = 0)
得到的图像如下:
首先是图像的移动距离很小(20 本来就很小),而且移动是向下的,这个和前面的文章中讲到的 OpenCV 绘图是一样的,其次通过平移得到的图像尺寸是按照设定来的,而使用 img.shape 得到的图像信息 x 和 y 是反过来的,下面我们对移动矩阵和移动大小进行修改:
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #构造平移矩阵,对 y 轴进行移动
img1_1_1 = cv2.warpAffine(img1_1, mat, (720, 487))
cv2.namedWindow("W1")
cv2.imshow("W1", img1_1_1)
cv2.waitKey(delay = 0)
其实移动 50 也有点小,但足够观察出变化
2. 缩放变换
图像的缩放就是对原图的尺寸大小进行调整,这个我们在前面文章中已经使用过了,使用 resize() 函数就可以达到目的,在这里我们再次进行学习加强记忆
图像的放大
"""
Author:XiaoMa
date:2021/10/19
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('E:\\From Zhihu\\For the desk\\de.jpg') #读取原图
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #调整原图大小
cv2.namedWindow("W0")
print(img1_1.shape)
cv2.imshow("W0", img1)
cv2.waitKey(delay = 0)
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #构造平移矩阵,对 y 轴进行移动
img1_1_1 = cv2.warpAffine(img1_1, mat, (720, 487))
cv2.namedWindow("W1")
cv2.imshow("W1", img1_1_1)
cv2.waitKey(delay = 0)
img1_11 = cv2.resize(img1_1, dsize = None, fx = 2, fy = 2)
cv2.namedWindow("W2")
cv2.imshow("W2", img1_11)
cv2.waitKey(delay = 0)
在读取原图时已经将原图进行了 0.6 的缩小,后面又经过了 2 倍的放大,所以最后的得到的图像应该是原图的 1.2 倍
图像的缩小
图像的缩小其实和图像的放大一样,只是将参数修改为小于 1 的数即可:
img1_11 = cv2.resize(img1_1, dsize = None, fx = 0.3, fy = 0.3)
0.6*0.3 = 0.18;即最上面的那幅小图尺寸是最下面的大图的 0.18 倍
3. 旋转变换
此处参考:图像的几何变换
对于图像的变换,OpenCV 提供了 getRotationMatrix2D() 函数,该函数包含三个参数,第一个参数是旋转中心,第二个参数是旋转角度,第三个参数是缩放比例
具体操作代码如下:
import cv2
img1 = cv2.imread('E:\\From Zhihu\\For the desk\\de.jpg') #读取原图
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #调整原图大小
cv2.namedWindow("W0")
print(img1_1.shape)
cv2.imshow("W0", img1)
cv2.waitKey(delay = 0)
img1_11 = cv2.resize(img1_1, dsize = None, fx = 0.3, fy = 0.3)
cv2.namedWindow("W2")
cv2.imshow("W2", img1_11)
cv2.waitKey(delay = 0)
print(img1_11.shape)
M = cv2.getRotationMatrix2D((108, 73), 45, 1) #第一个参数为旋转中心,和上一句得到的图像信息有关
cv2.namedWindow("W3")
res = cv2.warpAffine(img1_11, M, (216, 146))
cv2.imshow("W3", res)
cv2.waitKey(delay = 0)
可以从上面的代码中看出,图像的旋转最终还是与平移函数有关的
得到的图像如下:
但是我们可以看出旋转后的图像显示的不完全,如果希望通过旋转得到完整的图像,可以参考下面的这篇文章:旋转得到完整图像
4. 镜像变换
所谓镜像变换就是将图像以某一条边或者某一条线进行对称画图,其中的具体实现方法是构造一个和原图一模一样的图像,包括通道数,然后按照需要实现的变换将其中的像素点进行更换即可
复制原图
我们要使用 copy.deepcopy(img) 函数进行原图的复制
img1_2 = copy.deepcopy(img1_1)
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)
可以看出,得到的复制出的图像和原图是一摸一样的
水平镜像
水平镜像就是将图像按照左右对称的方式进行复制,所以我们不需要改变矩阵高度方向上的像素值,只是改变水平方向上的像素点即可:
img1_2 = copy.deepcopy(img1_1)
h = size[0]
w = size[1]
for i in range(h):
for j in range(w):
img1_2[i, w - 1- j] = img1_1[i, j] #像素点进行更换
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)
上面显示的就是经过水平变换得到的图像
垂直镜像
还是和上面的水平镜像一样,垂直变换则是只更换高度方向的像素点即可
img1_2 = copy.deepcopy(img1_1)
h = size[0]
w = size[1]
for i in range(h):
for j in range(w):
img1_2[h -1 -i, j] = img1_1[i, j] #将高度方向的像素点进行更换
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)
对角镜像
水平镜像和垂直镜像同时发生
img1_2 = copy.deepcopy(img1_1)
h = size[0]
w = size[1]
for i in range(h):
for j in range(w):
img1_2[h -1 -i, w - 1 - j] = img1_1[i, j]
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)
5. 仿射变换
仿射变换即为二维空间中的变换,前面提到的四种变换都可以包含在仿射变换中,如果需要加强了解可以参考下面的这篇文章,本文中就不赘述了
仿射变换(Affine Transformation)原理及应用(1)
结束语
这篇文章中总结了图像几何变换中的平移变换、旋转变换、缩放变换、镜像变换、仿射变换这五个部分,后面还有透视变换单独花一些时间来介绍,因为那部分比较难,其中参考的一些文章已经添加了链接,如果想进行更加全面的学习可以点进去进行查看,加油!
以上是关于Python 计算机视觉—— OpenCV 进行图像几何变换的主要内容,如果未能解决你的问题,请参考以下文章
计算机视觉OpenCV 4高级编程与项目实战(Python版):拼接图像
Python深度学习:计算机视觉处理库OpenCVNumpy编辑图片高斯模糊处理(读书笔记)
OpenCV-Python实战(23)——将OpenCV计算机视觉项目部署到云端