本篇用到的主要函数是:cv2.getRotationMatrix2D, 和cv2.warpAffine.
通过getRotationMatrix2D 函数,我们能得到一个仿射矩阵,这个矩阵代表了对图片进行的操作,包括:旋转和缩放等。然后再调用函数warpAffine,同时把仿射矩阵作为参数传入,就可以得到处理后的图片。
它们的参数和含义分别如下:
cv2.getRotationMatrix2D(center, angle, scale)
其中,center 指旋转的中心坐标;angle 代表旋转角度,比如,45代表逆时针旋转45°;scale 代表缩放程度,1.0表示不缩放。
cv2.warpAffine(src, M, dsize)
其中,src是待处理的图片;M是仿射矩阵,这里用getRotationMatrix2D的返回值;dsize 表示输出图片的大小。(warpAffine 有多个重载形式,这是最简单的一种)
示例1
import cv2
# 读取图片
img = cv2.imread("grass.jpg")
height, width, ch = img.shape
M = cv2.getRotationMatrix2D((width/2,height/2), 45, 1.0)
dst = cv2.warpAffine(img, M, (width,height))
# 显示图片
cv2.imshow("Original", img)
cv2.imshow("Rotate-45", dst)
# 按任意键退出图片显示
cv2.waitKey()
其中,仿射矩阵代表的操作是:以图片的中心为中心,逆时针旋转45度,图片大小不缩放。最后,程序显示结果如下图:
左边显示原始图片,右边是旋转过的图片。结果有点让人不满意的地方是,图片的四个角都没有显示出来。接下来我们试试把图片缩小一半,代码如下:
......
M = cv2.getRotationMatrix2D((width/2,height/2), 45, 0.5)
......
只是把getRotationMatrix2D最后一个参数改为0.5,程序显示结果如下图,
可以看出,缩小后的图片可以完整的显示出来了。
示例2
如果想保持图片的大小,同时又能完整显示出来,该怎么办呢?好像只能把输出图片的尺寸变大了。代码如下:
import cv2
# 读取图片
img = cv2.imread("grass.jpg")
height, width, ch = img.shape
M = cv2.getRotationMatrix2D((width/2,height/2), 45, 1.0)
dst = cv2.warpAffine(img, M, (width*2,height*2))
# 显示图片
cv2.imshow("Original", img)
cv2.imshow("Rotate-45", dst)
# 按任意键退出图片显示
cv2.waitKey()
程序显示结果如下图,
看来只放大输出图片尺寸还不行,要把图片平移一下。
示例3
下面的代码,把输出图片放大了一倍,同时对图片做旋转和平移操作。
import cv2
# 读取图片
img = cv2.imread("grass.jpg")
height, width, ch = img.shape
M = cv2.getRotationMatrix2D((width/2,height/2), 45, 1.0)
M[0,2] +=width/2
M[1,2] +=height/2
dst = cv2.warpAffine(img, M, (2*width,2*height))
# 显示图片
cv2.imshow("Original", img)
cv2.imshow("Rotate-45", dst)
# 按任意键退出图片显示
cv2.waitKey()
这里需要对仿射矩阵做进一步理解。 getRotationMatrix2D的返回值是一个2X3的矩阵,形式如下:
其中,a,b,c,d 用来控制旋转和缩放;Tx代表在x方向上移动的距离(正数向右移动,负数向左移动);Ty代表在y方向上平移的距离(正数向下移动,负数向上移动)。然而getRotationMatrix2D并没有提供平移的参数,所以我们只能在其输出结果上修改,然后再传给warpAffine函数。
......
M[0,2] +=width/2
M[1,2] +=height/2
......
所以,上面两行中,M[0,2]就是Tx, M[1,2]就是Ty,它们表示,图像向右移动width/2的距离,向下移动height/2的距离。
最终结果如下 ^_^
满意,收工!