专栏名称: GitChat技术杂谈
GitChat是新时代的学习工具。
目录
相关文章推荐
程序员小灰  ·  DeepSeek俱乐部,6000人了! ·  昨天  
程序员的那些事  ·  《人民日报》批谷歌安卓系统:假开源、真垄断 ·  2 天前  
程序员的那些事  ·  国企也中招!官网被挂上“码农的钱你也敢吞,* ... ·  2 天前  
程序猿  ·  松下电器突然官宣解散!曾风靡全球 ·  2 天前  
程序员的那些事  ·  DeepSeek 下棋靠忽悠赢了 ... ·  3 天前  
51好读  ›  专栏  ›  GitChat技术杂谈

PyQt 5 开发之旅之 OpenCV 的 GUI 特性

GitChat技术杂谈  · 公众号  · 程序员  · 2018-03-21 07:15

正文

本文来自作者 离梦远 GitChat 上分享 「PyQt 5 开发之旅之 OpenCV 的 GUI 特性」

编辑 | 哈比

背景

本篇适合 OpenCV (Python 版) 初学者入门使用。如果您对 OpenCV 比较了解,可以略过。

学习本文当然还要有一定的 Python 基础功底,至于 Python 2 还是 Python 3 无关紧要。

本文重点讲解 OpenCV 的 GUI 特性,还有部分 PyQt5 相关的内容,如果想动手敲代码的话一定要搭建好开发环境,关于开发环境我在另一场 Chat 有详细的介绍,本文不再讲解。

讲解过程中会做一些显示效果来说明,为了方便会先使用 OpenCV 自带的显示功能进行显示,后面总结的时候会结合 PyQt5 和 Matplotlib 显示。

开发环境搭建请参考 https://goo.gl/RnNSGy。

图像文件的读取、显示以及保存

读取图像

函数 cv2.imread(),有两个参数,参数 1 是要读入的图像文件 (包含路径), 参数 2 告诉函数应该如何读取图像 (可不填)

注意:图像的路径错误时,OpenCV 不会提醒。

下面列出读出方式:

  • cv2.IMREAD_COLOR(1):读入一副彩色图像,图像的透明度会被忽略,这是默认参数;会将图像转换成三通道、8 比特的图像。

  • cv2.IMREAD_GRAYSCALE(0):以灰度模式读入图像,会将图像转换成单通道、8 比特的图像。

  • cv2.IMREAD_UNCHANGED(-1):读入一副图像并且包括图像的 Alpha 通道,也就是使用原图像文件的通道数和比特数。

  • cv2.IMREAD_ANYCOLOR(4):转换成 8 比特的图像,通道数由图像文件决定,注意 4 通道图像会被转换成三通道图像。

  • cv2.IMREAD_ANYDEPTH(2):转换成单通道,比特数由图像文件决定。

下面用一个表格说明不同比特 (bit) 和通道 (Channel) 的图像读取之间的转换关系。

显示图像

显示图像就比较简单了,首先可以使用 OpenCV 自带的窗口显示,函数就是 cv2.imshow()。

第一个参数是窗口的名字,第二个参数是要显示的图像了,也就是 cv2.imread() 函数的返回值。

当然为了让显示窗口保持住程序不能运行结束需要使用 cv2.waitKey(),最后结束还要使用 cv2.destroyAllWindows() 销毁。

还有种方法就是使用 Matplotlib 来显示,这个要结合 PyQt5 在自己想要的地方进行显示的,显示过程和前面一个过程差不多。

但是要注意一点的是 Matplotlib 显示的彩色图像和 OpenCV 显示时候的 RGB 顺序不一样,所以在显示前要转换一下,这个在后面的例子中会详解。

保存图像

保存图像使用函数 cv2.imwrite(),它有两个参数:

  • 参数 1:要保存的文件名和后缀名以及保存的路径;

  • 参数 2:要保存的图像。

该函数会根据文件名的后缀自动保存相应的格式,不需要特殊指明,示例代码如下:

import cv2 img = cv2.imread('image/test2.jpg') cv2.imshow('demo', img) while True: if cv2.waitKey(20)&0xff == 27:    break cv2.destroyAllWindows() cv2.imwrite('sss.png', img)

效果如下图所示:

视频文件的获取和保存

获取视频帧

获取视频的函数为 cv2.VideoCapture()。

其参数可以是设备的索引号,也可以是视频文件。

索引号对应的是 PC 上的摄像头设备。获取到视频后,可以一帧一帧的获取 (使用 read()) 图像,但是最后,别忘记停止捕获视频 (使用 release() 函数)

read() 返回一个布尔值 (True/False) 。如果帧读取是正确的,就是 True。

有时候 cap(cv2.VideoCapture() 的返回值) 有可能无法成功的初始化摄像头的设备,这种情况下不能正常运行,可以使用 cap.isOpened(),来检测是否成功初始化。

如果返回是 True 就 OK,否则就需使用函数 cap.open()。

还可以使用函数 cap.get(propId) 来获得视频的一些参数信息。这里 propId 可以是 0 到 18 之间的任何整数,每个数代表视频的一个属性。

