图像的几何变换一般是指通过对图像进行放大、缩小、旋转等将一幅图像映射到另一幅图像中的操作。
1.仿射变换
仿射变换根据提供的仿射函数warpcv2.warpAffine(),以及一个映射矩阵M,仿射变换后的图像可由M与原图像的矩阵相乘得到。
*首先根据需求,写出M矩阵,然后利用放射变换函数对原图像处理,最后输出图像。*其中关键就在于M的求取。
1.1平移
展示一个将原图像向右上平移120个像素后的图像
首先,M矩阵可以为
[[ 1 0 120]
[ 0 1 -120]]
左边的两个1代表的就是原来的图像,右边的是上下移动的像素
接着利用从warpcv2.warpAffine()函数来实现图像的平移
程序如下:
import cv2 as cv
import numpy as np
image=cv.imread(r'E:\shiyan\1.jpg')
h,w=image.shape[:2]#获取图像大小信息,以便输出相同大小的图像
M=np.float32([[1,0,120],[0,1,-120]])#构建转矩阵M
imageMove=cv.warpAffine(image,M,(w,h))#进行仿射变换-平移,其中(w,h)是平移后输出图像的尺寸
cv.imshow('image',image)
cv.imshow('imageMove',imageMove)
cv.waitKey()
cv.destroyWindow()
1.2缩放
操作流程和上述流程一致,只需要改变M矩阵。
import cv2 as cv
import numpy as np
image=cv.imread(r'E:\shiyan\1.jpg')
h,w=image.shape[:2]#获取图像大小信息
'''
image.shape属性是读入图片后的一个元组dutuple
返回图片的(高,宽,位深)
比如image.shape返回(687, 740, 3)
而h,w=(687, 740, 3)
所以h,w=image.shape[:2]
分解了元组并分别用h,w获得了前两个数据,即高687、宽740
'''
M=np.float32([[0.5,0,0],[0,0.5,0]])#构建转矩阵M,与平移相比,之变化了此矩阵。
imageMove=cv.warpAffine(image,M,(w,h))#进行仿射变换-平移,其中(w,h)是平移后输出图像的尺寸
cv.imshow('image',image)
cv.imshow('imageMove',imageMove)
cv.waitKey()
cv.destroyWindow()
1.3旋转
import cv2 as cv
image=cv.imread(r'E:\shiyan\1.jpg')
h,w=image.shape[:2]
M=cv.getRotationMatrix2D((w/3,h/3),40,0.4)#使用该函数得到了,旋转矩阵M,效果是以中间的()内为旋转中心,40为旋转角度,0.4为图像缩放大小。
imageMove=cv.warpAffine(image,M,(w,h))
cv.imshow('image',image)
cv.imshow('imageMove',imageMove)
cv.waitKey()
cv.destroyWindow()
2.重映射
重映射就是将一幅图像内的像素点放置到另一幅图像的指定位置,与仿射变换类似,也是利用opencv中的cv2.remap()函数来实现。
2.1复制
实现图像的复制,是通过改变remap函数内的map1和map2来操作。
接下来介绍,复制的具体程序:
首先先试试如何实现像素的复制:
np.zeros的用法,即掩码的介绍
import cv2 as cv
import numpy as np
#构建一个6*6的随机数组
image=np.random.randint(0,256,size=[6,6],dtype=np.uint8)
h,w=image.shape[:2]
#建立一个新的用来可以复制的数组,要限定其大小
x=np.zeros((h,w),np.float32)
y=np.zeros((h,w),np.float32)
#实现新数组的访问操作
for i in range(h):
for j in range(w):
x.itemset((i,j),j)
y.itemset((i,j),i)
# 实现数组的复制
rst=cv.remap(image,x,y,cv.INTER_LINEAR)
print('image=\n',image)
print('rst\n',rst)
itemset的用法,就是一个设置数组内元素值得东西,同时数组内元素得序号是从0开始计算。
输出结果
image=
[[209 189 83 132 100 121]
[ 65 121 221 78 244 46]
[ 79 212 114 95 136 94]
[ 83 159 48 51 34 205]
[ 83 195 156 154 247 249]
[203 9 88 94 241 81]]
rst
[[209 189 83 132 100 121]
[ 65 121 221 78 244 46]
[ 79 212 114 95 136 94]
[ 83 159 48 51 34 205]
[ 83 195 156 154 247 249]
[203 9 88 94 241 81]]
然后展示图像得复制,程序如下
import cv2 as cv
import numpy as np
image=cv.imread(r'E:\shiyan\1.jpg')
h,w=image.shape[:2]
#建立一个新的用来可以复制的数组,要限定其大小
map1=np.zeros((h,w),np.float32)
map2=np.zeros((h,w),np.float32)
#实现图像的访问操作
for i in range(h):
for j in range(w):
map1.itemset((i,j),j)
map2.itemset((i,j),i)
# 实现图像的复制
rst=cv.remap(image,map1,map2,cv.INTER_LINEAR)
cv.imshow('image',image)
cv.imshow('rst',rst)
cv.waitKey()
cv.destroyWindow()
2.2绕x轴旋转
import cv2 as cv
import numpy as np
#构建一个6*6的随机数组
image=np.random.randint(0,256,size=[6,6],dtype=np.uint8)
h,w=image.shape[:2]
#建立一个新的用来旋转得数组,要限定其大小
x=np.zeros((h,w),np.float32)
y=np.zeros((h,w),np.float32)
#实现新数组的访问操作
for i in range(h):
for j in range(w):
x.itemset((i,j),j)
y.itemset((i,j),w-1-i)#x保持不变,y设置为总行数-1-当前行号,因为opencv中行号得下标 是从0开始的。
# 实现数组绕x轴旋转
rst=cv.remap(image,x,y,cv.INTER_LINEAR)
print('image=\n',image)
print('rst\n',rst)
image=
[[120 5 102 233 1 131]
[181 74 156 176 100 233]
[ 14 181 62 243 164 235]
[249 238 133 227 17 127]
[170 89 99 130 155 120]
[ 81 119 142 179 90 127]]
rst
[[ 81 119 142 179 90 127]
[170 89 99 130 155 120]
[249 238 133 227 17 127]
[ 14 181 62 243 164 235]
[181 74 156 176 100 233]
[120 5 102 233 1 131]]
接着实现图像的绕x轴翻转,
import cv2 as cv
import numpy as np
image=cv.imread(r'E:\shiyan\1.jpg')
h,w=image.shape[:2]
#建立一个新的用来可以复制的数组,要限定其大小
map1=np.zeros((h,w),np.float32)
map2=np.zeros((h,w),np.float32)
#实现图像的访问操作
for i in range(h):
for j in range(w):
map1.itemset((i,j),j)
map2.itemset((i,j),h-1-i)
# 实现图像的复制
rst=cv.remap(image,map1,map2,cv.INTER_LINEAR)
cv.imshow('image',image)
cv.imshow('rst',rst)
cv.waitKey()
cv.destroyWindow()
2.3绕y轴
同理x轴
2.4绕x,y轴转
同时改变x,y即可
2.5投影变换
物体在三维空间中发生了转换,叫做投影变换;与平面中仿射变换类似,只不过此处的M矩阵变成了需要通过内置函数计算的三阶矩阵。
import cv2 as cv
import numpy as np
image=cv.imread(r'E:\shiyan\1.jpg')
h,w=image.shape[:2]
#确立原图像的4个需要变换的像素点
sec=np.array([[0,0],[w-1,0],[0,h-1],[h-1,w-1]],np.float32)
#投影变换所需要的四个点
dst=np.array([[80,80],[w/2,50],[80,h-80],[w-40,h-40]],np.float32)
#计算所需要的M矩阵,记住,在投影变换中的M矩阵所输入的是四个点的矩阵
M=cv.getPerspectiveTransform(sec,dst)
#利用内置函数,进行投影变换
iamge1=cv.warpPerspective(image,M,(w,h),borderValue=125)
cv.imshow('image',image)
cv.imshow('image1',iamge1)
cv.waitKey()
cv.destroyWindow()
2.6极坐标变换
通常利用极坐标变换来校正图像中的圆形物体或被包含在圆环中的物体
略