基础类:CaptureManager
摄像头操作,获取图像,以及处理
import cv2
import numpy
import time
class CaptureManager (object):
def __init__(self, capture, previewWindowManager = None,shouldMirrorPreview = False):
self.previewWindowManager = previewWindowManager
self.shouldMirrorPreview = shouldMirrorPreview
self._capture = capture
self._channel = 0
self._enteredFrame = False
self._frame = None
self._imageFilename = None
self._videoFilename = None
self._videoEncoding = None
self._videoWriter = None
self._startTime = None
self._framesElapsed = 0
self._fpsEstimate = None
#定义属性访问器
@property
def channel(self):
return self._channel
@channel.setter
def channel(self, value):
if self._channel != value:
self._channel = value
self._frame = None
@property
def frame(self):
try:
# _enteredFrame 捕获到的视频帧
# 返回一个图片
if self._enteredFrame and self._frame is None:
# retrieve 是视频捕获对象的一个方法,用于检索捕获到的视频帧。
# self._frame 和 self._channel 是自定义的变量,可能用于存储检索到的帧和通道信息。
_, self._frame = self._capture.retrieve(self._frame, self._channel)
return self._frame
except Exception as e:
print("获取帧,发生异常"+e)
@property
def isWritingImage(self):
return self._imageFilename is not None
@property
def isWritingVideo(self):
return self._videoFilename is not None
def enterFrame(self):
#assert 是一个用于调试和测试的语句。它用于检查一个条件是否为真,如果条件为假,就会抛出一个 AssertionError 异常。
#_enteredFrame =false 会进入条件
assert not self._enteredFrame, print("Frame already entered")
if self._capture is not None:
#grab() 方法通常用于获取下一帧的视频数据
self._enteredFrame = self._capture.grab()
# exitFrame的实现从当前通道获取图像,估计帧率,通过窗口管理器(如果有的话)显示图像,并完成将图像写入文件的所有挂起请求。
def exitFrame(self):
if self._frame is None:
self._enteredFrame = False
return
if self._framesElapsed == 0:
self._startTime = time.time()
else:
timeElapsed = time.time() - self._startTime
self._fpsEstimate=self._framesElapsed/timeElapsed
self._framesElapsed += 1
if self.previewWindowManager is not None:
if self.shouldMirrorPreview:
mirroredFrame = numpy.fliplr(self._frame)
self.previewWindowManager.show(mirroredFrame)
else:
self.previewWindowManager.show(self._frame)
if self.isWritingImage:
cv2.imwrite(self._imageFilename, self._frame)
self._imageFilename = None
self._frame=None
self._enteredFrame =None
# 公共方法
# 写图片写入视频,停止写入
def writeImage(self, filename):
self._imageFilename = filename
def startWritingVideo(self,filename,encoding=cv2.VideoWriter.fourcc('M','J','P','G')):
self._videoFilename = filename
self._videoWriter = encoding
def stopWritingVideo(self):
self._videoWriter= None
self._videoEncoding= None
self._videoFilename= None
def _writeVideoFrame(self):
if not self.isWritingVideo:
return False
if self._videoWriter is not None:
fps = self._capture.get(cv2.CAP_PROP_FPS)
#获取不到FPS 使用推理
if fps <= 0.0 :
# 在帧率未知的情况下,我们在捕获会话开始时,跳过一些帧,这样就有时间构建帧率的估计。
if self._framesElapsed < 20:
return
else:
fps = self._fpsEstimate
#fps = 30
size= (int (self._capture.get(cv2.CAP_PROP_FRAME_WIDTH)),int (self._capture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
self._videoWriter= cv2.VideoWriter(self._videoFilename, self._videoEncoding, fps, size)
#写入视频
self._videoWriter.write(self._frame)
基础类:WindowsManager
对窗口的操作,打开 显示 销毁等
import cv2
# 对窗口的所有操作 打开 显示 销毁 绑定事件
class WindowsManager(object):
def __init__(self,windowsName,keypressCallbak=None):
self.keypressCallbak = keypressCallbak
self._windowsName = windowsName
self._isWindowsCreated=False
@property
def isWindowsCreated(self):
return self._isWindowsCreated
@property
def createWindow(self):
cv2.namedWindow(self._windowsName)
self._isWindowsCreated= True
def show(self,frame):
cv2.imshow(self._windowsName,frame)
def destoryWindows(self):
cv2.destroyWindow(self._windowsName)
self._isWindowsCreated=False
def processEvents(self):
keycode=cv2.waitKey(1)
if self.keypressCallbak is not None and keycode != -1:
self.keypressCallbak(keycode)
Main
from CaptureManager import *
from WindowsManager import *
import cv2
class cameo:
def __init__(self):
self._windowManager = WindowsManager("Capture", self.onKeypress)
self._captureManager = CaptureManager(cv2.VideoCapture(0),self._windowManager,True)
def run(self):
self._windowManager.createWindow
#设置窗口属性
while self._windowManager.isWindowsCreated:
#enterFrame的实现只(同步地)抓取一帧
self._captureManager.enterFrame()
#处理并返回帧
frame = self._captureManager.frame
if frame is not None:
pass
#exitFrame的实现从当前通道获取图像,估计帧率,通过窗口管理器(如果有的话)显示图像,并完成将图像写入文件的所有挂起请求。
self._captureManager.exitFrame()
#接收用户输入并且触发事件
self._windowManager.processEvents()
# 键盘事件
# 控制 CaptureManager 写入图片,写入视频等
# 控制 WindowsManager 关闭窗口
def onKeypress(self,keycode):
if keycode == 32: #空格
self._captureManager.writeImage('Sce.png')
elif keycode ==9: #Tab
if not self._captureManager.isWritingVideo:
self._captureManager.startWritingVideo('Sce.avi')
elif keycode == 27: #ESC
self._windowManager.destoryWindows()
else: #停止视频录制
self._captureManager.stopWritingVideo()
if __name__== "__main__":
cameo().run()