【问题标题】:How to send a pygame image over websockets?如何通过 websockets 发送 pygame 图像?
【发布时间】:2013-08-26 21:31:14
【问题描述】:

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

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

这是我的服务器代码,它使用了 Flask 和 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 文件:

<!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> 

这些是我认为我遇到问题的特定行:

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 上运行它也会变得非常滞后,但这可能是一个不相关的问题,我可以稍后进行调试。

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

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

我做错了什么?

【问题讨论】:

    标签: python image websocket pygame gevent


    【解决方案1】:

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

    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()
    

    【讨论】:

    • 花了我 3 个小时!考虑到 Mac 上始终简单的工作站设置和完全缺乏图像库知识:)
    【解决方案2】:

    我正在与同样的问题作斗争,问题是双重编码。在 Python 文件中,您必须删除“ws.send(base64.b64encode(data.getvalue()))”行并发送未编码的图像。然后在 js 文件中,您的脚本将进行编码等等。

    【讨论】:

      猜你喜欢
      • 2018-06-13
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 2017-11-19
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      相关资源
      最近更新 更多