缩放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)

resized_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)

图示: rotate

裁剪crop

裁剪是利用array自身的下标截取实现

代码示范:

img = cv2.imread('d.jpg')
print img.shape
#裁剪
crop_img = img[100:350, 50:160]
cv2.imshow('crop_img.jpg', crop_img)

原图: d

裁剪后图像: 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)

原图: crop_img

填充后图像: 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)

图示: translate

翻转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_horiz_img

# 垂直翻转
flip_verti_img = cv2.flip(pad_img, 0)

flip_verti_img

# 水平垂直翻转
flip_horandver_img = cv2.flip(pad_img, -1)

flip_horandver_img

图像的仿射变换Affine transformation 图像的仿射变换涉及到图像的形状位置角度的变化,是深度学习预处理中常到的功能,在此简单回顾一下。仿射变换具体到图像中的应用,主要是对图像的缩放scale,旋转rotate,剪切shear,翻转flip和平移translate的组合。在OpenCV中,仿射变换的矩阵是一个2×3的矩阵,其中左边的2×2子矩阵是线性变换矩阵,右边的2×1的两项是平移项:

Affine1 对于图像上的任一位置(x,y),仿射变换执行的是如下的操作:

Affine2

需要注意的是,对于图像而言,宽度方向是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)

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)

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)

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)

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 读取帧结果 TrueFalse
     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/