我理解的实时视频监控,是利用树莓派的摄像头采集到的视频流通过无线或有线传输实现一个远程的观看。

摄像头型号传输方式
USB、官方摄像头motion、mjpg-streamer、python(Picamera+socket)

1. 硬件设备

USB和官方摄像头属性上的差别我觉得是官方摄像头是采用一个特殊的转接线(CSI(Camera Serial Interface))与树莓派进行连接。
官方转接线的摄像头需要现在树莓派配置上打开摄像头功能,而USB摄像头插上即用,在这里也说明摄像头的启用。

  • USB摄像头
    将USB摄像头插入树莓派;
    lsusb查看USB摄像头,找打相应的摄像头型号,此处的是罗技摄像头;

    046d:0825 Logitech, Inc. Webvam C270
    
  • 官方转接线摄像头
    将摄像头转接线连上树莓派,那个卡槽可以往上掰开的,不要大力出奇迹了;
    打开树莓派的摄像头功能:sudo raspi-config,然后依次选择5 Interfacing Options,进入之后选择P1 Camera,然后在 Would you like the camera interface to be enabled? 对话框上选择 Yes 。最后通过 Finish 退出,并重启树莓派;
    检验摄像头是否启用:在终端输入raspistill -o test.jpg,如果成功则在主文件夹下有该图片。

2. 软件方法

方法说明
motion较为简单,但是很耗CPU,相对延迟,有存储功能
mjpg-streamer相对motion速度较快,没有找到存储目录。更加推荐这个,在速度上比比python实现更快,也包含相应的参数配置,在/plugins/input_raspicam文件夹下,后期补充其详细配置,堪比第三种方法。
python(Picamera+socket)http.server编程

2.1. motion

我尝试过用无论是USB还是官方转接线的摄像头motion都可以实现。

motion 是一款开源的支持多种摄像头的监控软件。

如果不是第一次配置,可直接跳到第四步,即一些配置步骤只需要执行一次即可。
第一步:安装motion

$sudo apt-get update
$sudo apt-get install motion

第二步:接上摄像头
如上所示。

第三步:配置motion
配置/etc/motion/motion.conf文件和/etc/default/motion文件

查看他的配置:树莓派+motion实现局域网简单监控

  • /etc/default/motion文件:

    //启动后台的守护进程
    start_motion_daemon=yes			
    
  • /etc/motion/motion.conf文件:

    //让Motion作为守护进程运行
    daemon on 	
    ...
    //用这个端口号来读取数据
    stream_port 8081
    ...
    //网络上其它主机也可以看到
    stream_localhost off
    ...
    //帧速率为每秒30帧
    stream_maxrate 30
    ...
    //摄像头捕捉视频的帧速率为每秒30
    framerate 30
    

其他一些重要的配置进行介绍。
(1)target_dir:该选项的默认值为/var/lib/motion。这就是Motion存储动作捕捉结果的地方。Motion的进程是以用户motion的身份运行的,所以用户motion必须对该目标文件夹有写入权限。
(2)threshold:动作捕捉阈值,默认值为1500。如果有超过阈值的像素点发生变化,那么认为有动作发生。
(3)videodevice:该项默认为路径/dev/video0。这个路径对应了默认的视频设备。如果你无法在/dev下找到video0,那么可以尝试加载V4L2驱动来解决问题:

$sudo rpi-update 
$sudo modprobe bcm2835-v412

第四步:开启服务

$sudo service motion start
$sudo motion

第五步:主机查看
在另一条能ping通的计算机上,输入“http://树莓派IP地址:8081/",就能看到摄像头的信息啦,信息存储在/var/lib/motion之下。
第五步:终止服务

$sudo service motion stop

参考链接:树莓派(四):使用摄像头实现拍照和远程监控功能

2.2. LJPG-streamer

MJPG-streamer是一个优秀的开源project,它可以通过HTTP的方式访问linux上面的兼容摄像头,从而做到远程视频传输的效果。

其实现步骤大致需要先安装mjpg-streamer依赖的库,再从github上下载源码进行编译,再尝试解决官方摄像头启动失败的问题。前提为树莓派上已连接摄像头并且能够开启。
第一步:安装必要的库

