建立 MJPEG 即时图像串流
这篇教学会介绍 False 与 mjpeg-streamer 两种建立 MJPEG 即时图像串流的方法,让电脑摄影机变成远端摄影机,使用类似 CCTV 监视器图像的方式传送 MJPEG 图像串流。
延伸参考:爬取交通部 CCTV 即时图像
快速导览:
认识 MJPEG 图像串流
MJPEG 或 Motion JPEG ( Motion Joint Photographic Experts Group ) 是一种图像压缩格式,可以将串流影片的每一帧压缩为 JPEG 图片进行传送,这种传输模式不仅大幅减少了数据传输量,更提高了解压缩的效率,这种图像串流的技术常用于物联网设备的摄影机、监视器、微控制器等应用情境,由于是传输 JPEG,因此传输过程中“无法传输声音”并会产生“失真压缩”。
MJPEG 的传输属于“多部分回应 Multipart Responses”,过程中每个影格都被独立压缩成 JPEG 格并以一个独立部分 ( part ) 的形式存在,Multipart Responses 使用 Content-Type 来传输数据,在 MJPEG 的情况下,Content-Type 通常是“
multipart/x-mixed-replace”,表示每个部分之间的分隔符号,用来区分不同的影格。
MJPEG 图像串流的结构如下:Content-Type 标头为“multipart/x-mixed-replace”并定义边界字串 boundary 为“frame”,接着每个部分以“--frame”为前缀,并具有自己的 Content-Type 标头。
HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=frame
--frame
Content-Type: image/jpeg
<jpeg data here>
--frame
Content-Type: image/jpeg
<jpeg data here>
...
用 Flask
了解 MJPEG 图像串流的结构之后,就能透过 Flask 搭配 OpenCV,建立可以即时传输串流图像的简单网页,首先安装 Flask 和 OpenCV。
pip install flask, opencv-python
使用下方的程序码,使用 Flask 建立一个简单的网页,当网页打开后,里面会放入一张路径为“/mjpeg”的图片,读取图片时,会发送另外一个 http request 执行 mjpeg 函数,函数内容根据上述的“多部分回应 Multipart Responses”结构,发送 MJPEG 的内容。
from flask import Flask, Response
import cv2, time
app = Flask(__name__)
def gen_frames():
cap = cv2.VideoCapture(0) # 開啟鏡頭
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) # 設定影像寬度 320
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) # 設定影像高度 240
while True:
ret, frame = cap.read() # 讀取影像
if not ret:
break
else:
jpg = cv2.imencode('.jpg', frame)[1] # 轉換成 jpg 陣列
mjpeg = jpg.tobytes() # 轉換成傳輸 bytes
# 使用 generator 的方式,每次傳輸特定每個部分
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + mjpeg + b'\r\n')
@app.route('/mjpeg')
def mjpeg():
# 回傳 Multipart Responses
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
return '''<h1>OXXO.STUDIO 影像串流</h1>
<img src="/mjpeg">'''
if __name__ == '__main__':
app.run("127.0.0.1", port=5000, threaded=True)
因此当网页打开后,网页中所加载的就会自动根据 MJPEG 发送对应的串流,不断显示每个部分的图像。
在网页上点击右键查看网页源代码,可以看出显示串流的 HTML 为一个 img 标签。
由于使用 Flask 是产生“内网”的网址,如果要透过外部连接查看图像串流,必须使用对外的 IP 或固定网址,也可以串接 nrgok 产生对外网址,详细参考:使用 ngrok 服务
使用 mjpeg-streamer
除了自己使用 Flask 架设网页服务器,也可以使用 mjpeg-streamer 软件包架设 MJPEG 的服务器 ( 常见于树莓派或一些单芯片装置使用,详细参考“mjpeg-streamer,首先输入指令安装 opencv-python mjpeg-streamer 软件包。
pip install opencv-python mjpeg-streamer --prefer-binary
执行下方程序码,就会在本机环境建立一个 MJPEG 专属的服务器,接着就能使用“http://xxx.xxx.xxx.xxx/mjpeg”打开串流图片,但这个做法只能产生串流图像,如果需要使用自己的网页样式呈现串流,则必须使用 Flask 的做法。
import cv2
from mjpeg_streamer import MjpegServer, Stream
cap = cv2.VideoCapture(0)
# 設定串流資訊,mjpeg 為圖片網址 size 尺寸 quality 品質 fps 幀率 ( 每秒幾格 )
stream = Stream("mjpeg", size=(640, 480), quality=50, fps=30)
server = MjpegServer("127.0.0.1", 5000) # 設定伺服器資訊
server.add_stream(stream) # 添加串流
server.start() # 啟動伺服器
while True:
ret, frame = cap.read() # 讀取影像
if not ret:
break
else:
stream.set_frame(frame) # 設定串流內容
小结
使用 Python 建置 MJPEG 的图像串流其实非常简单,只要熟悉操作原理,就可以自己在家里建立 IP CAM 摄影机,自己打造自己的监视器啰~
微信扫码关注
抖音扫码关注