Cameo项目介绍:

1、实时捕获并显示摄像头帧。

2、具备截图、保存视频和退出三个功能键。

要求存在文件:manager.py 和 cameo.py

一、manager.py

两个类:CaptureManager、WindowManager

  CaptureManager负责摄像头帧的捕获,编解码得到实际帧,当前帧保存为图片、一段时间内的帧保存为视频这四个核心功能。

  CaptureManager负责窗口的创建、窗口展示当前画面、三个功能键的交互、关闭窗口释放资源这四个个功能

二、cameo.py

程序入口,关联调用CaptureManager和CaptureManager,并定义三个功能键

详细方法实现参照下述代码和注释

manager.py

  1 from __future__ import annotations
2 import cv2
3 import numpy
4 import time
5
6 '''
7 1、允许同一文件下不同类之间的类型提示,py3.7以上特性
8 2、cv2——获取摄像头和展示
9 3、numpy——对展示画面进行左右翻转(fliplr)
10 4、time——精确获取时间间隔,然后计算帧率估值
11 '''
12
13
14 class CaptureManager:
15 def __init__(self, capture: cv2.VideoCapture,
16 previewWindowManager: WindowManager = None,
17 shouldMirrorPreview: bool = False):
18 self.previewWindowManager = previewWindowManager
19 self.shouldMirrorPreview = shouldMirrorPreview
20
21 self._capture = capture
22 self._channel = 0
23 self._enteredFrame = False
24 self._frame = None
25
26 self._imageFilename = None
27 self._videoFilename = None
28 self._videoEncoding = None
29 self._videoWriter = None
30
31 self._startTime = None
32 self._framesElapsed = 0
33 self._fpsEstimate = None
34
35 @property
36 def channel(self):
37 return self._channel
38
39 @channel.setter
40 def channel(self, value):
41 if self._channel != value:
42 self._channel = value
43 self._frame = None # 对通道赋值时需要将当前帧置空,否则可能出现通道为未更改现象
44
45 # 如果进入帧,且当前帧为None则对已捕获的帧进行解码和获取实际图像帧
46 @property
47 def frame(self):
48 if self._enteredFrame and self._frame is None:
49 _, self._frame = self._capture.retrieve(self._frame, self.channel)
50 return self._frame
51
52 @property
53 def isWritingImage(self):
54 return self._imageFilename is not None
55
56 @property
57 def isWritingVideo(self):
58 return self._videoFilename is not None
59
60 def enterFrame(self):
61 # 检查上一帧是否被处理完,如未处理完,则会被下一帧覆盖,最终导致实时画面或者保存的视频不连续
62 assert not self._enteredFrame, 'previous enterFrame() had no matching exitFrame()'
63
64 if self._capture is not None:
65 self._enteredFrame = self._capture.grab()
66
67 def exitFrame(self):
68 # 如果当前帧为None,表示未成功捕获有效帧或视频流已处理完成,此时则直接结束此方法
69 if self.frame is None:
70 self._enteredFrame = False
71 return
72
73 # 更新FPS估值
74 if self._framesElapsed == 0:
75 self._startTime = time.perf_counter()
76 else:
77 timeElapsed = time.perf_counter() - self._startTime
78 self._fpsEstimate = self._framesElapsed / timeElapsed
79 self._framesElapsed += 1
80
81 # 是否水平反转画面并展示
82 if self.previewWindowManager is not None:
83 if self.shouldMirrorPreview:
84 mirroredFrame = numpy.fliplr(self._frame)
85 self.previewWindowManager.show(mirroredFrame)
86 else:
87 self.previewWindowManager.show(self._frame)
88
89 # 将当前帧保存为图片
90 if self.isWritingImage:
91 cv2.imwrite(self._imageFilename, self._frame)
92 self._imageFilename = None
93
94 # 将当前帧写入视频
95 self._writeVideoFrame()
96
97 # 释放并退出当前帧
98 self._frame = None
99 self._enteredFrame = False
100
101 def writeImage(self, filename):
102 self._imageFilename = filename
103
104 def startWritingVideo(self, filename, encoding=cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')):
105 self._videoFilename = filename
106 self._videoEncoding = encoding
107
108 def stopWritingVideo(self):
109 self._videoFilename = None
110 self._videoEncoding = None
111 self._videoWriter = None
112
113 def _writeVideoFrame(self):
114 if not self.isWritingVideo:
115 return
116
117 # 检查是否创建了VideoWriter对象
118 if self._videoWriter is None:
119 # 获取摄像头帧率
120 fps = self._capture.get(cv2.CAP_PROP_FPS)
121 # 如果帧率获取失败则使用估计值
122 if numpy.isnan(fps) or fps <= 0.0:
123 # 获取更多的以处理帧数,以求得更稳定的帧率
124 if self._framesElapsed < 20:
125 return
126 else:
127 fps = self._fpsEstimate
128 size = (int(self._capture.get(
129 cv2.CAP_PROP_FRAME_WIDTH)),
130 int(self._capture.get(
131 cv2.CAP_PROP_FRAME_HEIGHT)))
132 self._videoWriter = cv2.VideoWriter(
133 self._videoFilename, self._videoEncoding,
134 fps, size)
135
136 self._videoWriter.write(self._frame)
137
138
139 class WindowManager(object):
140
141 def __init__(self, windowName: str
142 , keypressCallback=None):
143 self.keypressCallback = keypressCallback
144
145 self._windowName = windowName
146 self._isWindowCreated = False
147
148 @property
149 def isWindowCreated(self):
150 return self._isWindowCreated
151
152 def createWindow(self):
153 cv2.namedWindow(self._windowName)
154 self._isWindowCreated = True
155
156 def show(self, frame):
157 cv2.imshow(self._windowName, frame)
158
159 def destroyWindow(self):
160 cv2.destroyWindow(self._windowName)
161 self._isWindowCreated = False
162
163 def processEvents(self):
164 keycode = cv2.waitKey(1)
165 if self.keypressCallback is not None and keycode != -1:
166 self.keypressCallback(keycode)

cameo.py

 1 import cv2
2 from managers import WindowManager, CaptureManager
3
4
5 class Cameo:
6 def __init__(self):
7 self._windowManager = WindowManager('Cameo',
8 self.onKeypress)
9 self._captureManager = CaptureManager(
10 cv2.VideoCapture(0), self._windowManager, True)
11
12 def run(self):
13 # 创建窗口
14 self._windowManager.createWindow()
15 while self._windowManager.isWindowCreated:
16 # 开始捕获摄像头帧
17 self._captureManager.enterFrame()
18 # 解码并获取实际帧
19 frame = self._captureManager.frame
20 # 预留后续新功能
21 if frame is not None:
22 pass
23 # 写入图片文件或者视频文件并释放帧资源
24 self._captureManager.exitFrame()
25 # 检查并返回键盘状态
26 self._windowManager.processEvents()
27
28 def onKeypress(self, keycode):
29 if keycode == 32: # space
30 self._captureManager.writeImage(r'screenshot.png')
31 elif keycode == 9: # tab
32 if not self._captureManager.isWritingVideo:
33 self._captureManager.startWritingVideo('screencast.avi')
34 else:
35 self._captureManager.stopWritingVideo()
36 elif keycode == 27: # escape
37 self._windowManager.destroyWindow()
38
39
40 if __name__ == "__main__":
41 Cameo().run()

【Python】【OpenCV】Cameo项目(一)实时显示摄像头帧的更多相关文章

  1. Javaweb项目页面实时显示后台处理结果

    http://www.cnblogs.com/dong-xu/p/6701271.html 此博文甚好,项目参照博主代码可实现. 前端页面: <%@ page language="ja ...

  2. 使用Python控制1602液晶屏实时显示时间(附PyCharm远程调试)

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文介绍一下UP板的GPIO资源使用,以及一个使用Python演示一个简单的demo. 本文使用Markdown写成,为获得更好的 ...

  3. GUI开发:实时显示摄像头图像

    import tkinter as tk from PIL import Image, ImageTk import cv2 import numpy as np import time g_exit ...

  4. python opencv3 窗口显示摄像头的帧

    git:https://github.com/linyi0604/Computer-Vision # coding:utf8 import cv2 """ 在窗口显示摄像 ...

  5. springboot1.5.9整合websocket实现实时显示的小demo

    最近由于项目需要实时显示数据库更新的数据变化情况,一开始想过在前端使用ajax异步轮询方法实现,但后面考虑到性能和流量等要求,就放弃该方法而选择使用websocket(毕竟现在springboot整合 ...

  6. 在python3下使用OpenCV 抓取摄像头图像并实时显示3色直方图

    以下代码为在Python3环境下利用OpenCV 抓取摄像头的实时图像, 通过OpenCV的 calHist函数计算直方图, 并显示在3个不同窗口中. import cv2 import numpy ...

  7. HSmartWindowControl 之 摄像头实时显示( 使用 WPF )

    1.添加Halcon控件,创建WPF项目 在VS2013中创建一个WPF工程,然后添加halcon的控件和工具包,参见: HSmartWindowControl之安装篇 (Visual Studio ...

  8. python实现websocket服务器,可以在web实时显示远程服务器日志

    一.开始的话 使用python简单的实现websocket服务器,可以在浏览器上实时显示远程服务器的日志信息. 之前做了一个web版的发布系统,但没实现在线看日志,每次发布版本后,都需要登录到服务器上 ...

  9. 使用vue 遇到的问题————— 解决手机实时显示项目

    Vue项目文件组织架构: src文件夹存放源代码. Static文件夹存放第三方静态资源.     git将项目上传github  http://blog.csdn.net/laozitianxia/ ...

  10. Python+OpenCV图像处理(一)——读取显示一张图片

    先在此处先声明,后面学习python+opencv图像处理时均参考这位博主的博文https://blog.csdn.net/u011321546/article/category/7495016/2? ...

随机推荐

  1. 使用C#发送邮件支持 Implicit SSL

    安装Package: Install-Package AIM 使用下面的代码发送: class Mail { private static string mailAddress = "{yo ...

  2. MySQL面试题——隔离级别相关面试题

    隔离级别相关面试题 MySQL事务隔离级别 未提交读--可以读到其他事务未提交的数据(最新的版本) 错误现象:脏读.不可重复读.幻读的现象 提交读(RC)--可以读到其他事务已提交的数据(最新已提交的 ...

  3. 【译】ASP.NET Core在 .NET Core 3.1 Preview 1中的更新

    .NET Core 3.1 Preview 1现在可用.此版本主要侧重于错误修复,但同时也包含一些新功能. 这是此版本的ASP.NET Core的新增功能: 对Razor components的部分类 ...

  4. 2023年了,复习了一下spring boot配置使用mongodb

    前言 MongoDB是一个基于分布式文件存储的开源数据库系统,使用C++语言编写.它是一个介于关系数据库和非关系数据库之间的产品,具有类似关系数据库的功能,但又有一些非关系数据库的特点.MongoDB ...

  5. oracle监听配置与防火墙问题

    在建好pdb容器后,需配置网络,才能从客户端连接服务器端 1.首先查看pdb容器的服务名 lsnrctl status ... Service "19cdb" has 1 inst ...

  6. 文心一言 VS 讯飞星火 VS chatgpt (105)-- 算法导论10.1 3题

    三.用go语言,仿照图 10-2,画图表示依次执行操作 ENQUEUE(Q,4).ENQUEUE(Q,1).ENQUEUE(Q,3).DEQUEUE(Q).ENQUEUE(Q,8)和 DEQUEUE( ...

  7. 入门篇-其之五-Java运算符(上)

    一元运算符之正负号 Java支持多种一元运算符,一元运算符中的"一元"是指一个操作数.我们初中学过的正负号就属于一元运算符,因为正负号后面只有一个数字. 正数使用+表示,其中+可以 ...

  8. Linux下的网络输入输出流量的带宽控制(2015-11-23更新)

    Linux下的网络输入输出流量的带宽控制 整理者:赤子玄心 QQ:280604597 Email:280604597@qq.com 大家有什么不明白的地方,或者想要详细了解的地方可以联系我,我会认真回 ...

  9. JDK 动态代理原理

    代理模式 客户端不直接访问目标对象,需要通过第三者来实现间接访问对象 代理对象在客户端和目标对象之间起中介作用,能够屏蔽目标对象不想让客户端知道的内容,或增加额外的服务 动态代理 JDK 动态代理:基 ...

  10. CSS3之创建3D场景

    1.属性介绍 perspective:800    平面距离三维中方框的距离 perspective-origin:50% 50%   表示从平面上哪个位置看三维图 ,相当于是X轴和Y轴,此时表示平面 ...