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

pygame编程入门之五:Camera Module Introduction

作者: Nirav Patel(nrp@eclecti.cc)

翻译: 杨晓宏(561071777@qq.com)

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容