树莓派+Flask实现远程拍照WEB服务器

发布时间:2024-03-05 08:01

组件:

  • Raspberry Pi 3B 1G
  • RMONCAM G180摄像头

环境:

  • Python:3.7.3
  • Flask:1.0.2
  • opencv-python:4.5.3.56

一、打开相机配置

打开你的树莓派并转到树莓派配置工具的主菜单上,并确认相机接口是否开启:
如果你需要开启它,请按[Enable]并重新启动你的树莓派。

\"树莓派+Flask实现远程拍照WEB服务器_第1张图片\"
\"树莓派+Flask实现远程拍照WEB服务器_第2张图片\"
做一个简单的测试来验证一切是否正常:
以下为 CSI摄像头测试

raspistill -o /Desktop/image.png

如果使用的是USB摄像头,则在树莓派终端输入 sudo apt-get install fswebcam 安装 fswebcam。通过输入sudo fswebcam image.jpg进行拍照测试。使用方法可以通过输入fswebcam -h查询。

安装 fswebcam

sudo apt-get install fswebcam

pi@raspberrypi:~/Desktop $ sudo apt-get install fswebcam
正在读取软件包列表… 完成
正在分析软件包的依赖关系树
正在读取状态信息… 完成
下列软件包是自动安装的并且现在不需要了:
gconf-service gconf2-common libgconf-2-4 python-colorzero
使用’sudo apt autoremove’来卸载它(它们)。
下列【新】软件包将被安装:
fswebcam
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 3 个软件包未被升级。
需要下载 43.5 kB 的归档。
解压缩后会消耗 116 kB 的额外空间。
获取:1 http://mirrors.aliyun.com/raspbian/raspbian buster/main armhf fswebcam armhf 20140113-2 [43.5 kB]
已下载 43.5 kB,耗时 0秒 (142 kB/s)
正在选中未选择的软件包 fswebcam。
(正在读取数据库 … 系统当前共安装有 177053 个文件和目录。)
准备解压 …/fswebcam_20140113-2_armhf.deb …
正在解压 fswebcam (20140113-2) …
正在设置 fswebcam (20140113-2) …
正在处理用于 man-db (2.8.5-2) 的触发器 …

测试 USB摄像头 拍照

sudo fswebcam image.jpg

pi@raspberrypi:~/Desktop $ sudo fswebcam image.jpg
— Opening /dev/video0…
Trying source module v4l2…
/dev/video0 opened.
No input was specified, using the first.
Adjusting resolution from 384x288 to 352x288.
— Capturing frame…
Captured frame in 0.00 seconds.
— Processing captured image…
Writing JPEG image to ‘image.jpg’.
pi@raspberrypi:~/Desktop $

如果拍照成功,在到你树莓派桌面上会出现一个图像图标。 点击打开它, 如果出现图像,则说明准备步骤已经完成。如果你想获得更多关于相机的信息,可点击 Getting started with picamera.。

fswebcam 常用参数
  • /dev/video0:指定摄像头操作设备

    通过输入以下命令可以查看可用的摄像头操作设备

    ls /dev/video*
    

    pi@raspberrypi:~/Desktop $ ls /dev/video*
    /dev/video0 /dev/video10 /dev/video12 /dev/video14 /dev/video16
    /dev/video1 /dev/video11 /dev/video13 /dev/video15

  • –no-banner:图片上隐藏横幅。

  • -r 640x480:设置图片分辨率 640x480,默认是352x288。

  • ./static/image.jpg:存储路径,当前用户目录下,保存为 image.jpg。

例如:

fswebcam /dev/video0 --no-banner -r 640x480 ./static/image.jpg 

二、安装FLASK

创建一个Flask Web服务器环境:
首先要做的是在你的树莓派上安装Flask,去终端并输入:

sudo apt-get install python3-flask

pi@raspberrypi:~/Desktop $ sudo apt-get install python3-flask
正在读取软件包列表… 完成
正在分析软件包的依赖关系树
正在读取状态信息… 完成
python3-flask 已经是最新版 (1.0.2-3)。
下列软件包是自动安装的并且现在不需要了:
gconf-service gconf2-common libgconf-2-4 python-colorzero
使用’sudo apt autoremove’来卸载它(它们)。
升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 3 个软件包未被升级。

