本篇分享如何使用 Raspberry Pi 和 OpenCV + Flask 快速搭建簡易的影像串流 server,只用一份 py 檔實現土炮版的 IP cameras,就讓我們開始吧!
使用 OpenCV 擷取影像並壓縮
開一個空白檔案命名為 stream.py
,初始化 OpenCV
import cv2
cap = cv2.VideoCapture(0)
準備兩個 function,一個是 get_image_bytes()
,另一個是 resize_img_2_bytes()
from io import BytesIO
from PIL import Image
def resize_img_2_bytes(image, resize_factor, quality):
bytes_io = BytesIO()
img = Image.fromarray(image)
w, h = img.size
img.thumbnail((int(w * resize_factor), int(h * resize_factor)))
img.save(bytes_io, 'jpeg', quality=quality)
return bytes_io.getvalue()
def get_image_bytes():
success, img = cap.read()
if success:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_bytes = resize_img_2_bytes(img, resize_factor=0.5, quality=30)
return img_bytes
return None
其中做的事情如下:
- 首先
get_image_bytes()
從 camera 擷取一張影像 - 如果成功的話,先將編碼轉成 RGB(OpenCV 預設是 BGR,直接輸出成圖片顏色會很奇怪)
- 呼叫
resize_img_2_bytes()
壓縮圖片 - PIL 先將 image nparray 讀入後,使用
thumbail
api 縮小圖片 - 透過
BytesIO
作為中介,將 PIL image 壓縮儲存成 jpeg 回傳 - 最後
get_image_bytes()
將結果丟出去
使用 Flask 搭建簡易 Webserver
首先初始化 Flask,給定 template folder,因為我們需要 Flask 幫忙 render template
from flask import Flask, render_template, Response
app = Flask(
__name__,
static_url_path='',
static_folder='./',
template_folder='./',
)
寫一個 function 當進入網站時,render template
@app.route("/", methods=['GET'])
def get_stream_html():
return render_template('stream.html')
另外實作一個 api,從剛剛寫好的 get_image_bytes()
讀取資料,不斷丟到 Response
裡,瀏覽器就能刷新 img
,實現直播的畫面
def gen_frames():
while True:
img_bytes = get_image_bytes()
if img_bytes:
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + img_bytes + b'\r\n')
@app.route('/api/stream')
def video_stream():
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
最後簡單使用 app.run()
啟動 webserver
if __name__ == "__main__":
app.run(host='0.0.0.0')
別忘了準備 template html file,命名為 stream.html
並放在 py 檔同層目錄中
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="grid-cols-8">
<h3 class="text-4xl text-center m-11">Live Streaming</h3>
<img src="{{ url_for('video_stream') }}" width="100%">
</div>
</div>
</div>
</body>
</html>
啟動 Stream Server
用以下指令啟動
python stream.py
會看到 Flask 的警告,不過沒關係,只是簡單土炮,web server 還是可以正常使用
用瀏覽器開啟 http://<raspberry_pi_ip>:5000
,就會看到串流的畫面了
眼尖的朋友會發現我跑在 mac 上做截圖XD,其實只要有視訊鏡頭的裝置都可以用這份 py 檔來實現即時串流!
範例原始碼在此下載:github
延伸閱讀:
用 MotionEye + Raspberry pi 做一個網路監控系統吧!
使用 Face Recognition 套件快速建立自己的人臉辨識系統!
如何在 Jetson Nano 上安裝 OpenCV?
參考資料:Video Streaming in Web Browsers with OpenCV & Flask