OpenCV 3 计算机视觉 Python语言实现 初步Cameo 项目
Cameo项目初步实现 此程序能显示摄像头帧、监听键盘输入以及记录截图或截屏。
本项目代码共有两个 .py 文件
- managers.py
- cameo.py
managers.py
首先是导入需要的包
import cv2
import numpy
import time
使用 managers.CaptureManager 提取视频流
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 = int(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, if any."""
# But first, check that any previous frame was exited
assert not self._enteredFrame, 'previous enterFame() 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.
# The getter may retrieve and cache the frame.
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._fpsEstimer = self._framesElapsed / timeElapsed
self._framesElapsed += 1
# Draw to the window, id 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 voide file, if any.
self._WriteVedioFrame()
# 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
def startWritingVideo(self, filename, encoding = cv2.VideoWriter_fourcc('I', '4', '2', '0') ):
""" Start writing exited farmes to a video file. """
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 _WriteVedioFrame(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 unknown so use an estimate
if self._framesElapsed < 20:
# Wait until more frames elapse so that the estimate is more stable.
return
else:
fps = self._fpsEstimater
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)
使用managers。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 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 processEvent(self):
keycode = cv2.waitKey(1)
if self.keypressCallback is not None and keycode != 1:
#Discard any non-ASCII info encoded by GTK
keycode &= 0xFF
self.keypressCallback(keycode)
cameo.Cameo()的强大实现
Cameo类提供两种方法启动应用程序: run0和onkeypress()。在初始化时,Camco类会把onkeypresso作为回调函数创建WindowManager类,而CaptureManager类会使用摄像头和WindowManager类。当调用run()函数时,应用程序会执行主循环处理帧和事件,应用程序会调用onkeypress()函数处理事件。按空格键可获取截图信息,按Tab键可启动1停止截屏(一个视频记录),按Esc键可退出应用程序。
cameo.py
import cv2
from Cameo_Project.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
# TODO: Filter the frame (Chapter 3).
self._captureManager.exitFrame()
self._windowManager.processEvent()
def onKeypress(self, keycode):
""" Handle a keypress
space -> Take a screenshot.
tab -> Start/stop recording a screencast.
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.destoryWindow()
if __name__=="__main__":
Cameo().run()
运行该程序,摄像头的图像会被镜像显示,而截图和截屏不会被镜像显示。
书中说是在初始化CaptureManager类时,将shouldMirrorPreview参数设置成了 “Ture”。
这段代码目前除了对帧做镜像处理之外不会有任何操作。在以后的更新中会跟着增加其他效果。