在桌面新建文件夹

mkdir camWebServer

按照上面的命令,创建一个名为“camWebServer”的文件夹,并在这里保存我们的python脚本:

以下为 camWebServer文件夹 所在的路径位置。

/home/pi/Desktop/camWebServer

在这个camWebServer文件夹里,创建两个子文件夹:静态的CSS、最终的JavaScript文件以及HTML文件的模板。 转到你的新创建的文件夹:

cd camWebServer

并创建2个新的子文件夹:

mkdir static
mkdir templates

最终的目录“树”,如下所示:

├── Desktop
       ├── camWebServer
               ├── templates
               └── static

三、创建单线程视频流服务器

通过opencv 打开USB摄像头,并将摄像头拍到的画面显示在浏览器中。

安装 opencv-python 库

pip install opencv-python
app.py
from flask import Flask, render_template, Response
from camera import VideoCamera
 
app = Flask(__name__)
 
@app.route(\'/\')
def index():
    return render_template(\'index.html\')
 
def gen(camera):
    while True:
        frame = camera.get_frame()
        yield (b\'--frame\\r\\n\'
               b\'Content-Type: image/jpeg\\r\\n\\r\\n\' + frame + b\'\\r\\n\\r\\n\')
 
@app.route(\'/video_feed\')
def video_feed():
    return Response(gen(VideoCamera()),
                    mimetype=\'multipart/x-mixed-replace; boundary=frame\')
 
if __name__ == \'__main__\':
    app.run(host=\'0.0.0.0\', port=80, debug=True)
camera.py
import cv2
 
class VideoCamera(object):
    def __init__(self):
        # Using OpenCV to capture from device 0. If you have trouble capturing
        # from a webcam, comment the line below out and use a video file
        # instead.
        self.video = cv2.VideoCapture(0)
        # If you decide to use video.mp4, you must have this file in the folder
        # as the main.py.
        # self.video = cv2.VideoCapture(\'video.mp4\')
 
    def __del__(self):
        self.video.release()
 
    def get_frame(self):
        success, image = self.video.read()
        # We are using Motion JPEG, but OpenCV defaults to capture raw images,
        # so we must encode it into JPEG in order to correctly display the
        # video stream.
        ret, jpeg = cv2.imencode(\'.jpg\', image)
        # 对于 python2.7 或者低版本的 numpy 请使用 jpeg.tostring()
        return jpeg.tobytes()

将index.html文件存放到templates文件夹下:

<html>
  <head>
    <title>视频流title>
    <link rel=\"stylesheet\" href=\'../static/style.css\'/>
  head>
  <body>
    <h3><img src=\"{{ url_for(\'video_feed\') }}\" width=\"50%\">h3>
  body>
html>

将style.css文件存放到static文件夹下:

body{
	background: blue;
	color: yellow;
	padding:1%;
	text-align: center;
}

index.html最重要的一行是:

<img src=\"{{ url_for(\'video_feed\') }}\" width=\"50%\">

视频将会在这里“反馈”到我们的网页上。

确保所有的文件都在正确的位置,所有数据更新后,检查一下我们的环境:

├── Desktop
       ├── camWebServer
               ├── camera_pi.py
               ├── app.py
               ├── templates
               |     ├── index.html
               └── static
                     ├── style.css

现在,在终端上运行python脚本:

sudo python3 app.py

转到你的网络中的任何浏览器,并输入 http://树莓派的IP地址/video_feed

效果如下:

\"树莓派+Flask实现远程拍照WEB服务器_第3张图片\"

注意:如果你不能确定你的树莓派IP地址,请在你的终端上运行:

ifconfig

在wlan0:部分你会找到树莓派IP地址。

当多台电脑同时访问 http://树莓派的IP地址/video_feed 只有一个页面会显示画面,如果有需求可以加入多线程代码。

树莓派拍照服务器

通过cmd命令,实现访问拍照接口,将照片保存到项目的static文件夹中,然后通过 http://树莓派的IP地址/get_image 获取照片。

# main.py
from flask import Flask, render_template, Response, url_for, send_file
import cv2 
import time

app = Flask(__name__)
 
@app.route(\'/\')
def index():
    return render_template(\'index.html\')

def run_cmd( cmd_str=\'\', echo_print=1):
    \"\"\"
    执行cmd命令,不显示执行过程中弹出的黑框
    备注:subprocess.run()函数会将本来打印到cmd上的内容打印到python执行界面上,所以避免了出现cmd弹出框的问题
    :param cmd_str: 执行的cmd命令
    :return: 
    \"\"\"
    from subprocess import run
    if echo_print == 1:
        print(\'\\n执行cmd指令=\"{}\"\'.format(cmd_str))
    run(cmd_str, shell=True)

@app.route(\'/get_image\')
def get_image():
    run_cmd(\'sudo fswebcam ./static/images/test.jpg\')
    #return \"保存test.jpg成功!\"
    return send_file(\'./static/images/test.jpg\', mimetype=\'image/jpg\')


if __name__ == \'__main__\':
    app.run(host=\'0.0.0.0\', port=80, debug=True)

效果如下:

\"树莓派+Flask实现远程拍照WEB服务器_第4张图片\"

通过cmd命令,实现拍照,将照片保存到项目的static文件夹中,然后通过 http://树莓派的IP地址/get_image 获取照片。

test.html文件

DOCTYPE html>
<html lang=\"en\">
<head>
    <meta charset=\"UTF-8\">
    <title>Titletitle>
head>
<body>
    <img src=\"{{url_for(\'static\',filename=\'images/test.jpg\',_t=val1)}}\" alt=\"\">
body>
html>

app.py文件

# main.py
from flask import Flask, render_template, Response, url_for, send_file
import cv2 
import time

app = Flask(__name__)
 
@app.route(\'/\')
def index():
    return render_template(\'index.html\')

def run_cmd( cmd_str=\'\', echo_print=1):
    \"\"\"
    执行cmd命令,不显示执行过程中弹出的黑框
    备注:subprocess.run()函数会将本来打印到cmd上的内容打印到python执行界面上,所以避免了出现cmd弹出框的问题
    :param cmd_str: 执行的cmd命令
    :return: 
    \"\"\"
    from subprocess import run
    if echo_print == 1:
        print(\'\\n执行cmd指令=\"{}\"\'.format(cmd_str))
    run(cmd_str, shell=True)

@app.route(\'/get_image\')
def get_image():
    run_cmd(\'sudo fswebcam ./static/images/test.jpg\')
    #return \"保存test.jpg成功!\"
    return render_template(\"test.html\", val1=time.time())
    #return render_template(\"test.html\")


if __name__ == \'__main__\':
    app.run(host=\'0.0.0.0\', port=80, debug=True)

注:在网页中图片显示不能及时更新,由于缓存的问题,拍照存储的图片覆盖原有的图片,但是前端页面刷新还是以前的旧图。需要_t参数,使每次请求的数据不一样,才能刷新图片。

出现问题:

问题:

树莓派上可以找到摄像头驱动,但是在树莓派终端输入raspistill -o image.jpg,输出如下错误:

pi@raspberrypi:~/Desktop $ raspistill -o /Desktop/image.png
mmal: Cannot read camera info, keeping the defaults for OV5647
mmal: mmal_vc_component_create: failed to create component ‘vc.ril.camera’ (1:ENOMEM)
mmal: mmal_component_create_core: could not create component ‘vc.ril.camera’ (1)
mmal: Failed to create camera component
mmal: main: Failed to create camera component
mmal: Camera is not detected. Please check carefully the camera module is installed correctly

其原因为使用的摄像头为USB摄像头,而raspistill命令只能用于CSI摄像头。对于USB接口的摄像头,可以通过调用fswebcam进行访问。

参考:https://shumeipai.nxez.com/2018/07/03/video-streaming-web-server-with-flask.html

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号