05 pygame编程入门之五:Camera Module Introduction

pygame编程入门之五:Camera Module Introduction

作者: Nirav Patel([email protected])

翻译: 杨晓宏([email protected])

Pygame 1.9支持摄像头接口,允许你捕捉静态图像,观看实时流,并做一些简单的计算机视觉。本教程将介绍所有这些用例,提供您可以基于应用程序或游戏的代码示例。您可以参考完整的API的参考文档。
注意,在Pygame 1.9中,相机模块为在Linux上使用v4l2的相机提供了本机支持。通过可视设备或OpenCV支持其他平台,但本指南将重点介绍本机模块。大多数代码对于其他平台都是有效的,但是某些诸如控件之类的东西是行不通的。该模块也被标记为实验性的,这意味着API在后续版本中可能会发生变化。

#Import and Init
import pygame
import pygame.camera
from pygame.locals import *

pygame.init()
pygame.camera.init()

由于相机模块是可选的,所以需要像上面所示的那样手动导入和初始化。

捕捉单个图像

现在我们来看看最简单的例子,打开相机,捕捉一个框架作为一个表面。在下面的例子中,我们假设在计算机上有一个/dev/video0的摄像头,并将其初始化为640到480。被称为图像的表面是当getimage()被调用时所看到的任何东西。

cam = pygame.camera.Camera("/dev/video0",(640,480))
cam.start()
image = cam.get_image()

列出连接摄像头

你可能会想,如果不知道相机的确切路径呢?我们可以要求模块提供一个安装在计算机上的相机列表,并初始化列表中的第一个摄像头。

camlist = pygame.camera.list_cameras()
if camlist:
    cam = pygame.caemra.Camera(camlist[0],(640,480))
Using Camera Controls

大多数相机都支持控制,比如翻转图像和改变亮度。 set_controls() and get_controls() 可以在 using start()之后的任何地方使用。

cam.set_controls(hflip = True, vflip = False)
print camera.get_controls()

捕捉实时流

本教程的其余部分将基于捕捉实时的图像流。为此,我们将使用下面的类。正如所描述的,它将简单地将一个持续的摄像头帧流到屏幕上,有效地显示实时视频。它基本上就是您所期望的,循环getimage(),到显示表面,然后翻转它。出于性能方面的原因,我们将每次使用为相机提供相同的表面。

class Capture(object):
    def __init__(self):
        self.size = (640,480)
        # create a display surface. standard pygame stuff
        self.display = pygame.display.set_mode(self.size, 0)

        # this is the same as what we saw before
        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()

        # create a surface to capture to.  for performance purposes
        # bit depth is the same as that of the display surface.
        self.snapshot = pygame.surface.Surface(self.size, 0, self.display)

    def get_and_flip(self):
        # if you don't want to tie the framerate to the camera, you can check
        # if the camera has an image ready.  note that while this works
        # on most cameras, some will never return true.
        if self.cam.query_image():
            self.snapshot = self.cam.get_image(self.snapshot)

        # blit it to the display surface.  simple!
        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):
                    # close the camera safely
                    self.cam.stop()
                    going = False

            self.get_and_flip()

由于 get_image()是一个阻塞调用,它可能在慢的摄像头上花费相当多的时间,这个例子使用 query_image() 来查看相机是否已经准备好了。这可以让你把游戏的framerate和你的相机分开。如果您发现您的相机不支持queryimage()函数,那么也可以让相机在单独的线程中捕获图像,从而获得大致相同的性能收益。

基本的计算机视觉

通过使用相机、转换和掩码模块,pygame可以做一些基本的计算机视觉。

颜色空间

在初始化相机时,colorspace是一个可选参数,它有“RGB”、“YUV”和“HSV”作为可能的选择。YUV和HSV通常对计算机视觉比RGB更有用,并且允许你更容易通过颜色来调整阈值,我们将在后面的教程中看到。

self.cam = pygame.camera.Camera(self.clist[0], self.size, "RGB")
../_images/camera_rgb.jpg
self.cam = pygame.camera.Camera(self.clist[0], self.size, "YUV")
../_images/camera_yuv.jpg
self.cam = pygame.camera.Camera(self.clist[0], self.size, "HSV")
../_images/camera_hsv.jpg

Thresholding

从转换模块中使用 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)
../_images/camera_thresholded.jpg

当然,只有当您已经知道您要寻找的对象的确切颜色时,这才有用。
为了解决这个问题,让阈值在现实世界中可用,需要添加一个校准阶段,在这个阶段识别对象的颜色并使用它来进行阈值设置。
使用transform模块的 average_color() 函数来完成这项工作。
下面是一个校准函数例子,你可以循环,直到像按键一样的事件,以及类似。盒子里的颜色将会是这个threshold颜色。
请注意,在下面的图像中使用HSV彩色空间。

def calibrate(self):
    # capture the image
    self.snapshot = self.cam.get_image(self.snapshot)
    # blit it to the display surface
    self.display.blit(self.snapshot, (0,0))
    # make a rect in the middle of the screen
    crect = pygame.draw.rect(self.display, (255,0,0), (145,105,30,30), 4)
    # get the average color of the area inside the rect
    self.ccolor = pygame.transform.average_color(self.snapshot, crect)
    # fill the upper left corner with that color
    self.display.fill(self.ccolor, (0,0,50,50))
    pygame.display.flip()
    
../_images/camera_average.jpg
pygame.transform.threshold(self.thresholded,self.snapshot,self.ccolor,(30,30,30),(0,0,0),2)
../_images/camera_thresh.jpg

你可以用同样的方法做一个简单的绿色屏幕/蓝色屏幕,首先得到一个背景图像,然后对它进行阈值处理。
下面的例子只是把相机对准了HSV彩色空间的空白白色墙壁。

def calibrate(self):
    # capture a bunch of background images
    bg = []
    for i in range(0,5):
      bg.append(self.cam.get_image(self.background))
    # average them down to one to get rid of some noise
    pygame.transform.average_surfaces(bg,self.background)
    # blit it to the display surface
    self.display.blit(self.background, (0,0))
    pygame.display.flip()
    
../_images/camera_background.jpg
pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(30,30,30),(0,0,0),1,self.background)
../_images/camera_green.jpg

使用掩模模块

如果你只是想要显示图像,上面的东西是很棒的,但是使用蒙版模块,你也可以使用摄像头作为游戏的输入设备。例如,回到阈值的例子中,我们可以找到那个对象的位置,并使用它来控制屏幕上的对象。

def get_and_flip(self):
    self.snapshot = self.cam.get_image(self.snapshot)
    # threshold against the color we got before
    mask = pygame.mask.from_threshold(self.snapshot, self.ccolor, (30, 30, 30))
    self.display.blit(self.snapshot,(0,0))
    # keep only the largest blob of that color
    connected = mask.connected_component()
    # make sure the blob is big enough that it isn't just noise
    if mask.count() > 100:
        # find the center of the blob
        coord = mask.centroid()
        # draw a circle with size variable on the size of the blob
        pygame.draw.circle(self.display, (0,255,0), coord, max(min(50,mask.count()/400),5))
    pygame.display.flip()
../_images/camera_mask.jpg

这是最基本的例子。
你可以追踪多个不同颜色的斑点,找到物体的轮廓,在现实生活中和在游戏对象之间进行碰撞检测,获得一个物体的角度,以获得更好的控制,等等。玩得开心!

你可能感兴趣的:(05 pygame编程入门之五:Camera Module Introduction)