> 文档中心 > 第2章 处理文件、摄像头和图形用户界面cameo应用

第2章 处理文件、摄像头和图形用户界面cameo应用


managers02.py

"""*_* coding: UTF-8 *_*@author: xiaohao@time: 2022/6/25 0:06@Site: Qinhuangdao, China@file:managers02.py@software: PyCharm@CSDN: So come on"""import cv2import numpyimport timeclass 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 = int(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): ''' 判断一下是否抓取图片成功, 如果成功的话,把成功的图片的数据导入到_frame这个变量中, 使用的方法是retrieve()。 :return: ''' if self._enteredFrame and self._frame is None:     # As of OpenCV 3.0, VideoCapture.retrieve() no longer supports the channel argument.     # _, self._frame = self._capture.retrieve(channel = self.channel)     _, self._frame = self._capture.retrieve() return self._frame    @property    def isWritingImage(self): return self._imageFilename is not None    @property    def isWritingVideo(self): return self._videoFilename is not None    # 如果_capture不为空的话,抓取摄像头中的一帧。    # _capture指的是CaptureManager类实例_captureManager打开的摄像头capture。    def enterFrame(self): """Capture the next frame, if any.""" # But first, check that any previous frame was exited. # assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假 assert not self._enteredFrame, \     'previous enterFrame() had no matching exitFrame()' if self._capture is not None:     self._enteredFrame = self._capture.grab()    # 计算摄像头每秒钟的帧数,并且把摄像头捕获的帧放入窗口cameo中显示。    def exitFrame(self): """Draw to the window. Write to files. Release the frame.""" # Check whether any grabbed frame is retrievable. # The getter may retrieve and cache the frame. if self.frame is None:     self._enteredFrame = False     return # Update the FPS estimate and related variables. # 计算FPS(每秒帧数),而且估算是实时更新的。这个时间记录到_fpsEstimate里。 if self._framesElapsed == 0:     self._startTime = time.time() else:     timeElapsed = time.time() - self._startTime     self._fpsEstimate = self._framesElapsed / timeElapsed self._framesElapsed += 1 # Draw to the window, if any. # 把捕获的帧的图像显示到屏幕窗口上面,如果选择镜像的话,首先翻转图片,然后再显示到窗口上。 # 每一次循环都更新一下窗口,这样我们就相当于一帧帧地放图片,速度会很快,快的话就达到了视频的效果。 if self.previewWindowManager is not None:     if self.shouldMirrorPreview:  mirroredFrame = numpy.fliplr(self._frame).copy()  self.previewWindowManager.show(mirroredFrame)     else:  self.previewWindowManager.show(self._frame) # Write to the image file, if any. # 判断是否按下了空格键,就把按下时候刚好_enterFrame捕获的那一帧数据保存到硬盘中。 # 如果没有截图,就跳过。 if self.isWritingImage:     cv2.imwrite(self._imageFilename, self._frame)     self._imageFilename = None # Write to the video file, if any. # 判断是否按下了TAB,就把按下时候刚好_enterFrame捕获的那一帧数据保存到硬盘中, # 然后每一次循环都把_enterFrame保存起来,直到又按下TAB键,就不再保存了。 # 这样好多帧的图片会放到一个为avi格式的文件当中,说白了就是一个视频。 self._writeVideoFrame() # Release the frame. self._frame = None self._enteredFrame = False    def writeImage(self, filename): """Write the next exited frame to an image file.""" self._imageFilename = filename    def startWritingVideo(     self, filename,     encoding=cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')): """Start writing exited frames to a video file.""" self._videoFilename = filename self._videoEncoding = encoding    def stopWritingVideo(self): """Stop writing exited frames to a video file.""" self._videoFilename = None self._videoEncoding = None self._videoWriter = None    def _writeVideoFrame(self): if not self.isWritingVideo:     return if self._videoWriter is None:     fps = self._capture.get(cv2.CAP_PROP_FPS)     if fps <= 0.0:  # The capture's FPS is unknown so use an estimate.  if self._framesElapsed < 20:      # Wait until more frames elapse so that the      # estimate is more stable.      return  else:      fps = self._fpsEstimate     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)class WindowManager(object):    def __init__(self, windowName, keypressCallback=None): self.keypressCallback = keypressCallback self._windowName = windowName self._isWindowCreated = False    @property    def isWindowCreated(self): return self._isWindowCreated    # 先判断一下是否窗口创建完毕。    def createWindow(self): # 把_windowName中传入的名称,就是cameo写入, # 然后把_isWindowCreated属性改为True。 cv2.namedWindow(self._windowName) self._isWindowCreated = True    def show(self, frame): cv2.imshow(self._windowName, frame)    def destroyWindow(self): cv2.destroyWindow(self._windowName) self._isWindowCreated = False    # 监控键盘,看看它按下之前说的那些按键没有,    # 如果按下的话,就执行相应的操作。    def processEvents(self): keycode = cv2.waitKey(1) if self.keypressCallback is not None and keycode != -1:     # Discard any non-ASCII info encoded by GTK.     keycode &= 0xFF     self.keypressCallback(keycode)

cameo02.py

"""*_* coding: UTF-8 *_*@author: xiaohao@time: 2022/6/25 1:06@Site: Qinhuangdao, China@file:cameo02.py@software: PyCharm@CSDN: So come on"""import cv2from managers02 import WindowManager, CaptureManagerclass Cameo(object):    def __init__(self): # 创建一个WindowManager的实例,窗口名字叫Cameo, # 接受键盘按键(也就是录像或截图)的监控的函数叫做onKeypress self._windowManager = WindowManager('Cameo',  self.onKeypress) # 创建一个CaptureManager的实例。 # 第一参数是获取摄像头,只有一个摄像头括号为0,如果多个,输入第几个摄像头的标号数字。 # 第二参数是把WindowsManager实例_windowManager传给CaptureManager的实例_captureManager。 # 第三参数是是否镜像,True就是镜像,因为我们照镜子,镜子里面的人是相反的,所以应该水平翻转,给它变正。 self._captureManager = CaptureManager(     cv2.VideoCapture(0), self._windowManager, True)    def run(self): """Run the main loop.""" # 如果没建立好窗口的话,直接就退出程序运行 self._windowManager.createWindow() # 每一次循环都更新窗口,就相当于一帧帧地放图片,速度很快,快的话就达到视频效果。 while self._windowManager.isWindowCreated:     # 抓取     self._captureManager.enterFrame()     # 把上面捕获的帧的图像传入到变量frame中。     frame = self._captureManager.frame     if frame is not None:  # TODO: Filter the frame (Chapter 3).  pass     self._captureManager.exitFrame()     self._windowManager.processEvents()    # 监控键盘在循环语句的最后一句,当执行这句话的时候,    # 要是键盘按下键或者没有按下键,都会产生一个数据,    # 没按下是 - 1,按下了就是一个ASCII码,然后把这个码转换为GTK格式,    # 然后传入keypressCallback中,也就是传入Windowsmanager类中的函数    def onKeypress(self, keycode): """Handle a keypress. space  -> Take a screenshot. tab    -> Start/stop recording a screencast. escape -> Quit. """ if keycode == 32:  # space     self._captureManager.writeImage('screenshot.png') elif keycode == 9:  # tab     if not self._captureManager.isWritingVideo:  self._captureManager.startWritingVideo(      'screencast.avi')     else:  self._captureManager.stopWritingVideo() elif keycode == 27:  # escape     self._windowManager.destroyWindow()if __name__ == "__main__":    # 首先初始化Cameo这个类,然后执行run方法。    Cameo().run()

第2章 处理文件、摄像头和图形用户界面cameo应用