OpenCV 3计算机视觉 python语言实现笔记(二)

#Cameo项目(人脸跟着和图像处理)


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

#使用managers.CaptureManager提取视频流

#创建一个名为manager.py的文件,首先实现CaptureManager类:
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._frameElapsed = long(0)
        self._fpsEstimate = None
    
    #将get()和set()方法变成属性
    @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
    

#实现enterFrame()和exitFrame()函数:

def enterFrame(self):
    #捕获下一帧,但是,要先检测之前的帧是否已经退出。
    assert not self._enteredFrame,'previous enterFrame() had no matching exitFrame()'
    
    if self._capture is not None:
        #捕获下一帧
        self._enteredFrame = self._capture.grab()
        
def exitFrame(self):    
    
    if self.frame is None:
        self._enteredFrame = False
        return
    
    #更新fps的估计值
    if self._frameElapsed == 0:
        self._startTime = time.time()
    else:
        timeElapsed = time.time() - self._startTime()
    self._fpsEstimate = self._frameElapsed / timeElapsed
    self._frameElapsed += 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
    
#注意,enterFrame()的实现只能(同步)获取一帧,而且会推迟从一个通道的获取,
#以便随后能从变量frame中读取。exitFrame()函数可以从当前通道获取图像、
#估计帧速率、通过窗口管理器显示图像。


def writeImage(self,filename):
    #将下一帧写入文件filename
    #用新的filename赋值给self._imageFilename即可
    self._imageFilename = filename
        
def startWritingVideo(self,filename,
                     encoding = cv2.VideoWriter_fourcc('I','4','2','0')):
    #同理给属性赋值即可
    self._videoFilename = filename
    self._videoEncoding = encoding
    
def stopWriterVideo(self):
    #将相关的属性设置为None即可
    self._videoFilename = None
    self._videoEncoding = None
    self._videoWriter = None

def _writeVideoFrame(self):
    if not self.isWritingVideo:
        return
    if self._videoWriter is None:
        #获取fps
        fps = self._capture.get(cv2.CAP_PROP_FPS)
        #如果获取fps失败
        if fps == 0.0:
            if self._frameElapsed < 20:
                #等待更多的帧流,以便估计的更加稳定
                return
            else:
                fps = self._fpsEstimate
        #设置size
        size = (int(self._capture.get(cv2.CAP_PROP_WIDTH)),
                int(self._capture.get(cv2.CAP_PROP_HEIGHT)))
        
        self._videoWriter = cv2.VideoWriter(self._videoFilename,
                                           self._videoEncoding,
                                           fps,size)
        self._videoWriter.weite(self._frame)
        

#使用managers.WindowManager抽象窗口和键盘

#OpenCV提供了创建和销毁窗口、显示图像和处理事件的函数,这些函数
#不是窗口类的方法,只需要窗口名作为参数。

#Windowmanager的实现代码:
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 createdWindow(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.Cameo的强大实现
#在managers.py所在的目录中,创建名为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.createdWindow()
        while self._windowManager.isWindowCreated:
            self._captureManager.enterFrame()
            frame = self._captureManager.frame
            self._captureManager.exitFrame()
            self._windowManager.processEvents()
    def onKeypress(self,keycode):
    """处理按键事件
       空格 -> 截图
       tab  -> 开始/停止录制
       esc  -> 退出
    """
        #空格
        if keycode == 32:
            self._captureManager.writeImage('screeshot.png')
        #tab
        elif keycode == 9:
            if not self._captureManager.isWritingVideo:
                self._captureManager.startWritingVideo('screencast.avi')
            else:
                self._captureManager.stopWriterVideo()
        #esc
        elif keycode == 27:
            self._windowManager.destroyWindow()

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

    
#以上代码的功能是,根据键盘的按键,实现对摄像头的图像进行截图显示,或者录制。
#除了显示镜像,没有对摄像头的图像进行其他处理。
#下面我们,会慢慢添加对图像的其他处理,如边缘检测。
        
        
        
        
        
        
        
        
        
        
        
        
        

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值