树莓派利用Picamera2和HTTP 搭建局域网摄像头图传 简单web程序示例

        由于项目需要需要将树莓派摄像头捕获的图像通过局域网传输给PC上位机做图像处理。之前使用过mjpg-stream进行图像传输但由于树莓派系统更新较难应用并且传输分辨率有所限制。通过查阅Picamera2手册发现官方有该应用示例代码,清晰度低延迟性能都很好分享给大家。

import io
import logging
import socketserver

from http import server
from threading import Condition
from picamera2.encoders import Quality
from picamera2 import Picamera2
from picamera2.encoders import JpegEncoder
from picamera2.outputs import FileOutput

PAGE = """\
<html>
<head>
<title>picamera2 MJPEG streaming demo</title>
</head>
<body>
<h1>Picamera2 MJPEG Streaming Demo</h1>
<img src="stream.mjpg" width="3280" height="2464" />
</body>
</html>
"""

class StreamingOutput(io.BufferedIOBase):
    def __init__(self):
        self.frame = None
        # 定义Condtion 用于线程同步
        self.condition = Condition()

    def write(self, buf):
        with self.condition:

            self.frame = buf
            # 唤醒其余被阻塞线程
            self.condition.notify_all()

# 定义 StreamingHandler处理类 继承server.BaseHTTPRequestHandler
class StreamingHandler(server.BaseHTTPRequestHandler):
    # 定义do_GET 方法用于 处理GET请求
    def do_GET(self):

        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()

        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)

        # 访问192.168.137.100:8000/stream.mjpg 则尝试从output.frame中获取帧数据 并传输数据流到客户端
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                        # 如果分辨率小的话可以用 opencv 做一些图像处理功能frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

# 创建SteamingServer类  继承socketserver.ThreadingMixIn server.HTTPServer
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    # 允许服务器地址重用
    allow_reuse_address = True
    # 使用守护线程
    daemon_threads = True

# 初始化 Picamera2
picam2 = Picamera2()
# 设置相机为视频捕获模式 分辨率 设置为3240 2464
picam2.configure(picam2.create_video_configuration(main={"size": (3240, 2464)}))
# 定义编码器视频输出对象
output = StreamingOutput()
# 启动摄像头编码 jpeg格式 输出到output对象 输出质量最高
picam2.start_recording(JpegEncoder(), FileOutput(output),quality=Quality.VERY_HIGH)


try:
    #ip改为树莓派ip
    address = ('192.168.137.100', 8000)
    # 启动服务器 并监听指定地址请求 使用StreamingHandler来处理请求
    server = StreamingServer(address, StreamingHandler)
    server.serve_forever()
finally:
    # 关闭编码输出
    picam2.stop_recording()

 在浏览器输入ip:8000即可预览视频窗口,使用opencv可以打开相应视频流。

 

   cap.open("http://192.168.137.110:8000/stream.mjpg"); // 打开相机设备,0代表默认相机设备
   cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));

 示例代码链接:https://github.com/raspberrypi/picamera2/blob/main/tests/mjpeg_server.py

Picamera2 手册 picamera2-manual.pdf (raspberrypi.com) 

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值