基於tornado實現web camera
最近在學習python,找了一個框架學習,我選擇的是tornado,因爲其不只是一個web開發框架,其還是一個服務器,異步事件庫,一舉多得。
我一直在完opencv,我想接合他們兩個做一個web camera,這就開始。
在tornado中要實現對一個URL的響應,需要實現你自己的Handle,根據你對外提供的接口,實現相關的接口就好了。
下面爲整個工程的文件內容:
import tornado.ioloop
import tornado.web
import tornado.gen
import cv2
from tornado.options import define, options
define("port", default = 5000, help = "run in tornado on xxxx port", type = int)
define("id", default = 0, help = "camera id", type = int)
def auth(func):
def _auth(self):
if not self.current_user:
re = {"code" : 404, "message" : "login failed!"}
self.write(re)
else:
func(self)
return _auth;
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("user")
class LoginHandler(BaseHandler):
def get(self):
self.write('<html><body><form action="/login" method="post">'
'Name: <input type="text" name="name">'
'<input type="submit" value="Sign in">'
'</form></body></html>')
def post(self):
name = self.get_argument("name", "error")
if name == "error":
re = {"code" : 404, "message" : "login failed!"}
else:
self.set_secure_cookie("user", name)
re = {"code" : 200, "message" : "login successfully!"}
self.write(re)
class CameraHandler(BaseHandler):
@auth
def get(self):
ret, image = self.application.cap.read()
if ret:
self.set_header("Content-Type", "image/jpeg")
self.set_header("Refresh", "1")
self.set_header("content-transfer-encoding", "binary")
r, i = cv2.imencode('.jpg', image)
if r:
self.write(bytes(i.data))
else:
selt.write('Sorry, encode faily!')
else:
self.write('Sorry, get camera data faily!')
class Application(tornado.web.Application):
def __init__(self, camera_id):
handlers = [('/camera', CameraHandler), ('/login', LoginHandler)]
self.cap = cv2.VideoCapture(camera_id)
self.camera_id = camera_id;
tornado.web.Application.__init__(self, handlers, debug = True ,cookie_secret = "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o")
def __del__(self):
self.cap.release()
if __name__ == '__main__':
tornado.options.parse_command_line();
app = Application(options.id)
app.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
這其中還包括了一個login的例子,我學習tornado是爲了使用其做app後臺,所以我實現了自己的auth的修飾器,這樣只是返回一串json字符,而不是重定向到login頁面。
在Application構造時設置設備,在http://localhost:xxx/camera
這個url上使用get方法就會返回一副圖片。
def get(self):
ret, image = self.application.cap.read()
if ret:
self.set_header("Content-Type", "image/jpeg")
self.set_header("Refresh", "1")
self.set_header("content-transfer-encoding", "binary")
r, i = cv2.imencode('.jpg', image)
if r:
self.write(bytes(i.data))
else:
selt.write('Sorry, encode faily!')
else:
self.write('Sorry, get camera data faily!')
這段代碼就是這個功能,開始的時候我只是將數據拿出來就發送,沒有進行imencode,導致瀏覽器不能正確的顯示,使用Refresh實現自動的刷新。
項目地址:https://git.oschina.net/zhouX/web_camera.git
無圖無真相: