2013-08-23 61 views
5

我目前正在嘗試編碼的東西,可以讓網站查看我的攝像頭。我大致遵循this website上鍊接的教程,除了使用Python和pygame代替Processing。如何通過websockets發送pygame圖像?

目前,我的代碼是抓住一個pygame的圖像(這本來是一個SimpleCV圖像),試圖將其轉換爲JPG格式,的WebSockets發送到客戶那裏將顯示它的img標籤內。但是,我似乎無法弄清楚如何將pygame圖像轉換爲jpg格式並使其在Web瀏覽器上正確顯示。

這是我的服務器代碼,它使用瓶和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將di展示無效的jpg圖像。如果我嘗試在Firefox上運行它,它也變得非常滯後,但這可能是一個無關緊要的問題,我可以稍後進行調試。

我已經檢查並確保pygame圖像是有效的,因爲我從另一個庫轉換它,並且還通過來回發送文本數據來檢查我是否正確使用websockets。

我也試着打電話pygame.image.to_string試圖將pygame表面轉換成RGB格式,但這也行不通。

我在做什麼錯?

+0

不能給予好評更多... – leon

回答

4

使用底層PIL圖像,我們可以寫一個類文件對象,閱讀背面和底座-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() 
+0

太感謝你了!這工作完美。 – Michael0x2a

+0

花了我3個小時!在Mac上總是簡單的工作站設置的因素,並完全缺乏圖像庫的知識:) – leon