附录 A:集成 Pygame
本附录显示了如何在 OpenCV 应用中设置 Pygame 库以及如何使用 Pygame 进行窗口管理。 此外,附录还概述了 Pygame 的其他功能以及一些学习 Pygame 的资源。
注意
安装 Pygame
假设我们已经根据第 1 章,“设置 OpenCV”中描述的方法之一设置了 Python。 根据我们现有的设置,我们可以通过以下方式之一安装 Pygame:
- 带有 32 位 Python 的 Windows:从这个页面下载并安装 Pygame 1.9.1。
- 带有 64 位 Python 的 Windows:从这个页面。
-
带有 Macports 的 Mac:打开终端并运行以下命令:
```py $ sudo port install py27-game
```
-
带有 Homebrew 的 Mac:打开终端并运行以下命令来安装 Pygame 的依赖项,然后安装 Pygame 本身:
```py $ brew install sdl sdl_image sdl_mixer sdl_ttf smpeg portmidi $ /usr/local/share/python/pip install \
hg+http://bitbucket.org/pygame/pygame
```
-
Ubuntu 及其衍生版本:打开终端并运行以下命令:
```py $ sudo apt-get install python-pygame
```
-
其他类似 Unix 的系统:Pygame 在许多系统的标准存储库中可用。 典型的包装名称包括
pygame,pygame27,py-game,py27-game,python-pygame,和python27-pygame。
现在,Pygame 应该可以使用了。
文档和教程
Pygame 的 API 文档和一些教程可以在这个页面上在线找到。
Al Sweigart 的《使用 Python 和 Pygame 制作游戏》是一本烹饪手册,用于在 Pygame 1.9.1 中重新创建几个经典游戏。 可在这个页面上在线获得免费的电子版本,或在这个页面上下载 PDF 文件。 。
派生管理器
如第 2 章,“处理相机,文件和 GUI”中所述,我们的面向对象设计使我们可以轻松地将 OpenCV 的 HighGUI 窗口管理器替换为另一个窗口管理器,例如 Pygame 。 为此,我们只需要将managers.WindowManager类子类化,并覆盖四种方法:createWindow(),show(),destroyWindow()和processEvents()。 另外,我们需要导入一些新的依赖项。
要继续,我们需要第 2 章,“处理摄像机,文件和 GUI”的managers.py文件和第 4 章“使用 Haar 级联跟踪人脸”的utils.py文件。 从utils.py中,我们只需要一个函数isGray(),我们在第 4 章“用 Haar 级联跟踪人脸”中实现了该函数。 让我们编辑managers.py以添加以下导入:
import pygame
import utils
同样在managers.py中,在实现WindowManager之后的某个地方,我们想添加一个名为PygameWindowManager的新子类:
class PygameWindowManager(WindowManager):
def createWindow(self):
pygame.display.init()
pygame.display.set_caption(self._windowName)
self._isWindowCreated = True
def show(self, frame):
# Find the frame's dimensions in (w, h) format.
frameSize = frame.shape[1::-1]
# Convert the frame to RGB, which Pygame requires.
if utils.isGray(frame):
conversionType = cv2.COLOR_GRAY2RGB
else:
conversionType = cv2.COLOR_BGR2RGB
rgbFrame = cv2.cvtColor(frame, conversionType)
# Convert the frame to Pygame's Surface type.
pygameFrame = pygame.image.frombuffer(
rgbFrame.tostring(), frameSize, 'RGB')
# Resize the window to match the frame.
displaySurface = pygame.display.set_mode(frameSize)
# Blit and display the frame.
displaySurface.blit(pygameFrame, (0, 0))
pygame.display.flip()
def destroyWindow(self):
pygame.display.quit()
self._isWindowCreated = False
def processEvents(self):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and \
self.keypressCallback is not None:
self.keypressCallback(event.key)
elif event.type == pygame.QUIT:
self.destroyWindow()
return
请注意,我们正在使用两个 Pygame 模块:pygame.display和pygame.event。
通过调用pygame.display.init()创建窗口,并通过调用pygame.display.quit()销毁窗口。 重复调用display.init()不起作用,因为 Pygame 仅适用于单窗口应用。 Pygame 窗口具有pygame.Surface类型的绘图表面。 要获得对此Surface的引用,我们可以调用pygame.display.get_surface()或pygame.display.set_mode()。 后一个函数在返回Surface实体的属性之前对其进行修改。 Surface实体具有blit()方法,即,该方法将另一个Surface和一个坐标对作为参数,其中后一个Surface应该被“涂抹”(绘制)到第一个坐标上。 完成当前帧的窗口Surface的更新后,我们应调用pygame.display.flip()来显示它。
通过调用pygame.event.get()来轮询诸如keypresses之类的事件,该事件将返回自上次调用以来发生的所有事件的列表。 每个事件的类型均为pygame.event.Event,并具有type属性,该属性指示事件的类别,例如,单击的pygame.KEYDOWN和单击窗口的关闭按钮的pygame.QUIT 。 根据type的值,Event实体可能具有其他属性,例如KEYDOWN 事件的key(ASCII 键代码)。
相对于使用 HighGUI 的基础WindowManager,PygameWindowManager通过在每帧 OpenCV 的图像格式和 Pygame 的Surface格式之间进行转换会产生一些间接费用。 但是,PygameWindowManager提供正常的窗口关闭行为,而基本的WindowManager不提供。
修改应用
让我们将cameo.py文件修改为使用PygameWindowManager而不是WindowManager。 在cameo.py中找到以下行:
from managers import WindowManager, CaptureManager
替换为:
from managers import PygameWindowManager as WindowManager, \
CaptureManager
就这样! 现在,cameo.py使用一个 Pygame 窗口,当单击标准关闭按钮时,该窗口应该关闭。
Pygame 的进一步使用
我们仅使用了pygame.display和pygame.event模块的一些基本功能。 Pygame 提供了更多功能,包括:
- 绘制 2D 几何
- 绘制文字
- 管理可绘制 AI 实体(精灵)的组
- 捕获与窗口,键盘,鼠标和操纵杆/游戏手柄相关的各种输入事件
- 创建自定义事件
- 播放和合成声音和音乐
例如,Pygame 可能是适合使用计算机视觉的游戏的后端,而 HighGUI 则不是。
总结
到现在为止,我们应该有一个应用,该应用使用 OpenCV 捕获(并可能操纵)图像,同时使用 Pygame 显示图像和捕获事件。 从这个基本的集成示例开始,您可能想要扩展PygameWindowManager以包装其他 Pygame 功能,或者您可能想要创建另一个WindowManager子类来包装另一个库。
