Python-OpenCV学习笔记(五)

使用managers.CaptureManager提取视频流
CaptureManager类能对异性差异进行抽象,并提供了更加高级的接口从获取流中分配图像,再将图像分配到一个或多个输出中(如图像文件、视频文件或窗口)。
在VideoCapture类中初始化CaptureManager类,在应用程序主循环的每一次迭代中通常应调用CaptureManager中的enterFrame()和exitFrame()函数。在调用enterFrame()和exitFrame()函数之间,应用程序可能会设定通道属性并获取帧属性。通道属性的初始值为0.只有在多台摄像头的情况下,通道属性的初始值非0,。帧属性是调用enterFrame()函数时与当前通道状态对应的图像。
可能会经常调用CapTureManager类的writeImage(),startWritingVideo()和stopWritingVideo()函数。在调用exitFrame()函数之前,会有延迟写入文件。并且,在调用existFrame()函数过程中,帧属性可能会在窗口中显示,这取决于应用程序代码是将WindowManager类作为CaptureManager的构造函数参数还是设置previewWindowManager属性。
如果应用程序代码处理了帧属性,那么在记录文件和窗口中会有所体现。CaptureManager类有一个称为shouldMirrorPreview的构造函数参数和属性,如果想要帧在窗口中镜像,但不记录在文件中,可将shouldMirrorPreciew设置为True。
Opencv不能为摄像头提供准确的帧速率。解决这个问题的方法是通过帧计数器和Python标准的time.time()函数来估计帧数率。
创建一个名为managers.py,该文件包含了CaptureM的实现,这各实现结果很长分成几段,先导入包、构造函数和属性:

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=numpy.long(0)
        self._fpsEstimate=None

    def channel(self):
        return self._channel

    def frame(self):
        if self._enteredFrame and self._frame is None:
            _,self._frame=self._capture.retyieve()
            return self._frame

    def isWritingImage(self):
        return self._imageFilename is not None

    def isWritingVideo(self):
        return self._videoFilename is not None
    

大多数成员变量为非公有变量,这类变量名前会加一个下划线进行标识。这些非公有变量与当前帧的状态以及文件写入操作有关。
Python没有石油成员变量的概念,通常在变量前面加单/双下划线来表示私有变量。通常在Python中,以单下划线开始的成员变量称为保护变量,而异双下划线开始的变量称为私有成员变量。

 def enterFrame(self):
        assert  not self._enteredFrame
        if self._capture is not None:
            self._enteredFrame=self._capture.grab()

    def exitFrame(self):
        if self.frame is None:
            self._enteredFrame=False
            return
        if self._enteredFrame==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).copy()
                self.previewWindowManager.show(mirroredFrame)
            else:
                self.previewWindowManager.show(self._frame)
        if self.isWritingImage:
            cv2.imwrite(self._imageFilename,self._frame)
            self._imageFilename=None

        self._videoWriter()

        self._frame=None
        self._enteredFrame=False

enterFrame()的实现只能(同步)获取一帧,而且会推出从一个通道获取,以便随后能从变量frame中读取。exitFrame()函数可以从当前通道获取图像、估计帧速率、通过窗口管理器显示图像,执行暂停的请求,从而向文件中写入图像。

 def writeImage(self,fileneme):
        self._imageFilename=fileneme

    def startWritingVideo(self,filename,encoding=cv2.VideoWriter_fourcc('I','4','2','0')):
        self._videoFilename=filename
        self._videoEncoding=encoding

    def stopWritingVideo(self):
        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:
                if self._framesElapsed<20:
                    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)
     

writeImage(),startWritingVideo()和stopWritingVideo()是公有函数,简单地记录了文件的写入操作参数,实际写入会推迟到下一下exitFrame()函数。
Python-OpenCV学习笔记(五)

上一篇:【入门指南】使用阿里云Elasticsearch搭建ELK日志系统


下一篇:Java魔法堂:JUnit4使用详解