基于OpenCV3的计算机视频流录制,截图;Pycharm+Python实现

        学习到openCV部分的视频流提取,按照书上的教程逐步实现,最后发现书上面代码和结构都有编写问题。通过论坛上面看了别人的实现方式,最终实现了视频流的录制以及截图功能的实现。

先放两张图:

图1 截图功能实现

图2 录制的视屏文件,正常打开(清晰流畅,此处仅放个截图了)。

使用设备:普通杰瑞微通摄像头USB,接口cv2.VideoCapture(1),python3.7

论坛上的代码多少有些小问题,直接使用就输出不了图像,常见问题差不多都是调用的时候少个下划线,开头缩进不正确等。

本代码分为两部分第一部分为managers.py,第二部分为主函数cameo.py。

详细代码如下:

第一部分:managers.py

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 = float(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):
        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
        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) #获取fps
            if fps == 0.0:  #未获取到ps
                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(1),self._windowManager,True)

    def run(self):
        self._windowManager.createWindow()
        while self._windowManager.isWindowCreated:
            self._captureManager.enterFrame()
            frame = self._captureManager.frame
            if frame is not None:
                pass
            self._captureManager.exitFrame()
            self._windowManager.processEvents()
    def onKeypress(self,keycode):
        if keycode == 32:  #space键,截屏
            print("截图成功!")
            self._captureManager.writeImage('screenshot.png')
        elif keycode == 9:  #tab 判断开始录制还是结束
            if not self._captureManager.isWritingVideo:
                print("开始录制!")
                self._captureManager.startWritingVideo("screencast.avi")
            else:
                print("录制结束!")
                self._captureManager.stopWritingVideo()
        elif keycode == 27:    #ESc键退出
            print("退出!")
            self._windowManager.destroyWindow()

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值