$sudo apt-get update
$sudo apt-get install subversion
$sudo apt-get install libjpeg8-dev
$sudo apt-get install imagemagick
$sudo apt-get install libv4l-dev

第二步:下载源码、修改配置并编译
下载源码(方式二选一即可):

// 方法一:采用git方式
$sudo apt-get install git
$sudo git clone https://github.com/jacksonliam/mjpg-streamer.git
// 方法二:采用wget方式
$wget http://github.com/jacksonliam/mjpg-streamer/archive/master.zip
$sudo apt-get install unzip
$unzip master.zip
// 方法三:直接从官网下载压缩包,然后解压
$sudo apt-get install unzip
$unzip mjpg-streamer-master.zip

编辑配置文件(可选,我没有进行配置):

$cd mjpg-streamer-master/mjpg-streamer-experimental
$vim plugins/input_raspicam/input_raspicam.c

编译(在mjpg-streamer-master/mjpg-streamer-experimental路径下):

$sudo apt-get install cmake
$sudo apt-get install gcc g++
$make all
$sudo make install

第三步:尝试开启服务
使用下面指令启动普通USB摄像头:

./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so -w ./www"

启动树莓派专用摄像头RaspiCamera的指令是:

./mjpg_streamer -i "./input_raspicam.so" -o "./output_http.so -w ./www"

某些摄像头在执行这个指令时会有报错,至少要是最后没有退回到命令行提示符:
在这里插入图片描述

第四步:查看图像
查看图像,在PC端打开浏览器,输入下面网址可以看到静态截图:
http://<树莓派IP>:8080/?action=snapshot

输入下面两条网址可以看到动态图像(至于为什么端口号是8080在树莓派上运行后有相关的提示,至于为什么加"?action=stream",在进入http://raspberry-ip-address:8080是一个网址,"?action=stream"专门存放视频):
http://raspberry-ip-address:8080/?action=stream

动态图像的这个地址在有的浏览器不太好使,可以使用下面这个网址:
http://raspberry-ip-address:8080/javascript_simple.html
第五步:退出
ctrl+c or ctrl+d

参考链接:
「玩转树莓派」搭建智能家居远程监控系统
树莓派上MJPG-streamer的安装过程
Raspberry pi 記錄3-關於Pi Camera和即時串流(MJPG Stream Server)
树莓派新版系统上使用mjpg-streamer获取USB摄像头和树莓派专用摄像头RaspiCamera图像
mjpg-streamer

2.3. python(Picamera+socket)

树莓派上python的编程环境

应用说明
Python3(IDLE)一个Python Shell,不适合大型代码。
Thonny Python IDEmini版pycharm,有Python Shell和代码书写区域
Visual Studio Code

树莓派上运行python文件

方法说明
方法一sudo python3 xxx.py(sudo可选)
方法二在程序开头加入#!/user/bin/python3
# !/user/bin/python3
# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
<head>
<title>Raspberry Pi - Surveillance Camera</title>
</head>
<body>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="640" height="480"></center>
</body>
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    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)
        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
                    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()

# 绑定IP端口,使用HTTPServer来处理HTTP请求, ThreadingMinIn处理socket请求
class StreamingServer(server.HTTPServer, server.BaseHTTPRequestHandler):
    allow_reuse_address = True
    daemon_threads = True


def camera_config(camera):
    camera.resolution = (640, 480)
    camera.framerate = 25
    camera.video_stabilization = True  # 打开视频稳定功能
    camera.brightness = 55
    camera.contrast = -5
    camera.awb_mode = 'auto'
    camera.ISO = 400
    return camera
    
    
with picamera.PiCamera() as camera:
    camera = camera_config(camera)
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()
        

在树莓派终端输入:python3 ~/swift/rpi.python
此时监控系统以及开始工作了。局域网内的任何设备,打开浏览器地址栏输入 http://树莓派IP地址:8000,即可打开网络监控系统。视频响应的延时取决于你的树莓派和路由器的性能。
参考链接
用树莓派搭建一个实时视频监控系统
树莓派PiCamera库的基本使用

Logo

致力于链接即构和开发者,提供实时互动和元宇宙领域的前沿洞察、技术分享和丰富的开发者活动,共建实时互动世界。

更多推荐