其中的一些值可以使用 cap.set(propId,value) 来修改,value 就是你想要设置成的新值。例如 cap.get(3) 和 cap.get(4) 来查看每一帧的宽和高。

那么如何显示视频呢?其实就是一帧一帧的显示读取到的每一帧图片,显示的快了就是视频的形式了。

可以使用 cv2.waitKey() 设置适当的持续时间。如果设置的太低视频就会播放的快,太高就会播放的慢 (使用这个方法控制视频的播放速度)。

通常情况下 25 毫秒就可以了。下面列出所有属性的值 (使用的时候也可以之间填写括号中的数值)

cv2.CAP_PROP_POS_MSEC(0):current position of the video file in milliseconds cv2.CAP_PROP_POS_FRAMES(1):0-based index of the frame to be decoded/captured next cv2.CAP_PROP_POS_AVI_RATIO(2):Relative position of the video file:0-start of the film,1-end of the film. cv2.CAP_PROP_FRAME_WIDTH(3):width of the frames in the video stream. cv2.CAP_PROP_FRAME_HEIGHT(4):hright of the frames in the video stream. cv2.CAP_PROP_FPS(5):frame rate. cv2.CAP_PROP_FOURCC(6):4-character code of codec. cv2.CAP_PROP_FRAME_COUNT(7):number of frames in the video file. cv2.CAP_PROP_FORMAT(8):format of the Mat objects returned by retrieve(). cv2.CAP_PROP_MODE(9): Backend-specific value indicating thecurrent capture mode. cv2.CAP_PROP_BRIGHTNESS(10): Brightness of the image (only for cameras). cv2.CAP_PROP_CONTRAST(11): Contrast of the image (only for cameras). cv2.CAP_PROP_SATURATION(12): Saturation of the image (only for cameras). cv2.CAP_PROP_HUE(13): Hue of the image (only for cameras). cv2.CAP_PROP_GAIN(14): Gain of the image (only for cameras). cv2.CAP_PROP_EXPOSURE(15): Exposure (only for cameras). cv2.CAP_PROP_CONVERT_RGB(16): Boolean flags indicatingwhether images should be converted to RGB. cv2.CAP_PROP_WHITE_BALANCE(17): Currently unsupported cv2.CAP_PROP_RECTIFICATION(18): Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently

保存视频

在我们捕获视频,并对每一帧都进行加工之后我们想要保存这个视频,对于图片来说很简单使用 cv2.imwrite()。但是对于视频来说就要多做点工作。

首先要创建一个 VideoWriter 的对象,我们应该确定一个输出文件的名字。接下来指定 FourCC 编码。播放频率和帧的大小也需要确定。

最后一个是 isColor 标签,如果是 True,每帧就是彩色图,否则就是灰度图。

下面用一个实际操作的例子说明一下:

import cv2 import numpy as np # 选取摄像头,0 为笔记本内置的摄像头,1,2···为外接的摄像头 cap = cv2.VideoCapture(0) #定义摄像头的分辨率 cap.set(4,720) #第一个参数是路径和文件名,文件命名的时候不要有特殊的符号 #第二个参数是视频格式,“MPEG” 是一种标准格式,百度 fourcc 可见各种格式 #第二个参数(fourcc)如果设置为-1,允许实时选择视频格式 fourcc = cv2.VideoWriter_fourcc(*"MPEG") # 第三个参数则是镜头快慢的,20 为正常,小于二十为慢镜头 out = cv2.VideoWriter('./output.avi',fourcc,20,(640,480)) while True: ret,frame = cap.read()  # 获取图像 if ret == True:    frame = cv2.flip(frame, 1)# 在帧上进行操作    cv2.imshow("frame", frame)  # 显示帧    out.write(frame) # 保存视频    if cv2.waitKey(1) == ord('s'):  #按下 ‘s’ 保存图片        print('save photo')        cv2.imwrite("./new.png",frame)        if cv2.waitKey(1) == ord('q'):#按下 ‘q’ 退出            print('quit')            break    else: break # 释放摄像头资源 cap.release() out.release() cv2.destroyAllWindows()

OpenCV 中的绘图函数

OpenCV 中的绘图函数是在图像上绘制直线 (line) 、圆 (circle) 、矩形 (rectangle) 、椭圆 (ellipse) 、文字 (putText) 等,这些函数除需要自己特有的参数外,还有共同的参数如下:

  • img:绘制图像的那副图像;

  • color:绘制图形的颜色,以 BGR 为例,需要传入一个元祖,例如 (255,0,0),代表蓝色。对于灰度图只需要传入灰度值;

  • thickness:线条的粗细。如果给一个闭合图形设置为-1,那么这个图形就会被填充。默认值就是-1;

  • linetype:线条的类型,有连接、抗锯齿等。默认情况是 8 表,示连接。cv2.LINE_AA 表示抗锯齿。这样子看起来非常平滑。

画线

画线需要知道线的起点和终点,例如画一个起点 (0,0) 和终点 (100,100) ,线宽为 5 (像素) ,颜色为蓝色的线,代码如下:

import numpy as np import cv2 img = np.zeros((400,400,3), np.uint8)# 创建一副图像 cv2.line(img, (0,0), (100,100), (255,0,0), 5)







请到「今天看啥」查看全文