camon详细解决过程

原

基于Python的Cameo实现详解

以下内容为学习<OpenCV 3计算机视觉Python与原实现>(原书第2版)过程中,对编码的相关注释(菜鸟级).

同时参考了文章:Python 使用Opencv实现cameo功能,https://blog.csdn.net/HuangZhang_123/article/details/80415861

该代码由managers.py,cameo.py两部分组成,运行cameo.py实现控制摄像头拍摄及录屏,截图的功能.

详细代码及注释如下:

managers.py

  1. import cv2
  2. import numpy as np
  3. import time
  4. #视屏管理类
  5. #来读取新的帧,并能将帧分派到一个或多个输出中,这些输出包括静止的图片文件,视频文件以及窗口
  6. class Capturemanager(object):
  7. #类变量前加 _ 代表变量设置保护变量,只有类和子类才能访问
  8. #类变量前加 __ 代表将变量设置私有变量,只有类对象才能访问
  9. def __init__(self, capture, previewWindowManager=None, shouldMirrorPreview=False):
  10. self.previewWindowManager = previewWindowManager#创建界面管理类
  11. self.shouldMirrorPreview = shouldMirrorPreview#控制图像是否翻转,产生镜像文件
  12. self._capture = capture#视频或图片提取类型
  13. self._channel = 0#通道数,暂时没有使用
  14. self._enteredFrame = False#判断之前的窗口是否存在,默认为False
  15. self._frame = None#当前帧的图像
  16. self._imageFilename = None#图片名称,当截取图片时赋值,截取完毕后重新赋值None
  17. self._videoFilename = None#视屏名称,当截取视屏时赋值,截取完毕后重新赋值None
  18. self._videoEncoding = None#视频录制过程中赋值encoding,结束时赋值None
  19. self._videoWriter = None#在视频录制时赋值cv2.VideoWriter作用,指定视频格式并进行frame的记录,录制结束后赋值None
  20. self._startTime = None#计算fps的起始时间
  21. self._framesElapsed = float(0)#视频共录制帧数
  22. self._fpsEstimate = None#fps值
  23. #设置只读属性
  24. @property
  25. def channel(self):
  26. return self._channel
  27. #设置可写属性
  28. @channel.setter
  29. def channel(self, value):
  30. if self._channel != value:
  31. self._channel = value
  32. self.frame = None
  33. #设置只读属性
  34. @property
  35. def frame(self):
  36. if self._enteredFrame and self._frame is None:#在已存在窗口且frame为空的情况下,使用retrieve()方法提取摄像头数据
  37. #_enteredFrame为第一帧提取出的摄像头数据
  38. _, self._frame = self._capture.retrieve()
  39. return self._frame
  40. #设置只读属性
  41. @property
  42. def isWritingImage(self):
  43. return self._imageFilename is not None
  44. #设置只读属性
  45. @property
  46. def isWritingVideo(self):
  47. return self._videoFilename is not None
  48. #启动摄像头录制功能
  49. def enterFrame(self):
  50. '''Capture the next frame,if any'''
  51. #But first, check that any previous(之前的) frame was exited.
  52. #assert:判断条件是否成立,成立继续运行程序,不成立返回提醒值,程序中断
  53. #assert True,'提醒条件'
  54. #assert false,'提醒条件'
  55. #判断之前的窗口是否存在,若存在报错
  56. #self._enteredFrame-->False
  57. assert not self._enteredFrame,'previous enterFrame() had no matching exitFrame()'
  58. if self._capture is not None:#判断是否存在控制器
  59. self._enteredFrame = self._capture.grab()#capture = cv2.VideoCapture(0),返回True值
  60. #self._enteredFrame -->True
  61. #VideoCapure里的read是grab和retrieve的结合,由下面的函数介绍可知grab是指向下一个帧,retrieve是解码并返回一个
  62. # 帧,而且retrieve比grab慢一些,所以当不需要当前的帧或画面时,可以使用grab跳过,与其使用read更省时间。
  63. # 因为有的时候缓冲区的画面是存在了延迟的。当不需要的时候可以多grab之后再read的话,就能比一直read更省时间,
  64. # 因为没有必要把不需要的帧解码,由介绍可知也可以使用grab实现硬件同步。
  65. #视频显示,视频录制,视频保存的功能
  66. def exitFrame(self):
  67. '''Draw to the window. Write to files. Release(释放) the frame'''
  68. #Check whether any grabbed frame is retrievable
  69. #The getter may retrieve and cache the frame
  70. print(4,' ',self._frame is None)
  71. if self._frame is None:
  72. self._enteredFrame = False#_enteredFrame为False时,为第一次抓取视屏信息,采用grab()方式
  73. #为True时为非第一次抓取,采用retrieve方式抓取
  74. return
  75. #计算fps
  76. #Update the FPS estimate and related variables
  77. #使用帧数/时间得到每秒的帧数
  78. if self._framesElapsed == 0:
  79. self._startTime = time.time()
  80. else:
  81. timeElapsed = time.time() - self._startTime
  82. self._fpsEstimate = self._framesElapsed / timeElapsed
  83. self._framesElapsed += 1
  84. #显示图像
  85. #Draw to the window, if any
  86. if self.previewWindowManager is not None:
  87. if self.shouldMirrorPreview:#控制是否镜像显示图像
  88. #向左/右方向翻转阵列,翻转图像
  89. mirroredFrame = np.fliplr(self._frame).copy()
  90. self.previewWindowManager.show(mirroredFrame)#显示图像
  91. else:
  92. self.previewWindowManager.show(self._frame)#显示图像
  93. #图片文件生成
  94. #Write to the image file, if any
  95. if self.isWritingImage:
  96. cv2.imwrite(self._imageFilename, self._frame)
  97. self._imageFilename = None
  98. #录制文件生成
  99. #Write to the video file ,if any.
  100. self._writeVideoFrame()
  101. #录像生成
  102. #Release the frame
  103. self._frame = None#将参数还原到循环初始状态
  104. self._enteredFrame = False#将参数还原到循环初始状态
  105. #设置图片文件名
  106. def WriteImage(self, filename):
  107. '''Write the next exited frame to an image file'''
  108. self._imageFilename = filename
  109. #开始录制
  110. def startWritingVideo(self, filename, encoding = cv2.VideoWriter_fourcc('I','4','2','0')):
  111. '''Start writing exited frames to a video file.'''
  112. self._videoFilename = filename
  113. self._videoEncoding = encoding
  114. #停止录制
  115. def stopWritingVideo(self):
  116. '''Stop writing exited frames to a video file'''
  117. self._videoFilename = None
  118. self._videoEncoding = None
  119. self._videoWriter = None
  120. #录制视频
  121. def _writeVideoFrame(self):
  122. if not self.isWritingVideo:#控制是否为保存视频
  123. return
  124. if self._videoWriter is None:#如果视频保存方式无定义
  125. fps = self._capture.get(cv2.CAP_PROP_FPS)#获取fps
  126. if fps == 0.0:#如果未获取到fps
  127. #The capture's FPS is unknown so use an estimate.
  128. if self._framesElapsed<20:#如果现有帧数小于20,无法计算直接退出子程序
  129. #Wait until more frames elapse so that the estimate is more stable
  130. return
  131. else:
  132. fps = self._fpsEstimate
  133. size = (int(self._capture.get(cv2.CAP_PROP_FRAME_WIDTH)),
  134. int(self._capture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
  135. #创建videoWriter
  136. self._videoWriter = cv2.VideoWriter(
  137. self._videoFilename, self._videoEncoding, fps, size)
  138. #写入视频
  139. self._videoWriter.write(self._frame)
  140. #创建界面管理类
  141. #使应用程序代码能以面向对象的形式处理窗口的事件
  142. class WindowManager(object):
  143. def __init__(self,windowName, keypressCallback = None):
  144. self.keypressCallback = keypressCallback#实现按键控制功能
  145. self._windowName = windowName#在cameo.py中实例化为'Cameo'
  146. self._isWindowCreated = False#控制是否循环提取摄像头信息
  147. @property
  148. def isWindowCreated(self):#作为窗口是否存在的判别条件,self._isWindowCreated在createWindow中已修改为True
  149. return self._isWindowCreated
  150. #创建窗口
  151. def createWindow(self):
  152. cv2.namedWindow(self._windowName)#创建视屏窗口
  153. self._isWindowCreated = True#修改类属性,说明已经创建窗口,为Ture
  154. #显示窗口
  155. def show(self, frame):
  156. cv2.imshow(self._windowName, frame)
  157. #注销窗口
  158. def destroyWindow(self):
  159. cv2.destroyWindow(self._windowName)
  160. self._isWindowCreated = False
  161. #执行键盘操作的回调函数
  162. def processEvent(self):
  163. keycode = cv2.waitKey(1)#等待1微秒获取键盘输入信息
  164. if self.keypressCallback is not None and keycode != -1:#如果编辑了外界设备输入程序且输入不为0
  165. #Discard any non-ASCII info encoded by GTK
  166. keycode &= 0xFF#使用GTK进行编码
  167. self.keypressCallback(keycode)

cameo.py

  1. import cv2
  2. from managers import WindowManager, Capturemanager
  3. class Cameo(object):
  4. def __init__(self):
  5. #创建一个窗口,并将键盘的回调函数传入
  6. self._windowManager = WindowManager('Cameo', self.onKeypress)
  7. #告诉程序数据来自摄像头,还有镜面效果
  8. self._captureManager = Capturemanager(
  9. cv2.VideoCapture(0), self._windowManager, True
  10. )
  11. def run(self):
  12. '''Run the main loop'''
  13. self._windowManager.createWindow()#创建窗口,设置self._isWindowCreated = True控制循环提取摄像头信息
  14. while self._windowManager.isWindowCreated:
  15. #这里的enterFrame作用使得从程序从摄像头中取数据
  16. self._captureManager.enterFrame()#开启窗口
  17. #frame是原始帧数据,未做任何改动
  18. frame = self._captureManager.frame#获得当前帧
  19. #TODO: filter the frame(Chapter 3)
  20. #exitFrame()主要功能:实现截屏,录屏
  21. self._captureManager.exitFrame()#根据控制参数,选择是否进行截屏和录屏,并将self._frame等参数还原准备下一次循环
  22. #回调函数
  23. self._windowManager.processEvent()
  24. def onKeypress(self, keycode):
  25. '''Handle a keypress
  26. space -> Take a screenshot
  27. tab -> State/stop recording a screencast
  28. escape -> Quit
  29. '''
  30. if keycode == 32: #Space
  31. #截取保存的文件名称
  32. self._captureManager.WriteImage('screenshot.png')#设置截取图片保存信息
  33. elif keycode == 9:#tab
  34. if not self._captureManager.isWritingVideo:#判断为开始录制视频或结束录制视频
  35. #录像保存的文件名字
  36. self._captureManager.startWritingVideo(
  37. 'screencast.avi'
  38. )
  39. else:
  40. self._captureManager.stopWritingVideo()
  41. elif keycode == 27: #escape
  42. self._windowManager.destroyWindow()
  43. if __name__ == '__main__':
  44. Cameo().run()






湘云_聚离关注
湘云_聚离

9篇文章

排名:千里之外

retacn关注
retacn

480篇文章

排名:3000+

Lecol_leng关注
Lecol_leng

33篇文章

排名:千里之外

LiAnG小炜关注
LiAnG小炜

55篇文章

排名:千里之外









expat介绍文档翻译




03-22

阅读数
3万+






原文地址:
http://www.xml.com/pub/a/1999/09/expat/index.html

因为需要用,所以才翻译了这个文档。但总归赖于英语水平很有限,翻译出来的中文有可能...


博文
来自: ymj7150697的专栏







没有更多推荐了,返回首页




posted @ 2019-03-29 10:43  羽芊曦珖  阅读(1118)  评论(0)    收藏  举报