2013-08-23 7 views
5

Attualmente sto cercando di codificare qualcosa che consenta ai siti Web di visualizzare la mia webcam. Sto seguendo grosso modo il tutorial collegato su this website, eccetto l'uso di Python e pygame invece di Processing.Come inviare un'immagine pygame tramite websocket?

Al momento, il mio codice sta acquisendo un'immagine pygame (che in origine era un'immagine SimpleCV), tentando di convertirla in formato jpg e inviarla tramite websocket al client in cui verrà visualizzata all'interno di un tag img. Tuttavia, non riesco a capire come convertire un'immagine pygame in jpg e farlo visualizzare correttamente sul browser web.

Questo è il mio codice per il server, che utilizza Flask e 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() 

Questo è il mio file 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> 

Queste sono le linee specifiche che penso sto avendo problemi con:

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) 

Attualmente, se provo e faccio funzionare il mio codice, andando a localhost:5000 volontà di splay un'immagine jpg non valida. Diventa anche molto lento se provo a eseguirlo su Firefox, ma potrebbe trattarsi di un problema non correlato che posso eseguire il debug in seguito.

Ho verificato e verificato che l'immagine di pygame sia valida, dal momento che la sto convertendo da un'altra libreria, e ho anche verificato che stavo usando correttamente i web socket inviando i dati di testo avanti e indietro.

Ho anche provato a chiamare pygame.image.to_string per provare a convertire la superficie di pygame in formato RGB, ma anche questo non funziona.

Cosa sto sbagliando?

+0

Non può upvote più ... – leon

risposta

4

Usando l'immagine sottostante PIL, possiamo scrivere in un oggetto simile a file, riletti e base-64 codificarlo:

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

Grazie mille! Questo ha funzionato perfettamente. – Michael0x2a

+0

Mi ci sono voluti 3 ore! Fattore nella configurazione della workstation sempre semplice su un Mac e completa mancanza di conoscenza sulle librerie di immagini :) – leon