はじめに
某部活で作業せずにスマブラをする輩がいるので, いつでも部室の様子を見れるようにした話です.
OpenCVとWebSocketで, リアルタイムで様子が見れるものがあっさり作れたので
置いときます.
動作環境
CentOS Linux release 7.5.1804
Python 3.6.8
ロジクール ウェブカメラ C270
実装
以下をインストール
pip install opencv-python
pip install flask
pip install gevent
pip install gevent-websocket
ディレクトリ構成
├ main.py
├ templates/
├ index.html
サーバー : main.py
カメラとの接続は, これでいけます.
引数で繋いでるカメラを指定するみたいです. 1台しか繋いでないなら0で大丈夫なはずです.
# usbbカメラと接続
capture = cv2.VideoCapture(0)
カメラからフレームを読み込みます. frameが画像データです.
et, frame = capture.read() # カメラからフレーム読みこみ
画像jpgに変換. encimgが画像データです.
90は圧縮率です. 1-100で指定します. 低いほど高圧縮.
# jpgにエンコードするときのパラメーター
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
result, encimg = cv2.imencode('.jpg', frame, encode_param) #jpgに変換
プログラム全体
import cv2
import base64
from flask import Flask, request, render_template
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
app = Flask(__name__)
# usbカメラと接続
capture = cv2.VideoCapture(0)
# jpgにエンコードするときのパラメーター
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
@app.route('/')
def index():
return render_template('index.html')
@app.route('/live')
def live():
if request.environ.get('wsgi.websocket'):
ws = request.environ['wsgi.websocket']
while True:
ret, frame = capture.read() # カメラから画像読みこみ
result, encimg = cv2.imencode('.jpg', frame, encode_param) #jpgに変換
ws.send(base64.b64encode(encimg).decode('ascii')) # webbsocketでbase64に変換したjpg画像を送信
def main():
app.debug = True
server = pywsgi.WSGIServer(("", 8080), app, handler_class=WebSocketHandler)
server.serve_forever()
if __name__ == '__main__':
main()
フロント : index.html
受け取ったら画像を更新するようにするだけです.
<html>
<head>
<title>●REC</title>
</head>
<body>
<img id="player" src=""/>
<script>
const ws = new WebSocket("wss://localhost/live");
const player = document.getElementById("player");
# 受取時の処理
ws.onmessage = function(e) {
player.setAttribute("src", "data:image/jpg;base64,"+e.data)
}
</script>
</body>
</html>
ここまでできればlocalhost:8080にアクセスすれば画像が表示されるはずです.
Nginx
nginxのconfです.
server{
listen 80;
server_name hostname;
return 301 https://$host$request_uri;
}
server{
listen 443 ssl;
client_max_body_size 500M;
server_name hostname;
ssl_certificate cert.pem;
ssl_certificate_key privkey.pem;
location / {
proxy_pass http://localhost:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
}
}
おわりに
参考
FlaskとWebSocketを使用してリアルタイム通信を行う
OpenCV3をPython3で動かす。画像データ分析入門の為の下準備。