如何通过 websockets 发送 pygame 图像? [英] How to send a pygame image over websockets?

查看:20
本文介绍了如何通过 websockets 发送 pygame 图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试编写一些代码,让网站可以查看我的网络摄像头.我大致遵循了本网站上链接的教程,除了使用 Python 和 pygame 而不是 Processing.

I'm currently trying to code something that will let websites view my webcam. I'm roughly following the tutorial linked on this website, except using Python and pygame instead of Processing.

目前,我的代码正在抓取一个 pygame 图像(最初是一个 SimpleCV 图像),尝试将其转换为 jpg 格式,然后通过 websockets 将其发送到客户端,然后将其显示在 img 中 标签.但是,我似乎无法弄清楚如何将 pygame 图像转换为 jpg 并使其在网络浏览器上正确显示.

At the moment, my code is grabbing a pygame image (which was originally a SimpleCV image), attempting to convert it into jpg format, and send it over websockets to the client where it will display it inside an img tag. However, I can't seem to figure out how to convert a pygame image into jpg and get it to display properly on the web browser.

这是我的服务器代码,它使用 Flask 和 gevent:

This is my code for the server, which uses Flask and gevent:

#!/usr/bin/env python

import base64
import cStringIO
import time

from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from flask import Flask, request, render_template


import pygame
pygame.init()

import SimpleCV as scv

app = Flask(__name__)
cam = scv.Camera(0)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/camera')
def camera():

    if request.environ.get('wsgi.websocket'):
        ws = request.environ['wsgi.websocket']

        while True:            
            image = cam.getImage().flipHorizontal().getPGSurface()
            data = cStringIO.StringIO()
            pygame.image.save(image, data)
            ws.send(base64.b64encode(data.getvalue()))
            time.sleep(0.5)

if __name__ == '__main__':
    http_server = WSGIServer(('',5000), app, handler_class=WebSocketHandler)
    http_server.serve_forever()

这是我的 HTML 文件:

This is my HTML file:

<!DOCTYPE HTML>
<html>
<head>
<title>Flask/Gevent WebSocket Test</title>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script type="text/javascript" charset="utf-8">
        $(document).ready(function(){
            if ("WebSocket" in window) {
                cam = new WebSocket("ws://" + document.domain + ":5000/camera");
                cam.onmessage = function (msg) {
                    $("#cam").attr('src', 'data:image/jpg;base64,' + msg.data);
                };
                cam.onerror = function(e) {
                    console.log(e);
                }
            } else {
                alert("WebSocket not supported");
            }
        });
    </script>
</head>
<body>
    <img id="cam" src="" width="640" height="480" />
</body>
</html> 

这些是我认为我遇到问题的具体行:

These are the specific lines that I think I'm having trouble with:

while True:
    image = cam.getImage().flipHorizontal().getPGSurface()
    data = cStringIO.StringIO()
    pygame.image.save(image, data)
    ws.send(base64.b64encode(data.getvalue()))
    time.sleep(0.5)

目前,如果我尝试运行我的代码,转到 localhost:5000 将显示无效的 jpg 图像.如果我尝试在 Firefox 上运行它,它也会变得非常缓慢,但这可能是一个无关的问题,我可以稍后进行调试.

Currently, if I try and run my code, going to localhost:5000 will display an invalid jpg image. It also becomes really laggy if I try running it on Firefox, but that may be an unrelated issue that I can debug later.

我已经检查并确保 pygame 图像是有效的,因为我是从另一个库转换它的,并且还通过来回发送文本数据来检查我是否正确使用了 websocket.

I've checked and made sure that the pygame image is a valid one, since I'm converting it from another library, and also checked that I was using websockets correctly by sending text data back and forth.

我也尝试调用 pygame.image.to_string 来尝试将 pygame 表面转换为 RGB 格式,但这也不起作用.

I've also tried calling pygame.image.to_string to try and convert the pygame surface into RGB format, but that also doesn't work.

我做错了什么?

推荐答案

使用底层的 PIL 图像,我们可以写入一个类似文件的对象,读回并对其进行 base-64 编码:

Using the underlying PIL image, we can write to a file-like object, read back and base-64 encode it:

from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from flask import Flask, request
from time import sleep
from cStringIO import StringIO

import pygame
pygame.init()

import SimpleCV as scv

app = Flask(__name__)
cam = scv.Camera(0)


@app.route('/camera')
def camera():

    if request.environ.get('wsgi.websocket'):
        ws = request.environ['wsgi.websocket']

        while True:
            fp = StringIO()
            image = cam.getImage().flipHorizontal().getPIL()
            image.save(fp, 'JPEG')
            ws.send(fp.getvalue().encode("base64"))
            #fp.close() << benchmark and memory tests needed
            sleep(0.5)


if __name__ == '__main__':
    http_server = WSGIServer(('',5000), app, handler_class=WebSocketHandler)
    http_server.serve_forever()

这篇关于如何通过 websockets 发送 pygame 图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