OpenCV-几何变换
几何变换这一部分在图像处理方面应用比较广泛,比如合适的图像几何变换可以用于增大深度学习里训练样本的样本集,提取特征等等方面。
OpenCV中提供resize()函数来进行图像矩阵的变换。
cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
参数分别为原图像,变换大小,沿水平轴的比例因子,沿竖直轴的比例因子,插值方法。默认双线性插值。
通过下面的示例理解。首先是利用数组模拟图像。先构建一个两行四列的三通道数组,所有元素均置1。img[1,2,2]=4是将第二行第三列第三个通道的1改为4。用**img.shape[:2]**获取img的行和列,赋给变量size,需要注意的是在cv2.resize(img,size)函数中会将行和列颠倒过来,可以看到rst.shape变为了(4, 2, 3)。并且在变换过程不是简单的矩阵转置,而是为保证图像不失真进行的插值变换。
变换前
变换后
**
缩放
**
import cv2
import numpy as np
img=np.ones([2,4,3],dtype=np.uint8)
img[1,2,2]=4
size=img.shape[:2]
print("size.shape=",size)
rst=cv2.resize(img,size)
print("img.shape=\n",img.shape)
print("img=\n",img)
print("rst.shape=\n",rst.shape)
print("rst=\n",rst)
图像变换与矩阵变换相同,代码放在下面,截图体现不明显,还需实际操作。需要注意的是dy对应的是竖直方向也就是对行数进行操作。反之dx对列操作。
import cv2
img=cv2.imread("test.bmp")
rst=cv2.resize(img,None,fx=2,fy=0.5)
print("img.shape=",img.shape)
print("rst.shape=",rst.shape)
cv2.imshow('rst',rst)
cv2.imshow('img',img)
cv2.waitKey()
cv2.destroyAllWindows()
图像翻转、平移、旋转
OpenCV中提供flip()函数对图像进行翻转操作,主要是通过改变第二个参数,1对应水平镜像,0对应垂直镜像,-1对应对角镜像
翻转:
import cv2
img=cv2.imread(“lena.bmp”)
x=cv2.flip(img,0)
y=cv2.flip(img,1)
xy=cv2.flip(img,-1)
cv2.imshow(“img”,img)
cv2.imshow(“x”,x)
cv2.imshow(“y”,y)
cv2.imshow(“xy”,xy)
cv2.waitKey()
cv2.destroyAllWindows()
原图
沿X轴翻转(0)
沿Y轴翻转(1)
沿XY轴翻转(-1)
warpAffine是opencv提供的一个仿射变换的函数(线性变换和平移)
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
其中:
src - 输入图像。
M - 变换矩阵。
dsize - 输出图像的大小。
flags - 插值方法的组合
borderMode - 边界像素模式
borderValue - 边界填充值; 默认情况下,它为0即黑色
平移:
import cv2
import numpy as np
img=cv2.imread("lena.bmp")
height,width=img.shape[:2]
x=100
y=200
M = np.float32([[1, 0, x], [0, 1, y]])
move=cv2.warpAffine(img,M,(width,height))
cv2.imshow("original",img)
cv2.imshow("move",move)
cv2.waitKey()
cv2.destroyAllWindows()
[1, 0, x]表示水平方向, [0, 1, y]表示竖直方向
平移后
修改为cv2.warpAffine(img,M,(width,height),borderValue=(255,0,0))即把填充背景改为了蓝色(注意opencv中通道顺序为BGR)
图像旋转:
M=cv2.getRotationMatrix2D(center, angle, scale)
center:图片的旋转中心
angle:旋转角度
scale:旋转后图像相比原来的缩放比例
M:计算得到的旋转矩阵
import cv2
img=cv2.imread("lena.bmp")
height,width=img.shape[:2]
M=cv2.getRotationMatrix2D((width/2,height/2),45,0.6)
rotate=cv2.warpAffine(img,M,(width,height))
cv2.imshow("original",img)
cv2.imshow("rotation",rotate)
cv2.waitKey()
cv2.destroyAllWindows()
图像仿射:
import cv2
import numpy as np
img=cv2.imread('lena.bmp')
rows,cols,ch=img.shape
p1=np.float32([[0,0],[cols-1,0],[0,rows-1]])
p2=np.float32([[0,rows*0.33],[cols*0.85,rows*0.25],[cols*0.15,rows*0.7]])
M=cv2.getAffineTransform(p1,p2)
dst=cv2.warpAffine(img,M,(cols,rows))
cv2.imshow("origianl",img)
cv2.imshow("result",dst)
cv2.waitKey()
cv2.destroyAllWindows()
```![在这里插入图片描述](https://img-blog.csdnimg.cn/20210718231840882.png)
**图像透视**:
```python
import cv2
import numpy as np
img=cv2.imread('demo.bmp')
rows,cols=img.shape[:2]
print(rows,cols)
pts1 = np.float32([[150,50],[400,50],[60,450],[310,450]])
pts2 = np.float32([[50,50],[rows-50,50],[50,cols-50],[rows-50,cols-50]])
M=cv2.getPerspectiveTransform(pts1,pts2)
dst=cv2.warpPerspective(img,M,(cols,rows))
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()
图像复制:
import cv2
import numpy as np
img=cv2.imread(“lena.bmp”)
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(img.shape[:2],np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),j)
mapy.itemset((i,j),i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow(“original”,img)
cv2.imshow(“result”,rst)
cv2.waitKey()
cv2.destroyAllWindows()
绕x轴翻转
import cv2
import numpy as np
img=cv2.imread("lena.bmp")
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(img.shape[:2],np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),j)
mapy.itemset((i,j),rows-1-i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("original",img)
cv2.imshow("result",rst)
cv2.waitKey()
cv2.destroyAllWindows()
绕y
import cv2
import numpy as np
img=cv2.imread("lena.bmp")
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(img.shape[:2],np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),cols-1-j)
mapy.itemset((i,j),i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("original",img)
cv2.imshow("result",rst)
cv2.waitKey()
cv2.destroyAllWindows()
绕x,y:
import cv2
import numpy as np
img=cv2.imread("lena.bmp")
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(img.shape[:2],np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),cols-1-j)
mapy.itemset((i,j),rows-1-i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("original",img)
cv2.imshow("result",rst)
cv2.waitKey()
效果与翻转类似。
图像缩放:
import cv2
import numpy as np
img=cv2.imread("lena.bmp")
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(img.shape[:2],np.float32)
for i in range(rows):
for j in range(cols):
if 0.25*cols< i <0.75*cols and 0.25*rows< j <0.75*rows:
mapx.itemset((i,j),2*( j - cols*0.25 ) + 0.5)
mapy.itemset((i,j),2*( i - rows*0.25 ) + 0.5)
else:
mapx.itemset((i,j),0)
mapy.itemset((i,j),0)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("original",img)
cv2.imshow("result",rst)
cv2.waitKey()
cv2.destroyAllWindows()