在OpenCV中我们经常会用到图像的缩放,旋转以及平移,比如有的时候我们想对一类图片进行操作,这个时候我们就需要对这一类的图片进行尺寸统一,在以后深度学习的学习中,我们也会发现,对于数据集的训练,它们的数据集样本通常都是尺寸统一的。
缩放
在OpenCV中,使用函数cv2.resize()实现对图像的缩放 语法格式为:
dst = cv2.resize( src, dsize[ ,fx[, fy[ ,interpolation]]])
(1) src:原图片
(2)dsize:缩放图片尺寸,如果dsize=0,默认计算方式如下dsize=Size(round(fx∗src.cols),round(fy∗src.rows))
(3)fx fy和dsize不能同时为0 fx,fy分别是在x,y轴上的缩放系数,默认取0时,
fx=(double)dsize.width/src.cols ,fy=(double)dsize.height/src.cols,默认参数为0可以不写如里面
(4)interpolation :差值方式使用默认即可 默认的是INTER_LINEAR - a bilinear interpolation (used by default)现行差值:
我们习惯的坐标表示 是 先 x 横坐标,再 y 纵坐标。在图像处理中,这种惯性思维经常情况下是错误的。
因为在计算机中,图像是以矩阵的形式保存的,先行后列。所以,一张 宽×高×颜色通道=480×256×3 的图片会保存在一个 256×480×3 的三维张量中。图像处理时也是按照这种思想进行计算的(其中就包括 OpenCV 下的图像处理),即 高×宽×颜色通道。
但是问题来了,cv2.resize这个API却是个小例外。因为它的参数输入却是 宽×高×颜色通道。
我们来看代码:
import cv2
pic = cv2.imread("cat.jpg")
cv2.imshow("org",pic)
pic = cv2.resize(pic, (400, 400), interpolation=cv2.INTER_CUBIC)
cv2.imshow('res', pic)
cv2.waitKey(0)
cv2.destroyAllWindows()
先看原图效果:
再看缩放之后的效果:
我们发现,用这种方法缩小之后的宽高比跟原图并非一样,现在我们可以进行代码的改进:
import cv2
pic = cv2.imread("cat.jpg")
cv2.imshow("org",pic)
pic = cv2.resize(pic, (0, 0), fx=0.5, fy=0.5,
interpolation=cv2.INTER_NEAREST)
cv2.imshow('res', pic)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们直接来看缩放之后的图像:
在这里,如果我们不直接指定缩放后大小,则通过fx和fy直接指定缩放比例,0.5则长宽都为原来一半。
旋转
OpenCV中对图像的旋转主要是先通过getRotationMatrix2D函数得到图像的旋转矩阵,然后再通过仿射变换函数warpAffine得到旋转后的图像。
我们看一下函数:
cv2.getRotationMatrix2D(center, angle, scale)center 旋转中心点 (cx, cy) 你可以随意指定
angle 旋转的角度 单位是角度 逆时针方向为正方向 , 角度为正值代表逆时针。
scale 缩放倍数. 值等于1.0代表尺寸不变
该函数返回的就是仿射变换矩阵M,之后我们将这个仿射变换的矩阵传入到下一个函数:
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
src - 输入图像。
M - 变换矩阵。
dsize - 输出图像的大小。
flags - 插值方法的组合(int 类型!)
borderMode - 边界像素模式(int 类型!)
borderValue - 边界填充值; 默认情况下,它为0。
现在我们来讲述一下图像旋转的原理:
我们根据公式:
可以得出:
所以对应的变换矩阵为:
我们来看代码:
import cv2
img = cv2.imread("cat.jpg")
rows,cols = img.shape[:2]
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('res', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
旋转之后的效果:
图像平移
图像的平移实际上就是矩阵的移动,它是最简单的一种空间变换,其表达式为:
其中(b0,b1) 是偏移量。
举个例子,如果是向右平移10个像素, 向下平移30个像素的话, 那么变换矩阵M:
我们来看源码:
import cv2
import numpy as np
img = cv2.imread('cat.jpg')
height,width,channel = img.shape
# 声明变换矩阵 向右平移10个像素, 向下平移30个像素
M = np.float32([[1, 0, 10], [0, 1, 30]])
# 进行2D 仿射变换
shifted = cv2.warpAffine(img, M, (width, height))
cv2.imshow('res', shifted)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果演示:
如若需要修改平移的方位,只需要改动矩阵的值就可以。