博客
关于我
opencv面向对象设计初探
阅读量:791 次
发布时间:2023-02-23

本文共 5430 字,大约阅读时间需要 18 分钟。

学习OpenCV一直是基于过程编程的方式,这种方法虽然直观,但容易让人感到繁琐。随着技术的发展,OpenCV逐渐引入面向对象的编程方式,这种方法提供了更加系统化和规范化的开发流程。

面向对象编程的优势显著体现在代码的可维护性和扩展性上。通过定义类和属性,我们可以更直观地管理摄像头资源和视频流处理,这种方式降低了代码的耦合度,使得程序更易于理解和改进。

下面以一个启动外部摄像头并处理视频流的例子来说明面向对象编程的优势。这个例子主要包括两个核心部分:视频流管理器和窗口管理器。

视频流管理器负责从摄像头中获取图像数据,并提供图像处理功能。窗口管理器则负责显示实时图像和处理用户输入事件。

以下是视频流管理器的实现代码:

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 = 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._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)

窗口管理器负责处理窗口事件和显示图像:

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)

基于上述基础类,我们可以定义一个简单的摄像头控制类:

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.frame            self._captureManager.exitFrame()            self._windowManager.processEvents()    def onKeypress(self, keycode):        if keycode == 32:  # 空格键            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()

通过上述代码示例可以看出,面向对象编程使得代码结构更加清晰,便于扩展和维护。通过定义CaptureManager和WindowManager类,我们可以更直观地管理摄像头资源和窗口显示,同时通过键盘事件处理实现了截图和录像功能。

这种编程方式不仅提高了代码的可读性,还为后续功能的开发提供了更好的基础。

转载地址:http://swpfk.baihongyu.com/

你可能感兴趣的文章
OpenCV与AI深度学习 | 实战 | 基于YOLOv9+SAM实现动态目标检测和分割(步骤 + 代码)
查看>>
OpenCV与AI深度学习 | 实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)
查看>>
OpenCV与AI深度学习 | 实战 | 文本图片去水印--同时保持文本原始色彩(附源码)
查看>>
OpenCV与AI深度学习 | 实战 | 通过微调SegFormer改进车道检测效果(数据集 + 源码)
查看>>
OpenCV与AI深度学习 | 实战—使用YOLOv8图像分割实现路面坑洞检测(步骤 + 代码)
查看>>
OpenCV与AI深度学习 | 实战篇——基于YOLOv8和OpenCV实现车速检测(详细步骤 + 代码)
查看>>
OpenCV与AI深度学习 | 实战|OpenCV实时弯道检测(详细步骤+源码)
查看>>
OpenCV与AI深度学习 | 实用技巧 | 使用OpenCV进行模糊检测
查看>>
OpenCV与AI深度学习 | 实践教程|旋转目标检测模型-TensorRT 部署(C++)
查看>>
OpenCV与AI深度学习 | 工业缺陷检测中数据标注需要注意的几个事项
查看>>
OpenCV与AI深度学习 | 干货 | 深度学习模型训练和部署的基本步骤
查看>>
OpenCV与AI深度学习 | 手把手教你用Python和OpenCV搭建一个半自动标注工具(详细步骤 + 源码)
查看>>
OpenCV与AI深度学习 | 水下检测+扩散模型:或成明年CVPR最大惊喜!
查看>>
OpenCV与AI深度学习 | 深入浅出了解OCR识别票据原理
查看>>
OpenCV与AI深度学习 | 深度学习检测小目标常用方法
查看>>
OpenCV与AI深度学习 | 超越YOLOv10/11、RT-DETRv2/3!中科大D-FINE重新定义边界框回归任务
查看>>
OpenCV与AI深度学习 | 高效开源的OCR工具:Surya-OCR介绍与使用
查看>>
OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)
查看>>
Opencv中KNN背景分割器
查看>>
OpenCV中基于已知相机方向的透视变形
查看>>