Python-OpenCV自学笔记(一)安装与基本功能

一、OpenCV简介与安装

1.OpenCV简介

此次学习OpenCV是为了参加一个机器视觉相关的大创项目,老师的要求是OpenCV+Python。

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。OpenCV用C++语言编写,它的主要接口也是C++语言,该库也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。

2.安装

电脑为win10系统,之前安装了Python3.7,直接在命令行安装:

pip install opencv-python

二、文件处理

1.读取、写入图像

#!/usr/bin/env python3        
# -*- coding: utf-8 -*-  
import cv2
 
# 载入图像
im = cv2.imread('./0.png') 
 
# 打印图像尺寸
h,w = im.shape[:2]
print(h,w)
 
# 保存PNG格式图像为JPEG格式
cv2.imwrite('./0.jpg',im)

注意:import cv2不是指OpenCV2版本,”cv2”中的”2”并不表示OpenCV的版本号。我们知道,OpenCV是基于C/C++的,”cv”和”cv2”表示的是底层C API和C++API的区别,”cv2”表示使用的是C++API。这主要是一个历史遗留问题,是为了保持向后兼容性。

此外,在OpenCV中,图像就是用numpy.ndarray存储的。

imread()函数原型:imread(const string& filename, int flag=1)

flag=-1时,8位深度,原通道
flag=0,8位深度,1通道
flag=1, 8位深度 ,3通道
flag=2,原深度,1通道
flag=3, 原深度,3通道
flag=4,8位深度 ,3通道
"IMREAD_UNCHANGED"指定用图片的原来格式打开,即以不改变图片的方式打开,图片是彩色就是彩色,图片是灰度图像就是灰度图像
"IMREAD_GRAYSCALE"指定用灰度图像的方式打开图片,即将原始图像转化为灰度图像再打开
"IMREAD_COLOR"指定用彩色图像打开图片

flag默认为1,即读取为彩色图像,如果要读取为灰度图(单通道),只需要把flag修改为为0即可。

2.颜色空间转换

#!/usr/bin/env python3        
# -*- coding: utf-8 -*-  
import cv2
 
# 载入图像
im = cv2.imread('./2.png')
print(im.shape)

 
# create a grayscale version
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
print(gray.shape)

运行结果:
(66, 66, 3)
(66, 66)

注:使用opencv读取图片时, 默认的通道顺序是BGR而非RGB

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2

#不同参数时的加载图像
grayImg = cv2.imread('./3.png')
cv2.imwrite('3_1.png', grayImg)
grayImg = cv2.imread('./3.png', cv2.IMREAD_GRAYSCALE)
cv2.imwrite('3_2.png', grayImg)

在这里插入图片描述
在这里插入图片描述

3.显示图像

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('4.png')
cv2.imshow('my image', img)    # 参数:显示图像的帧名称、要显示的图像本身
cv2.waitKey()    # 参数为等待键盘触发的时间,当delay≤0,可以理解为延迟无穷大毫秒,就是暂停
cv2.destroyAllWindows()    # 释放全部窗口

注意:imshow()会放大图片,171k的png图片即可占满全屏,再大的图片会有打不开的现象

另外还有一种显示图像的方法:

# !/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2
from pylab import *

# 添加中文字体支持
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

# 载入图像
im = cv2.imread('2.png')

#matplotlib 中图像通道为 RGB,而 OpenCV 中图像通道为 BGR。
#因此进行显示的时候,要注意交换通道的顺序。
im2 = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)

# 颜色空间转换
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# 显示原始图像
fig = plt.figure()
subplot(121)
plt.gray()
imshow(im2)
title(u'彩色图', fontproperties=font)
axis('off')
# 显示灰度化图像
plt.subplot(122)
plt.gray()
imshow(gray)
title(u'灰度图', fontproperties=font)
axis('off')

show()

Python-OpenCV自学笔记(一)安装与基本功能_第1张图片

4.获取属性

import cv2
img = cv2.imread('2.png')
print(img.shape)
# (640, 640, 3)
print(img.size)
# 1228800
print(img.dtype)
# uint8
# 在debug的时候,dtype很重要

运行结果:
(3861, 2574, 3)
29814642
uint8

三、简单变换

1.缩放图片

下面的例子将实现缩放图片并保存,这个在使用 OpenCV 做图像处理的时候都是很常用的操作:

import cv2

img = cv2.imread('./4.png')
print(img.shape[:2])

height, width = img.shape[:2]

reSize1 = cv2.resize(img, (2*width, 2*height), interpolation=cv2.INTER_CUBIC)
reSize2 = cv2.resize(img, (int(width/2), int(height/2)), interpolation=cv2.INTER_CUBIC)

cv2.imshow('reSize1', reSize1)
cv2.imshow('reSize2', reSize2)

cv2.waitKey()
cv2.destroyAllWindows()

2.输出文本

import cv2

im = cv2.imread('./0.png')
cv2.putText(im, 'Hello World', (50, 50), 0, 0.5, (0, 0, 255), 2)
cv2.imshow('txt', im)
cv2.waitKey()
cv2.destroyAllWindows()

Python-OpenCV自学笔记(一)安装与基本功能_第2张图片

