原文链接:http://www.juzicode.com/opencv-python-resize-transpose-flip
在 OpenCV-Python教程:色彩空间变换 一文中我们介绍了在色彩空间对图像进行转换的方法,比如BGR转换为GRAY格式的灰度图,BGR色彩空间转换为HSV色彩空间,这篇文件将介绍图像在几何空间的转换,包括图片的缩放、转置、翻转等等。
1、缩放resize()
resize()可以实现图片大小的缩小或放大,接口形式:
dst=cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
- 参数含义:
- src:源图像;
- dsize:缩放后目标图像的尺寸,如果设置为0,目标图像则使用源图像的尺寸乘以fx和fy得到;dsize优先级高于fx和fy,如果设置了dsize,后面的fx和fy设置无效;
- fx和fy:dsize未设置的情况下,使用fx和fy分别作为宽度和高度的放大倍数;
- interpolation:插值方法,默认使用双线性插值cv2.INTER_LINEAR;
下面的例子中第1个resize直接指定新图像的大小为800×800,第2个例子则设置新图像的宽度为原始图像的0.5倍,高度为0.3倍:
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img1 = cv2.imread('..\\lena.jpg')
img_ret1 = cv2.resize(img1,(800,800))
print('img_ret1.shape:',img_ret1.shape)
cv2.imshow('lena-resize',img_ret1)
img_ret2 = cv2.resize(img1,None,fx=0.5,fy=0.3)
print('img_ret2.shape:',img_ret2.shape)
cv2.imshow('lena-resize2',img_ret2)
cv2.waitKey(0)
运行结果:
cv2.__version__: 4.5.2
img_ret1.shape: (800, 800, 3)
img_ret2.shape: (154, 256, 3)
通过设置fx或fy其中一个为1,另外一个为非0非1的值,可以实现图像的“拉伸”效果。
2、转置transpose()
transpose()可以实现像素下标的x和y轴坐标进行对调:dst(i,j)=src(j,i),接口形式:
dst = cv2.transpose(src[, dst])
下面的例子对lena.jpg和opencv-logo.png进行转置:
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img1 = cv2.imread('..\\lena.jpg')
img2 = cv2.imread('..\\opencv-logo.png')
img_ret1 = cv2.transpose(img1)
print('img1[161,199]: ',img1[161,199])
print('img_ret1[199,161]:',img_ret1[199,161])
cv2.imshow('lena-transpose',img_ret1)
img_ret2 = cv2.transpose(img2)
print('img2[100,200]: ',img2[100,200])
print('img_ret2[200,100]:',img_ret2[200,100])
cv2.imshow('logo-transpose',img_ret2)
cv2.waitKey(0)
运行结果:
VX公众号: 桔子code / juzicode.com
cv2.__version__: 4.5.2
img1[161,199]: [109 105 201]
img_ret1[199,161]: [109 105 201]
img2[100,200]: [ 0 0 255]
img_ret2[200,100]: [ 0 0 255]
从图像显示效果看,图像以对角线为轴,进行了翻转:
我们知道OpenCV的图像在Python接口中是以numpy数组形式存储的,numpy数组也有transpose()转置方法和T属性,是否也可以同numpy数组的转置方法进行转置呢?实测一把:
img1 = cv2.imread('..\\lena.jpg')
#img_ret1 = cv2.transpose(img1)
img_ret1 = img1.transpose()
print('img1.shape:',img1.shape)
print('img_ret1.shape:',img_ret1.shape)
print('img1[161,199]: ',img1[161,199])
print('img_ret1[199,161]:',img_ret1[199,161])
cv2.imshow('lena-transpose',img_ret1)
cv2.waitKey(0)
运行结果:
img1.shape: (512, 512, 3)
img_ret1.shape: (3, 512, 512)
img1[161,199]: [109 105 201]
Traceback (most recent call last):
File "img-transpose2.py", line 20, in <module>
print('img_ret1[199,161]:',img_ret1[199,161])
IndexError: index 199 is out of bounds for axis 0 with size 3
运行结果出错了,经过numpy数组的transpose()转置,第0轴和第2轴进行了转置,0轴的大小为3,所以数组下标访问越界了。另外图像shpae属性第3个元素表示的通道号变成了512,而不是原来的3,图像的的通道号要么是1、3或者4,其他的值是没有意义的。
3、翻转flip()
flip()函数可以实现对图像的水平翻转、垂直翻转和双向翻转。函数的接口形式:
dst=cv2.flip(src, flipCode[, dst])
- 参数含义:
- src:源图像;
- flipCode:翻转方式,0为水平轴翻转(上下翻转),大于0为垂直轴翻转(左右翻转),小于0做双向翻转。
下面这个例子对messi图像进行3种形式的翻转,并在matplotlib中显示,注意在matplotlib中显示时需要做色彩空间的转换,因为在matplotlib中是以R-G-B格式组织像素的:
import matplotlib.pyplot as plt
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
plt.rc('font',family='Youyuan',size='9')
plt.rc('axes',unicode_minus='False')
img1 = cv2.imread('..\\messi5.jpg')
img_ret1 = cv2.flip(img1,0)#水平轴翻转(上下翻转)
img_ret2 = cv2.flip(img1,1)#垂直轴翻转(左右翻转)
img_ret3 = cv2.flip(img1,-1)#双向翻转
fig,ax = plt.subplots(2,2)
ax[0,0].set_title('原图 VX:桔子code')
ax[0,0].imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)) #matplotlib显示图像为rgb格式
ax[0,1].set_title('上下翻转')
ax[0,1].imshow(cv2.cvtColor(img_ret1,cv2.COLOR_BGR2RGB))
ax[1,0].set_title('左右翻转')
ax[1,0].imshow(cv2.cvtColor(img_ret2,cv2.COLOR_BGR2RGB))
ax[1,1].set_title('双向翻转')
ax[1,1].imshow(cv2.cvtColor(img_ret3,cv2.COLOR_BGR2RGB))
ax[0,0].axis('off');ax[0,1].axis('off');ax[1,0].axis('off');ax[1,1].axis('off')#关闭坐标轴显示
plt.show()
运行结果:
小结:本教程前面几篇文章介绍的色彩空间转换、图像的加减乘除运算针对的是像素值本身,每个像素的坐标并未发生变化,而几何空间的变换主要涉及的则是图像坐标的变换。