opencv:cameo项目

Managers.py

'''
通常在python中,以单下划线开始的成员变量称为保护变量(即只有类对象和子类对象才能访问这些变量)
而以双下划线开始的变量称为私有成员变量(即只有类对象自己能访问,子类对象不能访问这个变量)
'''
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:
            ret,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,"先前的enterframe函数没有匹配的exitframe函数"
        if self._capture is not None:
            self._enteredFrame=self._capture.grab()
    def exitFrame(self):
        '''写入窗口,写入文件,释放帧'''
        #检查是否任何grabbed的帧已经被retrievalable
        #the getter may retrieve and cache the frame
        if self.frame is  None:
            self._enteredFrame=False
            return
        #更新帧率(fps)估值和相关变量
        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).copy()
                self.previewWindowManager.show(mirroredFrame)
            else:
                self.previewWindowManager.show(self._frame)
        #如果有,写入图片文件
        if self.isWritingImage:
            cv2.imwrite(self._imageFilename,self._frame)
            self._imageFilename=None
        #如果有的话,写入视频文件‘
        self._writeVideoFrame()

        #释放帧
        self._frame=None
        self._enteredFrame=False

    def writeImage(self,filename):
        '''写入下一个退出的帧到图片文件'''
        self._imageFilename=filename

    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:
                #捕捉的帧率(fps)是未知的,所以使用了估计
                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)

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):
        '''运行主循环'''
        self._windowManager.createWindow()
        while self._windowManager.isWindowCreated:
            self._captureManager.enterFrame()
            frame=self._captureManager.frame
            #Todo 滤波该帧
            self._captureManager.exitFrame()
            self._windowManager.processEvents()

    def onKeypress(self,keycode):
        '''获取键盘动作
        其中space空格键->截图
           tab换行键->开启或停止录屏(screencast)
           esc->退出'''
        if keycode==32: #空格键
            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:#esc键
            self._windowManager.destroyWindow()
if __name__=='__main__':
    cameo().run()

filters.py

import cv2
import numpy
import utils

def strokeEdge(src,dst,blurKsize=7,edgeKsize=5):
    '''blurKsize参数会作为medianBlur()函数的ksize函数
       edgeKsize参数会作为Laplacian()函数的ksize函数'''
    if blurKsize>=3:
        blurredSrc=cv2.medianBlur(src,blurKsize)#模糊函数
        graySrc=cv2.cvtColor(blurredSrc,cv2.COLOR_BGR2GRAY)
    else:
        graySrc=cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

    cv2.Laplacian(graySrc,cv2.CV_8U,graySrc,ksize=edgeKsize)
    normalizedInverseAlpha=(1.0/255)*(255-graySrc)
    channels=cv2.split(src)
    for channel in channels:
        channel[:]=channel*normalizedInverseAlpha
    cv2.merge(channels,dst)

class VconvolutionFilter(object):
    '''一个滤波效果,运用卷积到V(或者是所有的BGR)'''
    def __init__(self,kernel):
        self._kernel=kernel
    def apply(self,src,dst):
        '''运用该滤波使用bgr或者灰度图像'''
        cv2.filter2D(src,-1,self._kernel,dst)

class SharpenFilter(VconvolutionFilter):
    '''一像素半径的锐化滤波'''
    def __init__(self):
        kernel=numpy.array([[-1,-1,-1],
                            [-1,9,-1],
                            [-1,-1,-1]])     #权重加起来为1
        VconvolutionFilter.__init__(self,kernel)

class FindEdgesFilter(VconvolutionFilter):
    '''一像素半径的 边缘寻找滤波'''
    def __init__(self):
        kernel=numpy.array([[-1,-1,-1],
                            [-1,8,-1],
                            [-1,-1,-1]])     #权重加起来为0

你可能感兴趣的:(opencv)