美文网首页
OpenCV+Python简易视频处理框架

OpenCV+Python简易视频处理框架

作者: 音符纸飞机 | 来源:发表于2018-07-07 15:48 被阅读39次

    参考《Learning OpenCV 3 Computer Vision with Python second Edition》Chapter 2

    目录结构
    # -*-coding:utf-8-*-
    # managers.py
    
    import cv2
    import numpy as np
    import time
    
    
    class CaptureManager(object):
        def __init__(self, capture, preview_window_manager=None, should_mirror_preview=False):
            self.preview_window_manager = preview_window_manager
            self.should_mirror_preview = should_mirror_preview
    
            self._capture = capture
            # 给多头摄像机使用
            self._channel = 0
            # 标识是否已经grab()
            self._entered_frame = False
            self._frame = None
            self._image_file_name = None
            self._video_file_name = None
            self._video_encoding = None
            self._video_writer = None
            # 用于计算帧率
            self._start_time = None
            # 已处理过的frame个数
            self._frames_elapsed = 0
            # 估算的帧率,保存视频且无法获取当前帧率时使用
            self._fps_estimate = 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._entered_frame and self._frame is None:
                _, self._frame = self._capture.retrieve()
            return self._frame
    
        @frame.setter
        def frame(self, processed_frame):
            if processed_frame is not None:
                self._frame = processed_frame
    
        @property
        def is_writing_image(self):
            return self._image_file_name is not None
    
        @property
        def is_writing_video(self):
            return self._video_file_name is not None
    
        # 调用capture.grab()
        def enter_frame(self):
            assert not self._entered_frame, "上一个enter_frame()没有与之对应的exit_frame()"
            if self._capture is not None:
                self._entered_frame = self._capture.grab()
    
        # 真正保存帧的地方
        def exit_frame(self):
            if self.frame is None:
                self._entered_frame = False
                return
            # 如果是第一帧,记录开始时间
            if self._frames_elapsed == 0:
                self._start_time = time.time()
            # 否则计算帧率
            else:
                time_elapsed = time.time() - self._start_time
                self._fps_estimate = self._frames_elapsed / time_elapsed
            self._frames_elapsed += 1
    
            # 如果windowManager不为空,则显示帧
            if self.preview_window_manager is not None:
                if self.should_mirror_preview:
                    mirrored_frame = np.fliplr(self._frame).copy()
                    self.preview_window_manager.show(mirrored_frame)
                else:
                    self.preview_window_manager.show(self._frame)
    
            if self.is_writing_image:
                cv2.imwrite(self._image_file_name, self._frame)
                self._image_file_name = None
    
            self._write_video_frame()
    
            self._frame = None
            self._entered_frame = False
    
        # 记录保存图像的文件名
        def write_image(self, filename):
            self._image_file_name = filename
    
        # 记录保存视频的文件名和编码信息
        def start_writing_video(self, filename, encoding=cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')):
            self._video_file_name = filename
            self._video_encoding = encoding
    
        # 清除保存视频的信息
        def stop_writing_video(self):
            self._video_file_name = None
            self._video_encoding = None
            self._video_writer = None
    
        # 写视频帧的地方
        def _write_video_frame(self):
            if not self.is_writing_video:
                return
            if self._video_writer is None:
                fps = self._capture.get(cv2.CAP_PROP_FPS)
                if fps == 0.0:
                    if self._frames_elapsed < 20:
                        return
                    else:
                        fps = self._fps_estimate
                size = (int(self._capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(self._capture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
                self._video_writer = cv2.VideoWriter(self._video_file_name, self._video_encoding, fps, size)
            self._video_writer.write(self._frame)
    
    
    class WindowManager(object):
        def __init__(self, window_name, keypress_callback=None):
            self.keypress_callback = keypress_callback
            self._window_name = window_name
            self._is_window_created = False
    
        @property
        def is_window_created(self):
            return self._is_window_created
    
        def create_window(self):
            cv2.namedWindow(self._window_name)
            self._is_window_created = True
    
        def show(self, frame):
            cv2.imshow(self._window_name, frame)
    
        def destroy_window(self):
            cv2.destroyWindow(self._window_name)
            self._is_window_created = False
    
        def process_events(self):
            keycode = cv2.waitKey(1)
            if self.keypress_callback is not None and keycode != -1:
                keycode &= 0xFF
                self.keypress_callback(keycode)
    
    # -*-coding:utf-8-*-
    # scratch.py
    import cv2
    
    from cvgui.managers import WindowManager, CaptureManager
    
    
    class Scratch(object):
        def __init__(self, video):
            self._window_manager = WindowManager('Scratch', self.on_keypress)
            self._capture_manager = CaptureManager(cv2.VideoCapture(video), self._window_manager, True)
    
        def run(self):
            self._window_manager.create_window()
            while self._window_manager.is_window_created:
                self._capture_manager.enter_frame()
                frame = self._capture_manager.frame
                if frame is not None:
                    processed_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                    # TODO 对frame进行其他处理
                    self._capture_manager.frame = processed_frame
                self._capture_manager.exit_frame()
                self._window_manager.process_events()
    
        def on_keypress(self, keycode):
            """
            space -> 截屏
            tab -> 开始/结束录屏
            escape -> 退出
            """
            if keycode == 32:  # space
                self._capture_manager.write_image('screenshot.png')
            elif keycode == 9:  # tab
                if not self._capture_manager.is_writing_video:
                    self._capture_manager.start_writing_video('screencast.avi')
                else:
                    self._capture_manager.stop_writing_video()
            elif keycode == 27:  # esc
                self._window_manager.destroy_window()
    
    
    if __name__ == "__main__":
        Scratch("street.mp4").run()
    
    
    效果

    相关文章

      网友评论

          本文标题:OpenCV+Python简易视频处理框架

          本文链接:https://www.haomeiwen.com/subject/xpgwuftx.html