缩放scale
缩放通过cv2.resize()实现
函数说明:
cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst
参数说明:
src - 原图
dst - 目标图像。当参数dsize不为0时,dst的大小为size;否则,它的大小需要根据src的大小,参数fx和fy决定。dst的类型(type)和src图像相同
dsize - 目标图像大小。当dsize为0时,它可以通过以下公式计算得出:
所以,参数dsize和参数(fx, fy)不能够同时为0
fx - 水平轴上的比例因子。当它为0时,计算公式如下:
fy - 垂直轴上的比例因子。当它为0时,计算公式如下:
interpolation - 插值方法。共有5种: INTER_NEAREST - 最近邻插值法 INTER_LINEAR - 双线性插值法(默认) INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取也叫缩小图像(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。 INTER_CUBIC - 基于4x4像素邻域的3次插值法 INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
缩小图像 用INTER_AREA更好,放大图像用 INTER_CUBIC更好;
代码示范:
import cv2
import numpy as np
# 读取一张照片
img = cv2.imread('d.jpg')
# 缩放成200x200的图像
img_200x200 = cv2.resize(img, (200, 200))
# 不直接指定缩放后大小,通过fx和fy指定缩放比例,0.5则长宽都为原来一半
# 等效于img_200x300 = cv2.resize(img, (300, 200)),注意指定大小的格式是(宽度,高度)
# 插值方法默认是cv2.INTER_LINEAR,这里指定为最近邻插值
img_200x300 = cv2.resize(img, (0, 0), fx=0.5, fy=0.5,
interpolation=cv2.INTER_NEAREST)
cv2.imwrite('resized_200x200.jpg', img_200x200)
旋转rotate
opencv中对图像的旋转主要是先通过getRotationMatrix2D函数得到图像的旋转矩阵,然后再通过仿射变换函数warpAffine得到旋转后的图像。
函数说明:
cv2.getRotationMatrix2D(center, angle, scale) cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
参数说明:
getRotationMatrix2D:
center–表示旋转的中心点 angle–表示旋转的角度degrees scale–图像缩放因子 warpAffine:
src – 输入的图像 M – 2 X 3 的变换矩阵. dsize – 输出的图像的size大小 dst – 输出的图像 flags – 输出图像的插值方法 borderMode – 图像边界的处理方式 borderValue – 当图像边界处理方式为BORDER_CONSTANT 时的填充值 代码示范:
img = cv2.imread('d.jpg',0)
rows,cols = img.shape
#90度旋转
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('rotate.jpg',dst)
图示:
裁剪crop
裁剪是利用array自身的下标截取实现
代码示范:
img = cv2.imread('d.jpg')
print img.shape
#裁剪
crop_img = img[100:350, 50:160]
cv2.imshow('crop_img.jpg', crop_img)
原图:
裁剪后图像:
填充pad
填充通过函数copyMakeBorder实现:
函数说明:
cv2.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) → dst
参数说明:
src – 输入的图像
dst – 输出的图像
top,bottom,left,right – 分别表示在原图四周扩充边缘的像素值
borderType –图像边界的处理方式
常见的borderType:
BORDER_REPLICATE :复制法,复制最边缘像素 BORDER_REFLECT_101:对称法,以最边缘像素为轴,对称 BORDER_CONSTANT:常量法,以一个常量参数值(自定参数value给定)填充扩充的边界 value – 当图像边界处理方式为BORDER_CONSTANT 时的填充值
代码示范:
# 在上张图片的基础上,上下各填充50像素,填充值为128,生成新的的图像
pad_img = cv2.copyMakeBorder(crop_img, 50, 50, 0, 0, cv2.BORDER_CONSTANT, value=(128, 128, 128))
cv2.imshow('pad_img.jpg', pad_img)
原图:
填充后图像:
平移translate
平移通过自定义平移矩阵以及函数warpAffine实现:
代码示范:
img = cv2.imread('d.jpg',0)
rows,cols = img.shape
# 平移矩阵M:[[1,0,x],[0,1,y]]
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('translate.jpg', dst)
图示:
翻转flip
翻转通过函数flip实现:
函数说明:
cv2.flip(src, flipCode[, dst]) → dst
参数说明:
src – 输入的图像 dst – 输出的图像 flipCode – 翻转模式,flipCode==0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°) 代码示范:
# 水平翻转
flip_horiz_img = cv2.flip(pad_img, 1)
# 垂直翻转
flip_verti_img = cv2.flip(pad_img, 0)
# 水平垂直翻转
flip_horandver_img = cv2.flip(pad_img, -1)
图像的仿射变换Affine transformation 图像的仿射变换涉及到图像的形状位置角度的变化,是深度学习预处理中常到的功能,在此简单回顾一下。仿射变换具体到图像中的应用,主要是对图像的缩放scale,旋转rotate,剪切shear,翻转flip和平移translate的组合。在OpenCV中,仿射变换的矩阵是一个2×3的矩阵,其中左边的2×2子矩阵是线性变换矩阵,右边的2×1的两项是平移项:
对于图像上的任一位置(x,y),仿射变换执行的是如下的操作:
需要注意的是,对于图像而言,宽度方向是x,高度方向是y,坐标的顺序和图像像素对应下标一致。所以原点的位置不是左下角而是右上角,y的方向也不是向上,而是向下。在OpenCV中实现仿射变换是通过仿射变换矩阵和cv2.warpAffine()函数的。
仿射变换矩阵:
缩放scale:在x轴方向扩大 x倍,y轴方向扩大 y倍
M = [ [x, 0, 0],
[0, y, 0] ]
旋转rotate:顺时针旋转x度
M = [ [cosx, -sinx, 0],
[sinx, cosx, 0] ]
剪切shear
M = [ [1, shx, 0],
[shy, 1, 0] ]
平移translate:向x方向移动 x, y方向移动 y
M = [ [1, 0, x],
[0, 1, y] ]
代码:
img = cv2.imread('d.jpg')
# 沿着横纵轴放大2倍,然后平移(-150,-240),最后沿原图大小截取,等效于裁剪并放大
M_crop_trans = np.array([
[2, 0, -150],
[0, 2, -240]
], dtype=np.float32)
img_crop_trans = cv2.warpAffine(img, M_crop_trans, (400, 600))
cv2.imshow('img_crop_trans.jpg', img_crop_trans)
# x轴的剪切shear变换,角度45°
theta = 45 * np.pi / 180
M_shear = np.array([
[1, np.tan(theta), 0],
[0, 1, 0]
], dtype=np.float32)
img_sheared = cv2.warpAffine(img, M_shear, (400, 600))
cv2.imshow('img_sheared.jpg', img_sheared)
# 顺时针旋转,角度45°
M_rotate = np.array([
[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0]
], dtype=np.float32)
img_rotated = cv2.warpAffine(img, M_rotate, (400, 600))
cv2.imshow('img_rotated.jpg', img_rotated)
# 某种变换,具体旋转+缩放+旋转组合可以通过SVD分解理解
M = np.array([
[1, 1.5, -400],
[0.5, 2, -100]
], dtype=np.float32)
img_transformed = cv2.warpAffine(img, M, (400, 600))
cv2.imshow('img_transformed.jpg', img_transformed)
读写视频文件
#可以直接读取视频文件,也可以获取摄像头数据,0的话就是摄像头的下标
capture = cv2.VideoCapture('video.mp4')
# capture = cv2.VideoCapture(0)
#视频宽
frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
#视频高
frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
#视频帧率
fps = capture.get(cv2.CAP_PROP_FPS)
#视频帧数
frame_number=capture.get(cv2.CV_CAP_PROP_FRAME_COUNT)
#保存视频的编码 mp4
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# 最后一个参数指是否使用彩色图像
video_path="new_video.mp4"
out = cv2.VideoWriter(video_path, fourcc, int(fps), (int(frame_width), int(frame_height)), False)
while capture.isOpened():
#ret 读取帧结果 True或False
ret, frame = capture.read()
if ret:
#opencv是以BGR通道读取图片,这里转换为灰度图
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#写入视频
out.write(gray_frame)
cv2.imshow('gray', gray_frame)
# cv2.waitKey()这个函数是在一个给定的时间内(单位ms)等待用户按键触发
# 如果用户没有按下按键,则继续等待(循环)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
capture.release()
out.release()
cv2.destroyAllWindows()
本文链接:http://nix.pub/article/opencv/