我目前正在尝试编写一些代码,让网站可以查看我的网络摄像头。我大致遵循这个网站上链接的教程,除了使用Python和pygame而不是Processing。
目前,我的代码正在获取一个pygame图像(最初是SimpleCV图像),试图将其转换为jpg格式,并通过websocket将其发送到客户端,在那里它将在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图像是有效的,因为我正在从另一个库转换它,还通过来回发送文本数据来检查我是否正确使用了websocket。
我也尝试过调用pygame.image.to_string
来尝试将pygame曲面转换为RGB格式,但这也不起作用。
我做错了什么?
使用底层的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()
我正在与同一个问题作斗争,这个问题是双重编码。在Python文件中,您必须删除行";ws.send(base64.b64encode(data.getvalue()))";并且发送未编码的图像。然后在js文件中,您的脚本将进行编码等等。