1 Star 0 Fork 6

欣欣然阿/opencv

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
_2managers.py 12.25 KB
一键复制 编辑 原始数据 按行查看 历史
18151521911@163.com 提交于 2022-02-26 18:26 . Initial commit
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 14 12:27:01 2018
"""
'''
OPenCV3 计算机视觉 笔记
第二章 : 处理文件,摄像头和图形用户界面
Cameo项目(人脸跟踪和图像处理)
'''
'''
采用面向对象设计方法
定义了CaptureManager类和WindowManager类
'''
import cv2
import numpy as np
import time
class CaptureManager(object):
'''
定义一个CaptureManager类,作为一个高级的I/O流接口,用于提取视频流
该类可以用来读取新的帧(来自视频文件或者摄像头),并将帧分配到一个或者多个输出中,这些输出包括
静止的图像文件、视频文件以及窗口.
在应用程序的主循环的每一次迭代通常应调用enter_frame()和exit_frame()函数
param:
__channel:通道的初始值默认为0,只有在多个摄像头的情况下,通道初始值可能非0
__entered_frame: 捕获的一帧图像是否还存在(是否读取了),如果已经读取了,设置为False,否则设置为True
__frame:如果图像捕获成功,保存该帧图像 该属性保存的是在当前通道下调用enter_frame()函数时对应的图像
__image_file_name:捕获的一帧图像 保存路径 如果不为None,表示正在保存当前帧图片
__video_file_name:捕获的视频 保存路径 如果不为None,表示正在保存当前帧图片到视频文件中
__video_encoding:视频文件的编码格式
__video_writer:VideoWriter对象,用于保存写入视频文件
__fps_estimate:估计帧速率 __fps_estimate=__frames_elapsed/花费时间
__start_time:开始捕获的时间
__frames_elapsed:当前捕获的总帧数
'''
def __init__(self,capture,preview_window_manager= None,should_mirror_preview = False):
'''
构造函数
args:
capture:VideoCapture对象,用于读取视频文件或者捕获摄像头图像 例如capture = cv2.VideoCapture(0)
preview_window_manager:预处理窗口管理器,WindowManager对象,如果设置了该参数,在调用enter_frame()函数
时会把当前捕获帧图像显示在指定的窗体上。
should_mirror_preview:是否在指定窗口上镜像显示(水平翻转)
'''
self.preview_window_manager = preview_window_manager
self.should_mirror_preview = should_mirror_preview
#定义私有属性
self.__capture = capture
self.__channel = 0
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
self.__frames_elapsed = int(0)
self.__fps_estimate = None
#将一个getter()方法变成属性(和C#中的get访问器类似)
@property
def channel(self):
return self.__channel
#将一个setter()方法变成属性(和C#中的set访问器类似)
@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
@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
'''
注意:enter_frame()函数和exit_frame()函数是成对执行的
enter_frame()负责捕获一帧图像,只有执行了exit_frame()才会把当前捕获的一帧图像获取出来,然后才能捕获
下一帧,不然enter_frame()不会捕获新的帧
'''
def enter_frame(self):
'''
开始捕获下一帧图像,并设置捕获捕获的图像状态?已经读取?或者没有读取
只能(同步)捕获一帧,而且会推迟从一个通道的获取,以便随后能从属性frame中读取(即执行exit_frame()函数)
(即捕获了一帧图像之后,只有读取之后,才能捕获下一帧,不然会推迟捕获下一帧)
'''
#检查上一帧图像是否还存在(是否读取了),如果已经读取了,则可以捕获下一帧
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):
'''
从当前通道获取图像,估计帧速率,通过窗口管理器显示图像,执行暂停的请求,从而向文件中写入图像(如果指定文件路径)
'''
#获取和读取已经捕获的一帧图片,然后设置标志位__entered_frame,以便读取下一帧
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
#如果指定了窗口管理器 在窗口中显示图像
if self.preview_window_manager is not None:
#是否在窗口中镜像显示(水平翻转)
if self.should_mirror_preview:
mirrored_framed = np.fliplr(self.__frame).copy()
self.preview_window_manager.show(mirrored_framed)
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.__entered_frame = False
self.__frame = None
def write_image(self,filename):
'''
指定每一帧图像的写入路径,实际的写入操作会推迟到下一次调用exit_frame()函数
args:
filename:图片文件路径
'''
self.__image_file_name = filename
def start_write_video(self,filename,encoding=cv2.VideoWriter_fourcc('m','p','4','v')):
'''
指定每一帧图像写入的视频路径,实际的写入操作会推迟到下一次调用exit_frame()函数
args:
filename:视频文件路径
encoding:视频编码格式
'''
self.__video_file_name = filename
self.__video_encoding = encoding
def stop_write_video(self):
'''
停止把每一帧图像写入指定视频文件
清空一些相关参数
'''
if self.__video_writer is not None:
self.__video_writer.release()
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
#判断VideoWriter对象是否存在,不存在,重新创建一个用于写视频,并初始化相关参数
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)))
#1.VideoWriter类的构造函数指定视频文件名,这个文件名对应的文件若存在,则会被覆
#2.需要指定编解码器
#3.帧速率
#4.帧大小
self.__video_writer = cv2.VideoWriter(self.__video_file_name,self.__video_encoding,fps,size)
#把一帧图像写入视频文件
self.__video_writer.write(self.__frame)
def release(self):
'''
释放对象
'''
if self.__capture is not None:
self.__capture.release()
if self.__video_writer is not None:
self.video_writes.release()
class WindowManager(object):
'''
定义一个窗口管理器类 用于抽象窗口和键盘,鼠标
Parma :
__window_name:该窗口名称
__is_window_created:表示该窗口是否已经被创建 存在True,不存在False
'''
def __init__(self,window_name,key_press_call_back = None,mouse_call_back = None):
'''
构造函数 初始化参数
args:
window_name:指定准备创建的窗口名字
key_press_call_back:键盘事件回调函数 该函数有一个参数,即按下的键盘的ASCII码
mouse_call_back:鼠标事件回调函数
鼠标事件的回调函数5个参数 (event,x,y,flag,param)
args:
event:回调事件参数,有很多取值,分别对应不同的鼠标事件
param:可选参数,它是setMouseCallback()函数的第三个参数 默认为0
flag:标志参数 如 cv2.EVENT_FLAG_LBUTTON:该事件对应按下鼠标左键
x,y:鼠标坐标
'''
self.key_press_call_back = key_press_call_back
self.mouse_call_back = mouse_call_back
self.__window_name =window_name
self.__is_window_created = False
if self.mouse_call_back is not None:
#设置鼠标事件回调函数 来获取鼠标输入
cv2.setMouseCallback(window_name,self.mouse_call_back)
@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):
'''
在窗口中显示一帧图像
args:
frame:一帧图像
'''
cv2.imshow(self.__window_name,frame)
def destory_window(self):
'''
销毁该窗口
'''
cv2.destroyWindow(self.__window_name)
self.__is_window_created = False
def process_event(self):
'''
该函数用于处理键盘事件
'''
#等待1ms
keycode = cv2.waitKey(1)
#有按键按下(keycode != -1)或者有按键回调函数
if self.key_press_call_back is not None and keycode != -1:
#抛弃GTK的非ASCII信息
keycode &= 0xff
#执行键盘事件回调函数
self.key_press_call_back(keycode)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/top_xiong/opencv.git
git@gitee.com:top_xiong/opencv.git
top_xiong
opencv
opencv
master

搜索帮助