camera模块介绍(Camera Module Introduction)
Author: by Nirav Patel
Contact: nrp@eclecti.cc
Pygame 1.9支持连接相机,允许您捕捉静止图像,观看直播流,并做一些简单的计算机视觉。 本教程将涵盖所有这些用例,提供可以基于您的应用或游戏的代码示例。 您可以参考完整API的参考文档。
注意从Pygame 1.9开始,相机模块为在Linux上使用v4l2的相机提供原生支持。 通过Videocapture或OpenCV支持其他平台,但本指南将重点介绍本身的模块。 大多数代码对其他平台都有效,但控件之类的某些东西不起作用。 该模块也标记为实验性的(EXPERIMENTAL),这意味着API可能会在后续版本中更改。
导入和初始化(Import and Init)
import pygame
import pygame.camera
from pygame.locals import *
pygame.init()
pygame.camera.init()
由于camera模块是可选的,因此需要手动导入和初始化,如上所示。
捕捉单个图像(Capturing a Single Image)
现在我们将介绍打开相机并将框架捕获帧作为表面【surface】。 在下面的示例中,我们假设计算机上有/ dev / video0处的摄像头,并将其初始化为640 x 480的大小。称为图像的表面是调用get_image()时摄像头看到的内容。
cam = pygame.camera.Camera("/dev/video0",(640,480))
cam.start()
image = cam.get_image()
列出已连接的相机(Listing Connected Cameras)
您可能想知道,如果我们不知道相机的确切路径会怎么样?我们可以要求模块提供连接到计算机的摄像机列表,并初始化列表中的第一台摄像机。
camlist = pygame.camera.list_cameras()
if camlist:
cam = pygame.caemra.Camera(camlist[0],(640,480))
使用相机控件(Using Camera Controls)
大多数相机都支持控制,如翻转图像和改变亮度。使用start()后,可以在任何时候使用set_controls()和get_controls()。
捕获流直播(Capturing a Live Stream)
本教程的其余部分将基于捕获实时图像流。 为此,我们将使用下面的类。 如上所述,它只会将持续的相机帧流呈现在屏幕上,有效地显示实时视频。 它基本上是你所期望的,循环get_image(),blitting到显示表面,然后翻转它。 出于性能原因,我们将为相机提供相同的表面以便每次使用。
class Capture(object):
def __init__(self):
self.size = (640,480)
# 创建一个显示surface。 标准的pygame东西
self.display = pygame.display.set_mode(self.size, 0)
# 这跟我们之前看到的一样
self.clist = pygame.camera.list_cameras()
if not self.clist:
raise ValueError("Sorry, no cameras detected.")
self.cam = pygame.camera.Camera(self.clist[0], self.size)
self.cam.start()
#创建要捕获的表面。 出于性能目的
#位深度与显示表面的深度相同。
self.snapshot = pygame.surface.Surface(self.size, 0, self.display)
def get_and_flip(self):
#如果你不想将帧率绑定到相机,你可以检查
#如果相机准备好了图像。 请注意,虽然这适用于
#大多数相机,但有些永远不会返回true。
if self.cam.query_image():
self.snapshot = self.cam.get_image(self.snapshot)
# 把它blit到显示器表面。 简单!
self.display.blit(self.snapshot, (0,0))
pygame.display.flip()
def main(self):
going = True
while going:
events = pygame.event.get()
for e in events:
if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
#安全地关闭相机
self.cam.stop()
going = False
self.get_and_flip()
由于get_image()是一个阻塞调用,在慢速摄像机上可能需要相当长的时间,因此本例使用query_image()来查看摄像机是否准备就绪。 这允许您将游戏的帧率与相机的帧率分开。 如果您发现相机不能正确支持query_image()函数,也可以让相机在单独的线程中捕获图像,以获得大致相同的性能增益。
基本计算机视觉(Basic Computer Vision)
通过使用camera,transform和mask模块,pygame可以做一些基本的计算机视觉。
色彩空间(Colorspaces)
初始化相机时,颜色空间是一个可选的参数,其中“RGB”、“YUV”和“HSV”是可能的选择。YUV和HSV都比RGB更适用于计算机视觉,允许您更容易按颜色阈值,我们将在本教程后面看到。
self.cam = pygame.camera.Camera(self.clist[0], self.size, "RGB")

