openCV调起电脑摄像头提取视频流和截图

managers.py文件完成提取视频流和键盘操作等:

import cv2
import numpy as np
import time

'''
本类用于提取视频流。
CaptureManager类用于读取新的帧,并能将帧分派到一个或者多个输出中,这些输出包括静止的图像文件、视频文件以及窗口。
'''
class CaptureManager(object):

    def __init__(self,
                 capture,
                 previewWindowmanager = None,
                 shouldMirroPreview = False):
        self.previewWindowManager = previewWindowmanager
        self.shouldMirroPreview = shouldMirroPreview

        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是一个装饰器(decorator),装饰器可以给函数动态加上功能。
    Python内置的@property装饰器就是负责把一个方法变成属性调用的,使用后会对函数的参数进行检查。'''

    @property  #定义内联函数
    def channel(self):
        return self._channel

    @property
    def channel(self, value):
        if self._channel != value:
            self._channel = value
            self._frame = None

    @property
    def frame(self):
        if self._enteredFrame  and self._frame is None:
            _, 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

    #捕获下一帧
    def enterFrame(self):  #检查先前帧是否退出
        assert  not self._enteredFrame, 'previous enterFrame()had no matching exitFrame()'

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

     #Draw to window,write to file,release the frame
    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

        '''Draw to window'''
        if self.previewWindowManager is not None:
            if self.shouldMirroPreview:
                mirroedFrame = np.fliplr(self._frame).copy()
                self.previewWindowManager.show(mirroedFrame)
            else:
                self.previewWindowManager.show(self._frame)

        '''write to image file'''
        if self.isWritingImage:
            cv2.imwrite(self._imageFileName, self._frame)
            self._imageFileName = None

        '''write to video'''
        if self.isWritingVideo:
            self._writeVideoFrame()
        #Release the frame
        self._frame = None
        self._enteredFrame = False

    def writeImage(self, filename):
        self._imageFileName = filename #将下一个已存在的帧写入image文件

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

    def stopWriteVideo(self):
        self._videoFileName = None
        self._videoEncoding = None
        self._videoWriter = None

    '''_writeVideoFrame()函数可以创建或者向视频追加内容'''
    def _writeVideoFrame(self):
        if not  self.isWritingVideo:
            return

        if self._videoWriter is None:
            fps = self._capture.get(cv2.CAP_PROP_FPS)
            #捕获的FPS未知因而需要预估(FPS:frames per second,帧速率)
            if fps == 0.0:
                if self._fpsEstimate < 20: #过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)

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):
        cv2.namedWindow(self._windowName)
        self._isWindowCreated = True

    def show(self, frame):
        cv2.imshow(self._windowName, frame)

    def destoryWindow(self):
        cv2.destroyWindow(self._windowName)
        self._isWindowCreated = False

    def processEvents(self):
        keycode = cv2.waitKey(1)
        if self.keypressCallback is not None and keycode != -1:
            keycode &= 0xff
            self.keypressCallback(keycode)

cameo.py主函数调用,进行相关的操作:

import cv2
from managers import windowManager, CaptureManager
class Cameo(object):
    def __init__(self):
        self._windowManager = windowManager("Cameo", self.onKeyPress)
        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 = self._captureManager.frame

            self._captureManager.exitFrame()
            self._windowManager.processEvents()

    def onKeyPress(self, keycode):
        #处理键盘输入
        if keycode == 32: #space
            self._captureManager.writeImage('screenshot.png')
        elif keycode == 9: #tab
            if not self._captureManager.isWritingVideo:
                self._captureManager.startWriteVideo('screencast.avi')
            else:
                self._captureManager.stopWriteVideo()
        elif keycode == 27: #escape
           self._windowManager.destoryWindow()

if __name__ == '__main__':
    Cameo().run()

完成之后按下Tab键可以录制视频(貌似还有点小问题);

space键可以截图;

Esc键可以退出。

window窗口的图像会被镜像,但是录制的视频和截图不会镜像。

你可能感兴趣的:(openCV)