前回は、Webページをローカルで作成して、そこからブラウザに表示させていたのですが、
今回はWebページをラズパイに設置して、ブラウザからラズパイにアクセスすることによってプレビュー画面を表示させたいと思います。
動作はURLのパスによって変えます。
パスが”/”ならば、Webページを、”/Streaming”ならカメラの画像を返すようにします。
まず、Pythonのコードはこうなりました。
import base64
import cv2
import json
import os
import sys
import time
import threading
from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
from http import HTTPStatus
from urllib.parse import urlparse
PORT = 8000
cap = cv2.VideoCapture(0)
def __main__():
thread = threading.Thread(target=httpServe)
thread.start()
try:
while cap.isOpened():
time.sleep(1)
except KeyboardInterrupt:
return
def httpServe():
handler = StubHttpRequestHandler
httpd = HTTPServer(('',PORT),handler)
httpd.serve_forever()
class StubHttpRequestHandler(BaseHTTPRequestHandler):
server_version = "HTTP Stub/0.1"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def do_GET(self):
parsed = urlparse(self.path)
if parsed.path == '/Streaming':
enc = sys.getfilesystemencoding()
_, img = cap.read()
resized_img = cv2.resize(img, (480, 320))
_, encoded_img = cv2.imencode('.jpg', resized_img, [int(cv2.IMWRITE_JPEG_QUALITY), 30])
dst_base64 = base64.b64encode(encoded_img).decode('utf-8')
data = {
'image': 'data:image/jpg;base64,' + dst_base64
}
encoded = json.dumps(data).encode()
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", "text/html; charset=%s" % enc)
self.send_header("Access-Control-Allow-Origin", "null")
self.send_header("Content-Length", str(len(encoded)))
self.end_headers()
self.wfile.write(encoded)
elif parsed.path == '/vue.min.js':
self.send_response(HTTPStatus.OK)
with open('vue.min.js',mode='br') as f:
data = f.read()
self.send_header("Content-type", "text/javascript")
self.end_headers()
self.wfile.write(bytes(data))
elif parsed.path == '/jquery-3.5.1.slim.min.js':
self.send_response(HTTPStatus.OK)
with open('jquery-3.5.1.slim.min.js',mode='br') as f:
data = f.read()
self.send_header("Content-type", "text/javascript")
self.end_headers()
self.wfile.write(bytes(data))
else:
self.send_response(HTTPStatus.OK)
with open('index.html',mode='br') as f:
data = f.read()
self.send_header("Content-type", "text/html; charset=utf-8")
self.end_headers()
self.wfile.write(bytes(data))
__main__()
無駄にでかくなった気がする。
というのも、使用しているjsファイルもラズパイからGETしようとブラウザが動くので、jsファイルを送るように作成しないといけないのです。
めんどくさいから、他のライブラリを使用することも考えないといかんなぁ。
続いて、html側。
こちらはそんなに難しくはない。
URLを変えるだけなので。
<!DOCTYPE html>
<html>
<head>
<title>My first Vue app</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="vue.min.js"></script>
<script src="jquery-3.5.1.slim.min.js"></script>
</head>
<body>
<div id="app">
<image id="camera" src="" />
</div>
<script>
var app = new Vue({
el: '#app',
data: {
timer: null,
},
created: function() {
self = this;
this.timer = setInterval(function() {self.onLoad()}, 50)
},
methods: {
onLoad: function() {
axios.get('http://pi4.local:8000/Streaming').then(function(response){
$("#camera").attr('src', response.data.image);
}).catch(function(error){
});
}
}
})
</script>
</body>
</html>
これで動作しました。
「【ラズパイ】【カメラ】プレビュー画面をラズパイから取得・表示」への1件のフィードバック