3.翻转图片

  • 1 水平翻转
  • 0 垂直翻转
  • -1 水平垂直翻转
imgflip = cv2.flip(img,1)

4.复制图片

imgcopy = img.copy()

四、摄像头与视频

1.视频文件读写

OpenCV提供了VideoCapture类和VideoWriter类来支持各种格式的视频文件。

	=	cv.VideoCapture(		)
	=	cv.VideoCapture(	filename[, apiPreference]	)
	=	cv.VideoCapture(	index[, apiPreference]	)
# 参数为0时打开电脑摄像头
	=	cv.VideoWriter(		)
	=	cv.VideoWriter(	filename, fourcc, fps, frameSize[, isColor]	)
	=	cv.VideoWriter(	filename, apiPreference, fourcc, fps, frameSize[, isColor]	)

支持的格式类型会因系统的不同而变化,但应该都支持AVI格式。在到达视频文件末尾之前,VideoCapture类可通过read()函数来获取新的帧,每帧都是一幅基于BGR格式的图像。

可将一幅图像传递给VideoWriter类的write()函数,该函数会将这幅图像加到VideoWriter类所指向的文件中。

fourcc:用于压缩帧的4字符编解码器代码。例如,VideoWriter :: fourcc(‘P’,‘I’,‘M’,‘1’)是MPEG-1编解码器,VideoWriter :: fourcc(‘M’,‘J’,‘P’,‘G’)是一个运动jpeg编解码器等。代码列表可以通过FOURCC页面在视频编解码器中获得。

如下示例读取AVI文件的帧,并采用YUV颜色编码将其写入另一帧中:

import cv2
videoCapture = cv2.VideoCapture(0)    # 读取视频文件
fps = videoCapture.get(cv2.CAP_PROP_FPS)    # 获取帧率(每秒钟帧数)

# 获取视频流中帧的宽度和高度
size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))

# cv2.VideoWriter_fourcc()函数的作用是输入四个字符代码即可得到对应的视频编码器。
videoWriter = cv2.VideoWriter('video2.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)

# videoCapture.read()写入视频抓取,解码并返回下一个视频帧
# 如果没有抓取帧(摄像机已断开连接,或视频文件中没有帧),则方法返回false,函数返回NULL指针
success, frame = videoCapture.read()

while success:  # 循环直到所有帧结束
    videoWriter.write(frame)
    success, frame = videoCapture.read()

要特别注意:必须要为VideoWriter类的构造函数指定视频文件名,这个文件名对应的文件若存在,会被覆盖。也必须指定视频编解码器。编解码器的可用性根据系统不同而不同。下面是一些常用选项:

cv2.VideoWriter_force(‘I’, ‘4’, ‘2’, ‘0’):该选项是一个未压缩的YUV颜色编码,是4:2:0色度子采样。这种编码有很好的兼容性,但会产生较大文件,文件扩展名为.avi。

cv2.VideoWriter_force(‘P’, ‘I’, ‘M’, ‘1’):该选项是MPEG-1编码类型,文件扩展名为.avi。

cv2.VideoWriter_force(‘X’, ‘V’, ‘I’, ‘D’):该选项是MPEG-4编码类型,如果希望得到的视频大小为平均值,推荐使用此选项,文件扩展名为.avi。

cv2.VideoWriter_force(‘T’, ‘H’, ‘E’, ‘O’):该选项是Ogg Vorbis,文件扩展名应为.ogv。

cv2.VideoWriter_force(‘F’, ‘L’, ‘V’, ‘1’):该选项是一个Flash视频,文件扩展名应为.flv。

帧速率和帧大小也必须要指定,因为需要从另一个视频文件复制视频帧,这些属性可以通过VideoCapture类的get()函数得到。

2.捕获摄像头的帧

VideoCapture类可以获得摄像头的帧流。但对摄像头而言,通常不是用视频的文件名来构造VideoCapture类,而是需要传递摄像头的设备索引(device index)。

下面的例子会捕获摄像头10秒的视频信息,并将其写入一个AVI文件中:

import cv2

cameraCapture = cv2.VideoCapture(0)
fps = 30
size = (int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
videoWriter = cv2.VideoWriter('MyOutputVid.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)
success, frame = cameraCapture.read()
numFramesRemaining = 10 * fps - 1
while success and numFramesRemaining > 0:
    videoWriter.write(frame)
    success, frame = cameraCapture.read()
    numFramesRemaining -= 1
cameraCapture.release()

然而,VideoCapture类的get()方法不能反悔摄像头帧速率的准确值,它总是返回0。

为了针对摄像头创建合适的VideoWriter类,要么对帧速率做出假设,要么使用计时器来测量。摄像头的数量和顺序由系统决定,但OpenCV没有提供任何查询摄像头数量和属性的方法。如果使用无效索引构造了VideoCapture类,就不会得到帧,VideoCapture的read()函数会返回(false, None)。为了不让read()函数从没有正确打开的VideoCapture类中获取数据,可在执行该函数之后使用VideoCapture.isOpened方法做一个判断,该方法返回一个Boolean值。

当需要同步一组摄像头或一个多头摄像头(例如立体摄像头或Kinect)时,read()方法就不再适合了,可用grab()和retrive()方法代替它。

你可能感兴趣的:(openCV)