數字影象處理筆記(一):利用OpenCV的Cameo框架搭建實驗環境
阿新 • • 發佈:2018-12-15
1 - 引言
Python的應用程式可以通過面向物件的方法來實現,OpenCV提供了一個Cameo框架可以捕捉電腦的攝像頭。我們可以通過編寫新增框架裡的類和方法來對攝像頭捕捉到的畫面進行影象處理和實驗,是一個很好的學習方法,下面讓我們來搭建一下這個Cameo框架
2 - 使用managers.CaptureManager提取視訊流
無論影象來自視訊檔案還是攝像頭,OpenCV都可以獲取、顯示和記錄影象流,但是每種情況都有一些需要特殊考慮的地方。CaptureManager類對一些差異進行了抽象,並提供了更高階的介面從獲取流中分配影象,再將影象分到一個或多個輸出中(如影象檔案、視訊檔案或視窗)
建立managers.py檔案
# 使用managers.CaptureManager提取視訊流 import numpy import cv2 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 = 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): assert not self._enteredFrame, 'previous enterFrame() had no matching exitFram()' 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._writerVideoFrame() 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 _writerVideoFrame(self): if not self.isWritingVideo: return if self._videoWriter is None: fps = self._capture.get(cv2.CAP_PROP_FPS) if fps == 0.0: 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) # 使用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 processEvents(self): keycode = cv2.waitKey(1) if self.keypressCallback is not None and keycode != -1: keycode &= 0xFF self.keypressCallback(keycode)
3 - 使用manager.WindowManager抽象視窗和鍵盤
對於一個應用程式,我們還需要能夠實現人機互動,通過manager.WindowManager抽象視窗和鍵盤,我們可以通過鍵盤來實現人機互動
建立一個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.enterFrame self._captureManager.exitFrame() self._windowManager.processEvents() def onKeypress(self,keycode): if keycode == 32: # space self._captureManager.writeImage('cameo/screenshot.png') elif keycode == 9: # tab if not self._captureManager.isWritingVideo: self._captureManager.startWritingVideo('cameo/screenshot.avi') else: self._captureManager.stopWritingVideo() elif keycode == 27: # escape self._windowManager.destoryWindow() if __name__ == "__main__": Cameo().run()
3 - 實現效果
至此,我們已經搭建好了一個Cameo最原始的框架,可以捕捉攝像頭並且通過鍵盤實現截圖和錄製視訊,在之後的學習中,我們會慢慢的擴充這個框架來學習影象處理的各種演算法
按下空格鍵後儲存攝像頭捕捉到的圖片
按下ESC退出