图像处理库OpenCV安装与使用
2019-05-09 本文已影响0人
Byte猫
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
官方文档
安装
pip install opencv-python
pip install opencv-contrib-python # 安装opencv-contrib,包含一些其它库,比如xfeature2d
在安装后通过在python控制台中输入"import cv2"命令可以验证是否成功安装
使用OpenCV
1、图像的存取
import cv2 as cv
# 读取彩色图像
img = cv.imread('test.jpg') # 读取后直接就是numpy数组的形式
# 直接读取单通道灰度图
gray_img = cv.imread('test.jpg', cv.IMREAD_GRAYSCALE)
# 彩色图变为灰度图
# gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 灰度图像二值化
# threshold = 155
# _, binary_image = cv.threshold(gray_img, threshold, 255, cv.THRESH_BINARY) # 超过阈值的像素值修改成设定值,其他值为0
# 输出图片信息
print('彩色图片尺寸:', img.shape)
print('彩色图片数据:', type(img), img)
print('灰度图片尺寸:', gray_img.shape)
print('灰度图片数据:', type(gray_img), gray_img)
把单通道图片保存后,再读取,仍然是3通道,相当于把单通道值复制到3个通道保存
cv.imwrite('test_gray.jpg', gray_img)
reload_grayimg = cv.imread('test_gray.jpg')
print(reload_grayimg.shape)
保存图像时还可以根据需要控制文件大小
# IMWRITE_JPEG_QUALITY指定jpg质量,范围0到100,默认95,越高画质越好,文件越大
cv.imwrite('test_imwrite.jpg', color_img, (cv.IMWRITE_JPEG_QUALITY, 80))
# IMWRITE_PNG_COMPRESSION指定png质量,范围0到9,默认3,越高文件越小,画质越差
cv.imwrite('test_imwrite.png', color_img, (cv.IMWRITE_PNG_COMPRESSION, 5))
2、图像显示
cv.imshow('picture show', img)
cv.waitKey(0)
if k == 27: # wait for ESC key to exit
cv.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
cv.imwrite('mypic.png', img)
cv.destroyAllWindows()
需要注意的是opencv加载的图像色彩通道是BGR不是RGB,如果想要用matplotlib进行显示,需要进行转换
import matplotlib.pyplot as plt
# 改变颜色 (from BGR to RGB)
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.imshow(img)
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.show()
3、色度、饱和度、明度
调整色度
# 通过cvtColor把图像从BGR转换到HSV
img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# H空间中,绿色比黄色的值高一点,所以给每个像素+15,黄色的树叶就会变绿
turn_green_hsv = img_hsv.copy()
turn_green_hsv[:, :, 0] = (turn_green_hsv[:, :, 0]+15) % 180
turn_green_img = cv.cvtColor(turn_green_hsv, cv.COLOR_HSV2BGR)
调整饱和度
# 减小饱和度会让图像损失鲜艳,变得更灰
colorless_hsv = img_hsv.copy()
colorless_hsv[:, :, 1] = 0.5 * colorless_hsv[:, :, 1]
colorless_img = cv.cvtColor(colorless_hsv, cv.COLOR_HSV2BGR)
调整明度
# 减小明度为原来一半
darker_hsv = img_hsv.copy()
darker_hsv[:, :, 2] = 0.5 * darker_hsv[:, :, 2]
darker_img = cv.cvtColor(darker_hsv, cv.COLOR_HSV2BGR)
4、图像变换
图像缩放
# 指定大小,缩放成 (width, height)的图像
img_resize = cv.resize(img, (200, 200))
# 按照50%比例缩放, interpolation表示使用何种差值方式对图像进行缩放
# INTER_NEAREST为采用最近邻插值
# INTER_LINEAR为双线性插值,默认情况使用
# INTER_NEAREST为最邻近插值
# INTER_AREA使用像素区域关系重新采样,和INTER_NEAREST相似
# INTER_CUBIC采用4x4像素邻域内的双立方插值
img_resize = cv.resize(img, (0, 0), fx=0.5, fy=0.5, interpolation=cv.INTER_NEAREST)
图像旋转
def rotate_bound(image, angle):
'''
图像旋转
INPUT -> 图像数组, 旋转角度(顺时针)
'''
(h, w) = image.shape[:2]
# 旋转中心点
(cX, cY) = (w // 2, h // 2)
# 获得旋转矩阵
M = cv.getRotationMatrix2D((cX, cY), -angle, 1.0)
#theta = angle * np.pi / 180
#M = np.array([
# [np.cos(theta), -np.sin(theta), 0],
# [np.sin(theta), np.cos(theta), 0]
#], dtype=np.float32)
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
# 计算图像新外接框
nW = int((h * sin) + (w * cos))
nH = int((h * cos) + (w * sin))
M[0, 2] += (nW / 2) - cX
M[1, 2] += (nH / 2) - cY
return cv.warpAffine(image, M, (nW, nH))
img2 = rotate_bound(img, 45)
图像截取
# 直接截取
dst = img[10:600, 10:400]
# 沿着横纵轴放大1.6倍,然后平移(-150,-240),最后按原图大小截取,等效于裁剪并放大
M = np.array([
[1.6, 0, -150],
[0, 1.6, -240]
], dtype=np.float32)
dst = cv.warpAffine(img, M, (img.shape[1], img.shape[0]))
图像移位
M = np.array([
[1, 0, -150],
[0, 1, -240]
], dtype=np.float32)
dst = cv2.warpAffine(img, M, (height,width))
5、摄像头、视频的读取以及保存
打开摄像头并保存视频
# coding = utf-8
import numpy as np
import cv2 as cv
import time
def video_save(num_frames, filepath, out_fps):
'''
打开摄像头并保存视频
INPUT -> 捕获总帧数, 视频保存路径, 输出帧率
'''
cap = cv.VideoCapture(0) # VideoCapture(0)表示打开默认的相机
if cap.isOpened() is False: # 确认摄像头是否成功打开
print('Error')
exit(1)
# 获取捕获的分辨率
size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),
int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
# 设置要保存视频的编码,分辨率和帧率
video = cv.VideoWriter(
filepath,
cv.VideoWriter_fourcc('M', 'P', '4', '2'), # 视频编码格式参考:http://www.fourcc.org/codecs.php
out_fps, # 输出文件的帧率
size
)
for i in range(num_frames):
ret, frame = cap.read()
video.write(frame)
# time.sleep(interval) 捕获图像的间隔(秒)
# 释放资源并写入视频文件
video.release()
cap.release()
video_save(100, '100000.avi', 24)
def video_save2(key, window_name, path, out_fps):
'''
打开摄像头并保存视频(不限定总帧数,直到按下某键)
INPUT -> 按键, 窗口名, 视频保存路径, 输出帧率
'''
cv.namedWindow(window_name) # 创建一个窗口
cap = cv.VideoCapture(0) # VideoCapture(0)表示打开默认的相机
if cap.isOpened() is False: # 确认摄像头是否成功打开
print('Error')
exit(1)
# 获取捕获的分辨率
size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),
int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
# 设置要保存视频的编码,分辨率和帧率
video = cv.VideoWriter(
path,
cv.VideoWriter_fourcc('M', 'P', '4', '2'), # 视频编码格式参考:http://www.fourcc.org/codecs.php
out_fps, # 输出文件的帧率
size
)
while True:
ret, frame = cap.read()
video.write(frame)
cv.imshow(window_name, frame) # 将图像矩阵显示在一个窗口中
if cv.waitKey(20) & 0xFF == ord(key): # 每隔20ms采集一帧,按某键退出采集
break
# 释放资源并写入视频文件
video.release()
cap.release()
cv.destroyWindow(window_name)
video_save2('k', 'test window', '100001.avi', 24)
间隔读取视频文件中的每帧的图片
def video_extraction(filepath, interval):
'''
视频帧提取
INPUT -> 视频地址, 帧间隔
'''
if not os.path.exists(os.path.abspath(filepath) +"_extraction"):
os.mkdir(os.path.abspath(filepath) +"_extraction")
cap = cv.VideoCapture()
cap.open(filepath)
# 获取视频帧数
num_frames = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
for i in range(num_frames):
ret, frame = cap.read()
if i % interval == 0: # 每隔interval帧进行一次截屏操作
imagepath = os.path.abspath(filepath) +"_extraction\ " + str(i)+".jpg"
print('导出 {}!'.format(imagepath))
cv.imwrite(imagepath, frame)
# 执行结束释放资源
cap.release()
video_extraction('100001.avi', 10)