self.cam = pygame.camera.Camera(self.clist[0], self.size, "YUV")

self.cam = pygame.camera.Camera(self.clist[0], self.size, "HSV")

阈值(Thresholding)
使用transform模块中的threshold()函数,可以执行简单的绿色屏幕效果,或者在场景中隔离特定颜色的对象。 在下面的示例中,我们仅将绿树阈值化,并使图像的其余部分变黑。 有关阈值功能的详细信息,请查阅参考文档。
self.thresholded = pygame.surface.Surface(self.size, 0, self.display)
self.snapshot = self.cam.get_image(self.snapshot)
pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(90,170,170),(0,0,0),2)

当然,只有在您已经知道要查找的对象的确切颜色时,这才有用。 为了解决这个问题并使阈值处理在现实世界中可用,我们需要添加一个校准阶段,我们可以识别对象的颜色并使用它来进行阈值处理。 我们将使用transform模块的average_color()函数来执行此操作。 下面是一个示例校准功能,您可以循环直到像按键这样的事件,以及它看起来像什么的图像。 框内的颜色将是用于阈值的颜色。 请注意,我们在下面的图像中使用HSV颜色空间。
def calibrate(self):
# 捕捉图像
self.snapshot = self.cam.get_image(self.snapshot)
# 把它blit到显示surface上
self.display.blit(self.snapshot, (0,0))
# 在屏幕中间制作一个rect
crect = pygame.draw.rect(self.display, (255,0,0), (145,105,30,30), 4)
# 获取rect内部区域的平均颜色
self.ccolor = pygame.transform.average_color(self.snapshot, crect)
# 用这种颜色填充左上角
self.display.fill(self.ccolor, (0,0,50,50))
pygame.display.flip()

pygame.transform.threshold(self.thresholded,self.snapshot,self.ccolor,(30,30,30),(0,0,0),2)

你可以使用相同的想法做一个简单的绿色屏幕/蓝色屏幕,首先获得一个背景图像,然后对其进行阈值处理。下面的示例只是将相机指向HSV色彩空间中的空白墙。
def calibrate(self):
# 捕获一堆背景图像
bg = []
for i in range(0,5):
bg.append(self.cam.get_image(self.background))
# 将它们平均降低到一个以消除一些噪音
pygame.transform.average_surfaces(bg,self.background)
# 把它搞定到显示器surface
self.display.blit(self.background, (0,0))
pygame.display.flip()

pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(30,30,30),(0,0,0),1,self.background)

使用Mask模块(Using the Mask Module)
如果你只想显示图像,上面的东西很棒,但是使用遮罩模块,你也可以使用相机作为游戏的输入设备。 例如,回到阈值化特定对象的示例,我们可以找到该对象的位置并使用它来控制屏幕上的对象。
def get_and_flip(self):
self.snapshot = self.cam.get_image(self.snapshot)
# 与我们之前得到的颜色相对应的阈值
mask = pygame.mask.from_threshold(self.snapshot, self.ccolor, (30, 30, 30))
self.display.blit(self.snapshot,(0,0))
# 只保留那种颜色的最大斑点
connected = mask.connected_component()
# 确保斑点足够大,不仅仅是噪音
if mask.count() > 100:
# 找到斑点的中心
coord = mask.centroid()
# 在斑点的大小上绘制一个大小可变的圆
pygame.draw.circle(self.display, (0,255,0), coord, max(min(50,mask.count()/400),5))
pygame.display.flip()

这只是最基本的例子。 您可以跟踪多个不同颜色的斑点,查找对象的轮廓,在现实生活和游戏对象之间进行碰撞检测,获得对象的角度以实现更精细的控制等等。 玩得开心!
以上内容,自己翻译,可能有误,可参考:Tutorials - camera模块介绍(Camera Module Introduction))
点我回顶部 ☚
Fin.