![cover](https://img-blog.csdnimg.cn/13238e8dda354da582e1ba70a698ffad.png)
python图像处理实战(三)—图像几何变换
图像几何变换就是在不改变图像像素值的前提下,对图像进行像素变换的处理。通常几何变换可以用来解决由成像的角度、透视位置不合预期等问题。比如拍摄的斜着的路牌,如果我们在只能对现有的照片进行处理的情况下又想要从侧面看到路牌上的字体,那么此时就要用到几何变换。
🚀写在前面🚀
🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog
🎁欢迎各位大佬支持点赞收藏,三连必回!!
🔈本人新开系列专栏—python图像处理
❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。
前言
图像几何变换就是在不改变图像像素值的前提下,对图像进行像素变换的处理。通常几何变换可以用来解决由成像的角度、透视位置不合预期等问题。比如拍摄的斜着的路牌,如果我们在只能对现有的照片进行处理的情况下又想要从侧面看到路牌上的字体,那么此时就要用到几何变换。
几何变换作为图像归一化的核心工作之一,对图像的预处理起到了重要作用。
目录
注:本文涉及到的图片资源可在博客积分资源中获取,相关链接:https://download.csdn.net/download/m0_52051577/87844285?spm=1001.2014.3001.5503
一、所需函数及基础变换的插值方法
1.所需函数
cv.resize(src, dsize,dst=None,fx=None, fy=None, interpolation=None)
功能:用来放大及缩小图像的函数。
参数:[输入图像,修改尺寸,输出图像,x方向缩放系数,Y 方向缩放系数,插值方式]
M = np.array([[...]], dtype=np.float32)
cv.warpAffine(img, M, dsize)功能:对图像进行平移变换。
参数:M表示构造的变换矩阵,warpAffine()函数中img表示变换的图像,M表示变换矩阵,dsize设置修改尺寸。
cv.flip(img,bool)
功能:对图像进行镜像变换。
参数:其中img表示变换的图像,flip()函数中bool为布尔值,可选0或1,0表示垂直镜像;1表示水平镜像;-1表示水平垂直同时进行。
M = cv.getRotationMatrix2D(center, angle, scale)
功能:对图像进行旋转变换(角度可定义)
参数:
getRotationMatrix2D()函数中center 表示旋转图像所要围绕的中心点。
angle 表示旋转的角度. 在OpenCV中正角度是逆时针的。
scale 表示缩放因子,可选的。
img_rotate = cv.rotate(img, cv.ROTATE_90_CLOCKWISE)
功能:对图像进行旋转变换(90°)
参数:rotate()旋转函数,将图像旋转90°。
M = cv.getPerspectiveTransform(src, dst)
功能:求得图像透视变换的变换矩阵。
参数:cv2.getPerspectiveTransform()函数根据图像中不共线的 4 个点在变换前后的对应位置求得 (3x3) 变换矩阵。
img = cv.warpPerspective(img, M, dsize)
功能:对图像进行透视变换。
参数:cv2.warpPerspective 使用该 (3x3) 变换矩阵即可求出变换后的图像。标量进行加法运算。
2.常见插值方法
在做图像处理时,经常会碰到小数像素坐标的取值问题,这就需要一种插值算法来对坐标进行插值。常见的四种插值方法如下:
最近邻插值: interpolation = cv.INTER_NEAREST
放大图片:interpolation = cv.INTER_CUBIC(速度慢)
interpolation = cv.INTER_LINEAR 线性插值(速度快)
缩小图片:interpolation = cv.INTER_AREA
3.最近邻插值
将原本10X10的图像放大成15X15,放大1.5倍。
比如要计算新图像在(10,11)处的灰度值,则对应原图像(10/1.5,11/1.5)= (6.7,7.3)处的灰度值,四舍五入取整,选取原图像(7,7)处的灰度值即可。如下图:
4.最近邻和双线性插值比较
##### 最近邻和双线性插值比较
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB), cmap='gray', vmin=0, vmax=255)
plt.show()
img = cv.imread('pic/rabbit50x33.jpg')
img_resize1 = cv.resize(img, (330, 500), interpolation=cv.INTER_NEAREST)
img_resize2 = cv.resize(img, (330, 500), interpolation=cv.INTER_LINEAR)
show(img)
show(np.hstack([img_resize1, img_resize2]))
最左图为模糊处理后的图像,中间图为最近邻处理的效果图,最右图为双插值处理的效果图,可见同样图片尺寸下,双插值处理效果更清晰。
二、图像操作
首先,定义导入图片的函数。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
else:
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
1.裁剪图像 (放大缩小)
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
img.shape #查看图像维度
如图,原图的维度为(500,333,3),下面将图像裁剪。
# 裁剪
rabbit = img[150:450, 50:300, :]
show(rabbit)
如图,裁剪后的维度中,150:450表示纵轴上裁剪的长度,50:300表示横轴上裁剪的长度。
2.平移变换
平移变换的原理为,在原有像素点的基础上指定x方向与y方向的偏移量▲x与▲y,将原有的像素坐标(x0,y0)进行处理,平移后的坐标为(x,y);并将方程写成原向量与偏移向量相加的形式。同时原向量还可写成[[1,0],[0,1]]向量组与[x0,y0]相乘的形式,随后再偏移向量填补,写成3阶矩阵与3维向量相乘的形式,从而实现平移变换。
# 平移
transM = np.array([
[1, 0, 20],
[0, 1, 100]
], dtype=np.float32)
img_trans = cv.warpAffine(img, transM, dsize=(333, 500))
show(img_trans)
如图,首先构造平移矩阵transM, 分别指定x与y方向上的平移量,用图像中每个像素点对应的矩阵点乘平移矩阵transM,从而实现图像的平移变换。其中dsize是设置平移图像的尺寸。
3.错切变换
错切变换实现原理:令x=x0+y0tanθ,y=y0。按上图公式进行变换,y0tanθ为x在水平方向上的错切量,纵轴位置不变,从而实现水平方向的错切变换。
# 错切
shearM = np.array([
[1, 0.3, 0],
[0, 1, 0]
], dtype=np.float32)
img_shear = cv.warpAffine(img, shearM, dsize=(400, 500))
show(img_shear)
如图,错切变换后的图像是由矩阵错切变换公式得来的,公式中tanα表示横坐标错切比例,横坐标错切量dx=原像素点纵坐标y0×错切所占比例tanα。同理,tanβ表示纵坐标错切比例,纵坐标错切量dy=原像素点纵坐标x0×错切所占比例tanβ。以这样的方式得到的图像即为错切变换图像。
4.镜像变换
镜像变换原理:本质是将水平或竖直方向的坐标对称过去。
4.1方式一
# 镜像1
mirrorM = np.array([
[-1, 0, 333],
[0, 1, 0]
], dtype=np.float32)
img_mirr = cv.warpAffine(img, mirrorM, dsize=img.shape[:2][::-1])
show(img_mirr)
如图,mirrorM中,x方向向量的首位元素为-1,表示将原图横向翻转,纵轴不变。
4.2方式二
# 镜像2
img_mirh = cv.flip(img, 1)
img_mirv = cv.flip(img, 0)
img_mirb = cv.flip(img, -1)
show(np.hstack([img, img_mirh, img_mirv, img_mirb]))
如图,采用flip()函数进行镜像翻转,其中1表示水平翻转,0表示竖直翻转,-1表示水平竖直同时进行。
5.旋转变换
旋转变换原理:首先定义旋转矩阵,再将原图像对应向量×矩阵中每个行向量分量。
旋转矩阵推导过程如上图,定义旋转半径r,旋转角α和β,其中(x0,y0)根据三角公式可以用r和α表示出来。
那么同理,要想将(x0,y0)变换到新坐标(x,y),同样用r和旋转角来表示,此时的旋转角为α-β,表示出新坐标(x,y)后,再用rcosα和rsinα替换掉x0,y0。并将方程组写成矩阵相乘的形式,即为旋转矩阵。
5.1方式一
# 旋转1
img_rotate = cv.rotate(img, cv.ROTATE_90_CLOCKWISE)
show(img_rotate)
采用rotate()函数将图像顺时针旋转90°。
5.2方式二
# 旋转2
rotateM = cv.getRotationMatrix2D((80, 100), 45, 1)
img_rotate = cv.warpAffine(img, rotateM, dsize=(500, 500))
show(img_rotate)
采用getRotationMatrix2D()函数,定义旋转图像所要围绕的中心点(80,100),定义旋转的角度为45°,定义缩放因子为1。进行旋转变换,并调整尺寸为(500,500)。
5.3设置不同缩放因子时的旋转效果
# 旋转scale
rotateM1 = cv.getRotationMatrix2D((80, 100), 45, 0.8)
rotateM2 = cv.getRotationMatrix2D((80, 100), 45, 1)
rotateM3 = cv.getRotationMatrix2D((80, 100), 45, 1.2)
img_rotate1 = cv.warpAffine(img, rotateM1, dsize=(700, 300))
img_rotate2 = cv.warpAffine(img, rotateM2, dsize=(700, 300))
img_rotate3 = cv.warpAffine(img, rotateM3, dsize=(700, 300))
show(np.hstack([img_rotate1, img_rotate2, img_rotate3]))
如图,缩放因子越大,图像显示越大。
6.放大缩小
# 放大、缩小
img_resize = cv.resize(img, (300, 200))
show(img_resize)
采用 resize()函数对尺寸进行重新定义,设置尺寸为(300,200)。
7.透视变换
透视变换原理:选取图像中四点的坐标(一般四点呈现平行四边形,根据图像位置来判定选取),再另外选择四点坐标(一般为矩形,根据自己想要呈现的效果来选取),分为两种矩阵src和dst,其中src为变换前选取的坐标矩阵,dst为想要变换的坐标矩阵。并采用getPerspectiveTransform()函数构造计算后的变换矩阵。并用warpPerspective()函数进行透视变换。如今,透视变换主要用于车道检测和图片矫正。
import cv2 as cv
img = cv.imread('pic/parthenon500x750.jpg')
show(img)
src = np.array([
[210, 50],
[610, 270],
[650, 480],
[150, 450]
], dtype=np.float32)
dst = np.array([
[150, 50],
[650, 50],
[650, 480],
[150, 480]
], dtype=np.float32)
M = cv.getPerspectiveTransform(src, dst)
img2 = cv.warpPerspective(img, M, dsize=(750, 500))
show(img2)
构造的变换矩阵M为:
array([[ 2.71437487e-01, 1.50299394e-01, 5.07376979e+01], [-6.40928318e-01, 1.08051969e+00, 1.18987142e+02], [-1.23293942e-03, 5.45617563e-04, 1.00000000e+00]])
如图,左边为原图,右边为透视变换后的效果。
🚗 创作不易,期待大佬们的三连支持!🚗
更多推荐
所有评论(0)