这是我参与更文挑战的第4天,活动详情查看: 更文挑战
OpenCV是一个C++库,目前流行的计算机视觉编程库,用于实时处理计算机视觉方面的问题,它涵盖了很多计算机视觉领域的模块。在Python中常使用OpenCV库实现图像处理。
本文将介绍如何在Python3中使用OpenCV实现对图像的几何变换:
参考: Opencv4 官方文档 : docs.opencv.org/4.2.0/
图像的几何变换主要包括:平移、缩放与扩大、旋转、仿射、透视等。
图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对应的图像变换关系。
图像缩放与扩大
缩放就是改变图像的大小,常使用cv2.resize()函数进行操作。
图像的大小可以手动指定,也可以使用缩放比例。
cv2.resize()支持多种插值算法,默认使用的是cv2.INTER_LINEAR(不管放大和缩小)。
缩小最适合使用:cv2.INTER_AREA,
放大最适合使用:cv2.INTER_CUBIC (慢) 或cv2.INTER_LINEAR。
代码如下
import numpy as np
import cv2
## 按比例缩放
img = cv2.imread('E:\\demo\\lena.jpg')
res = cv2.resize(img,None,fx=0.5, fy=0.5, interpolation = cv2.INTER_CUBIC)
#或者按具体宽高进行缩放
#height, width = img.shape[:2]
#res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
cv2.imshow('Original image',img)
cv2.imshow('Reduce image',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码输出为
同理图像扩大代码如下:
图像扩大
图像扩大代码如下:
import numpy as np
import cv2
## 按比例缩放
img = cv2.imread('E:\\demo\\lena.jpg')
res = cv2.resize(img,None,fx=1.5, fy=1.5, interpolation = cv2.INTER_CUBIC)
#或者按具体宽高进行缩放
#height, width = img.shape[:2]
#res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
cv2.imshow('Original image',img)
cv2.imshow('Enlarge image',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出为:
图像平移
平移是物体位置的移动。同理图像平移也是基于这个原理,图像上的每个像素对应坐标轴上的点(x,y),图像的平移也就代表坐标轴上点的平移。
Opencv中是通过创建转换矩阵M,进行图像的平移,如下所示:
并将其放入np.float32类型的Numpy数组中,然后传递给cv.warpAffine函数。
代码如下
参见下面平移为(80, 50)的代码示例:
import numpy as np
import cv2
img = cv2.imread('E:\\demo\\lena.jpg')
rows = img.shape[0]
cols = img.shape[1]
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('Original image',img)
cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码输出为
图像旋转
在Opencv中提供了cv2.getRotationMatrix2D函数获得变换矩阵。
第一参数指定旋转圆点;第二个参数指定旋转角度;第三个参数指定缩放比例。
代码如下
import numpy as np
import cv2
img = cv2.imread('E:\\demo\\lena.jpg')
rows = img.shape[0]
cols = img.shape[1]
# 将图像相对于中心旋转90度,而不进行任何缩放。旋转中心,角度,缩放比率
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('Original image',img)
cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码输出为
图像仿射变换
仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。
图像旋转加上拉升就是图像仿射变换,仿射变化也是需要一个M矩阵就可以实现,但是由于仿射变换比较复杂,一般直接找很难找到这个矩阵。
Opencv提供了根据变换前后三个点的对应关系来自动求解M。
这个函数是M=cv2.getAffineTransform(pos1,pos2),
其中两个位置就是变换前后的对应位置关系。
输出的就是仿射矩阵M。然后再使用函数cv2.warpAffine()。生成最后的图片。
代码如下
import cv2
import numpy as np
img = cv2.imread('E:\\demo\\lena.jpg')
rows = img.shape[0]
cols = img.shape[1]
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
#第三个参数:变换后的图像大小
dst = cv2.warpAffine(img,M,(rows,cols))
cv2.imshow('Original image',img)
cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码输出为
图像透视变换
透视变换是将图片投影到一个新的视平面,也称作投影映射。它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x’,y’)空间的映射。
相对于仿射变换,透视变换提供了更大的灵活性,将一个四边形区域映射到另一个四边形区域(不一定是平行四边形)。它是通过线性变换和矩阵乘法实现的。
该变换使用的是一个3x3的矩阵,矩阵的前两行与仿射矩阵相同
(m11,m12,m13,
m21,m22,m23),
也实现了线性变换和平移,第三行用于实现透视变换;
要找到此变换矩阵M,开发者需要在输入图像上有4个点,在输出图像上需要相应的点。在这四个点中,其中三个不应共线。然后可以通过函数cv.getPerspectiveTransform找到变换矩阵。
然后将cv.warpPerspective应用于此3x3转换矩阵。即可生成最终的图像。
代码如下
import cv2
import numpy as np
img = cv2.imread('E:\\demo\\lena.jpg')
rows = img.shape[0]
cols = img.shape[1]
ch = img.shape[2]
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
#第三个参数:变换后的图像大小
dst = cv2.warpPerspective(img,M,(300,300))
cv2.imshow('Original image',img)
cv2.imshow('img',dst)
代码输出为
本月将陆续推出相关系列文章,
篇篇精彩,尽请关注。