OpenCV3-Python摄像头实时图像
admin 于 2018年04月13日 发表在 计算机视觉

Cameo项目,使每一步都设计成该应用的一个组件(component),以使应用具有扩展性和重用性。项目实现视频播放、内容截图、关闭调用等功能。

1. 设计方法

创建CaptureManager类和WindowManager类作为高级的I/O流接口。在应用程序代码中可以使用CaptureManager来读取新的帧,并能将帧分配到一个或多个输出中,这些输出包括静止的图像文件、视频文件以及窗口(可通过WindowManager类来实现),WindowManager类使应用程序代码能以面向对象的形式处理窗口和事件。

备注:

Python没有私有成员变量的概念,通常在变量前面添加单/双下划线(_)来表示私有变量。通常在Python中,以单下划线开始的成员变量称为保护变量(即只有类对象和子类对象能访问这些变量),而以双下划线开始的变量称为私有成员变量(即只有类对象自己能访问,子类对象不能访问这个变量)

2. 实现源码

(1) managers.py内容:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Apr  1 10:18:20 2018

@author: lu
"""

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
        
    @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):
        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):
        
        """ capture the next frame """
        assert not self._enteredFrame,'previous enterFrame() had no matching exitFrame()'
        
        if self._capture is not None:
            self._enteredFrame = self._capture.grab()
            
    def exitFrame(self):

        """ Draw to the window. Write to files. Release the frame"""
        #check whether any grabbed frame is retrievable
        if self.frame is None:
            self._enteredFrame = False
            return
    
        #update the FPS estimate and related variables
        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
        if self.isWritingImage:
            cv2.imwrite(self._imageFilename,self._frame)
            self._imageFilename = None
        
        #write to the video file, if any
        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

    """stop writing exited frame to a video file"""        
    def startWritingVideo(self, filename, 
                          encoding = cv2.VideoWriter_fourcc('I','4','2','0')):
        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 unknow so use an estimate
                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)
        
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 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:
            keycode &= 0xFF
            self.keypressCallback(keycode)

(2) main.py内容

import numpy as np
import cv2
from managers import WindowManager, CaptureManager

class Cameo(object):
    
    def __init__(self):
        self._windowManager = WindowManager('Camo', self.onKeypress)
        self._captureManager = CaptureManager(cv2.VideoCapture(0), self._windowManager, True)
    
    def run(self):
        self._windowManager.createWindow()
        while self._windowManager.isWindowCreated:
            self._captureManager.enterFrame()
            frame = self._captureManager.frame
            self._captureManager.exitFrame()
            self._windowManager.processEvents()
            
    def onKeypress(self, keycode):
        
        """
        space  ->  Take a screenshot
        tab    ->  start/stop recording a creencast
        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()

3. 实现效果图:

下一篇:《OpenCV3-Python滤波器详细介绍》

注意:本站所有文章除特别说明外,均为原创,转载请务必以超链接方式并注明作者出处。 标签:opencv3,cameo