OpenCV 无法在生产服务器上捕获帧 (Nginx + uWSGI) [英] OpenCV can't capture frames on production server (Nginx + uWSGI)

查看:49
本文介绍了OpenCV 无法在生产服务器上捕获帧 (Nginx + uWSGI)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 Raspberry Pi 4 上构建生产服务器.Web 应用程序是用 Django 编写的.我使用 uWSGI 作为应用服务器,使用 Nginx 作为反向代理.我遵循了 数字海洋.其中一项任务是从连接到 RPi 的 USB 相机流式传输帧.我的灵感来自 post 来自 PyImageSearch,但我想在 Django 中做到这一点.我的 OpenCV 版本是 4.5.2.

I'm building a production server on Raspberry Pi 4. Web app is written in Django. I used uWSGI as an application server and Nginx as a reverse proxy. I followed many tips from Digital Ocean. One of the tasks is to stream frames from USB camera connected to RPi. My inspirations was post from PyImageSearch, but I wanted to do it in Django. My OpenCV version is 4.5.2.

  1. 负责打开相机的类如下所示:

# views.py

class VideoCamera(object):
    def __init__(self):
        self.video = cv2.VideoCapture(0)
        (self.grabbed, self.frame) = self.video.read()
        if not self.grabbed:
            print("Can't open camera")
        threading.Thread(target=self.update, args=()).start()

    def __del__(self):
        self.video.release()

    def get_frame(self):
        image = self.frame
        _, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

    def update(self):
        while True:
            (self.grabbed, self.frame) = self.video.read()

  1. 这段代码在我的笔记本电脑和 RPi 4 上都可以正常工作,但只能在 Django 的开发服务器上运行.在生产服务器(Nginx + uWSGI)上运行后,我在 sudo systemctl status uwsgi 后收到以下消息:
  1. This code works fine both on my laptop and on RPi 4, but only on development server of Django. After running on production server (Nginx + uWSGI) I get following message after sudo systemctl status uwsgi:

uwsgi.service - uWSGI Emperor service
   Loaded: loaded (/etc/systemd/system/uwsgi.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2021-05-21 10:12:09 CEST; 58min ago
  Process: 371 ExecStartPre=/bin/bash -c mkdir -p /run/uwsgi; chown pi:video /run/uwsgi (code=exited, status=0/SUCCESS)
 Main PID: 428 (uwsgi)
   Status: "The Emperor is governing 1 vassals"
    Tasks: 13 (limit: 4915)
   CGroup: /system.slice/uwsgi.service
           ├─428 /home/pi/HomeGuard/my_env/bin/uwsgi --emperor /etc/uwsgi/sites
           ├─502 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─560 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─561 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─562 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─563 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─564 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─565 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─566 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─567 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           ├─568 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini
           └─569 /home/pi/HomeGuard/my_env/bin/uwsgi --ini homeguard.ini

May 21 11:07:07 raspberrypi uwsgi[428]: Can't open camera
May 21 11:07:07 raspberrypi uwsgi[428]: Traceback (most recent call last):
May 21 11:07:07 raspberrypi uwsgi[428]:   File "/home/pi/HomeGuard/my_env/lib/python3.7/site-packages/django/utils/text.py", line 300, in compress_sequence
May 21 11:07:07 raspberrypi uwsgi[428]:     for item in sequence:
May 21 11:07:07 raspberrypi uwsgi[428]:   File "/home/pi/HomeGuard/vision/views.py", line 36, in gen
May 21 11:07:07 raspberrypi uwsgi[428]:     frame = camera.get_frame()
May 21 11:07:07 raspberrypi uwsgi[428]:   File "/home/pi/HomeGuard/vision/views.py", line 26, in get_frame
May 21 11:07:07 raspberrypi uwsgi[428]:     _, jpeg = cv2.imencode('.jpg', image)
May 21 11:07:07 raspberrypi uwsgi[428]: cv2.error: OpenCV(4.5.2) /home/pi/opencv/modules/imgcodecs/src/loadsave.cpp:896: error: (-215:Assertion failed) !image.empty() in function 'imencode'
May 21 11:07:07 raspberrypi uwsgi[428]: [pid: 562|app: 0|req: 3/5] 192.168.178.43 () {42 vars in 761 bytes} [Fri May 21 09:07:05 2021] GET /vision/camera-usb-streaming/ => generated 10 bytes in 2034 msecs

  1. 相机无法开始工作,可能是由于某些权限问题.要使用相机给定的用户应该是视频"组的一部分.我将用户pi"和www-data"添加到视频"组.

  1. Camera can't start to work, probably due to some permissions problem. To use camera given user should be part of the 'video' group. I added users 'pi' and 'www-data' to the 'video' group.

我的 uWSGI 配置文件 (homeguard.ini) 如下所示:

My uWSGI configuration file (homeguard.ini) looks as follows:

[uwsgi]

# Django-related settings
project = homeguard

# user
uid = pi
# the base directory (full path)
base = /home/pi/HomeGuard
chdir = %(base)

# the virtualenv (full path)
home = %(base)/my_env
virtualenv = %(home)
pythonpath = %(base)
env = DJANGO_SETTINGS_MODULE=homeguard.settings

# Django's wsgi file
module = %(project).wsgi:application

# process-related settings
# master
master          = true

# maximum number of worker processes
processes       = 10

# the socket (use the full path to be safe
socket = /run/uwsgi/%(project).sock

# ... with appropriate permissions - may be needed
chown-socket = %(uid):video
chmod-socket = 777
enable-threads = true
# clear environment on exit

vacuum          = true

我设置777只是为了检查是否有问题,但没有帮助,稍后我会更改.

I set 777 only to check if it was a problem, but it didn't help, and I will change it later.

  1. 套接字权限:

ls -l /run/uwsgi/
srwxrwxrwx 1 pi video 0 May 21 10:12 homeguard.sock

  1. 我的 Nginx 配置如下所示:

# configuration of the server
server {
    # the port your site will be served on
    listen 80;
    # the domain name it will serve for
    server_name raspberrypi.local; #substitute your machine's IP address or FQDN
    location = /favicon.ico { access_log off; log_not_found off; }
    charset utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media/  {
        alias /home/pi/HomeGuard/media/;  # your Django project's media files - amend as required
    }

    location /static/ {
        alias /home/pi/HomeGuard/static/; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  unix:/run/uwsgi/homeguard.sock;
        include     uwsgi_params; # the uwsgi_params file you installed
    }
}

  1. 我的 uwsgi.service 文件如下所示:

[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown pi:video /run/uwsgi'
ExecStart=/home/pi/HomeGuard/my_env/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

  1. 运行sudo journalctl -u uwsgi命令后,日志如下:
  1. After running sudo journalctl -u uwsgi command, the log is as follows:

May 21 10:12:08 raspberrypi systemd[1]: Starting uWSGI Emperor service...
May 21 10:12:09 raspberrypi uwsgi[428]: *** Starting uWSGI 2.0.19.1 (32bit) on [Fri May 21 10:12:09 2021] ***
May 21 10:12:09 raspberrypi uwsgi[428]: compiled with version: 8.3.0 on 17 June 2020 09:19:11
May 21 10:12:09 raspberrypi uwsgi[428]: os: Linux-5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021
May 21 10:12:09 raspberrypi uwsgi[428]: nodename: raspberrypi
May 21 10:12:09 raspberrypi uwsgi[428]: machine: armv7l
May 21 10:12:09 raspberrypi uwsgi[428]: clock source: unix
May 21 10:12:09 raspberrypi uwsgi[428]: pcre jit disabled
May 21 10:12:09 raspberrypi uwsgi[428]: detected number of CPU cores: 4
May 21 10:12:09 raspberrypi uwsgi[428]: current working directory: /
May 21 10:12:09 raspberrypi uwsgi[428]: detected binary path: /home/pi/HomeGuard/my_env/bin/uwsgi
May 21 10:12:09 raspberrypi uwsgi[428]: uWSGI running as root, you can use --uid/--gid/--chroot options
May 21 10:12:09 raspberrypi uwsgi[428]: *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
May 21 10:12:09 raspberrypi uwsgi[428]: *** WARNING: you are running uWSGI without its master process manager ***
May 21 10:12:09 raspberrypi uwsgi[428]: your processes number limit is 60527
May 21 10:12:09 raspberrypi uwsgi[428]: your memory page size is 4096 bytes
May 21 10:12:09 raspberrypi uwsgi[428]: detected max file descriptor number: 1024
May 21 10:12:09 raspberrypi systemd[1]: Started uWSGI Emperor service.
May 21 10:12:09 raspberrypi uwsgi[428]: *** starting uWSGI Emperor ***
May 21 10:12:09 raspberrypi uwsgi[428]: *** has_emperor mode detected (fd: 7) ***
May 21 10:12:09 raspberrypi uwsgi[428]: [uWSGI] getting INI configuration from homeguard.ini
May 21 10:12:09 raspberrypi uwsgi[428]: *** Starting uWSGI 2.0.19.1 (32bit) on [Fri May 21 10:12:09 2021] ***
May 21 10:12:09 raspberrypi uwsgi[428]: compiled with version: 8.3.0 on 17 June 2020 09:19:11
May 21 10:12:09 raspberrypi uwsgi[428]: os: Linux-5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021
May 21 10:12:09 raspberrypi uwsgi[428]: nodename: raspberrypi
May 21 10:12:09 raspberrypi uwsgi[428]: machine: armv7l
May 21 10:12:09 raspberrypi uwsgi[428]: clock source: unix
May 21 10:12:09 raspberrypi uwsgi[428]: pcre jit disabled
May 21 10:12:09 raspberrypi uwsgi[428]: detected number of CPU cores: 4
May 21 10:12:09 raspberrypi uwsgi[428]: current working directory: /etc/uwsgi/sites
May 21 10:12:09 raspberrypi uwsgi[428]: detected binary path: /home/pi/HomeGuard/my_env/bin/uwsgi
May 21 10:12:09 raspberrypi uwsgi[428]: chdir() to /home/pi/HomeGuard
May 21 10:12:09 raspberrypi uwsgi[428]: your processes number limit is 60527
May 21 10:12:09 raspberrypi uwsgi[428]: your memory page size is 4096 bytes
May 21 10:12:09 raspberrypi uwsgi[428]: detected max file descriptor number: 1024
May 21 10:12:09 raspberrypi uwsgi[428]: lock engine: pthread robust mutexes
May 21 10:12:09 raspberrypi uwsgi[428]: thunder lock: disabled (you can enable it with --thunder-lock)
May 21 10:12:09 raspberrypi uwsgi[428]: uwsgi socket 0 bound to UNIX address /run/uwsgi/homeguard.sock fd 3
May 21 10:12:09 raspberrypi uwsgi[428]: setuid() to 1000
May 21 10:12:09 raspberrypi uwsgi[428]: Python version: 3.7.3 (default, Jan 22 2021, 20:04:44)  [GCC 8.3.0]
May 21 10:12:09 raspberrypi uwsgi[428]: PEP 405 virtualenv detected: /home/pi/HomeGuard/my_env
May 21 10:12:09 raspberrypi uwsgi[428]: Set PythonHome to /home/pi/HomeGuard/my_env
May 21 10:12:10 raspberrypi uwsgi[428]: Python main interpreter initialized at 0xcb8f20
May 21 10:12:10 raspberrypi uwsgi[428]: python threads support enabled
May 21 10:12:10 raspberrypi uwsgi[428]: your server socket listen backlog is limited to 100 connections
May 21 10:12:10 raspberrypi uwsgi[428]: your mercy for graceful operations on workers is 60 seconds
May 21 10:12:10 raspberrypi uwsgi[428]: mapped 708488 bytes (691 KB) for 10 cores
May 21 10:12:10 raspberrypi uwsgi[428]: *** Operational MODE: preforking ***
May 21 10:12:10 raspberrypi uwsgi[428]: added /home/pi/HomeGuard/ to pythonpath.
May 21 10:12:12 raspberrypi uwsgi[428]: WSGI app 0 (mountpoint='') ready in 2 seconds on interpreter 0xcb8f20 pid: 502 (default $
May 21 10:12:12 raspberrypi uwsgi[428]: *** uWSGI is running in multiple interpreter mode ***
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI master process (pid: 502)
May 21 10:12:12 raspberrypi uwsgi[428]: Fri May 21 10:12:12 2021 - [emperor] vassal homeguard.ini has been spawned
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 1 (pid: 560, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 2 (pid: 561, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: Fri May 21 10:12:12 2021 - [emperor] vassal homeguard.ini is ready to accept requests
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 3 (pid: 562, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 4 (pid: 563, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 5 (pid: 564, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 6 (pid: 565, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 7 (pid: 566, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 8 (pid: 567, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 9 (pid: 568, cores: 1)
May 21 10:12:12 raspberrypi uwsgi[428]: spawned uWSGI worker 10 (pid: 569, cores: 1)
May 21 10:19:30 raspberrypi uwsgi[428]: [pid: 567|app: 0|req: 1/1] 192.168.178.43 () {40 vars in 639 bytes} [Fri May 21 08:19:26$
May 21 10:19:30 raspberrypi uwsgi[428]: announcing my loyalty to the Emperor...
May 21 10:19:30 raspberrypi uwsgi[428]: Fri May 21 10:19:30 2021 - [emperor] vassal homeguard.ini is now loyal
May 21 10:56:45 raspberrypi uwsgi[428]: [pid: 567|app: 0|req: 2/2] 192.168.178.43 () {40 vars in 639 bytes} [Fri May 21 08:56:45$
May 21 11:05:42 raspberrypi uwsgi[428]: [pid: 562|app: 0|req: 1/3] 192.168.178.43 () {40 vars in 639 bytes} [Fri May 21 09:05:41$
May 21 11:05:42 raspberrypi uwsgi[428]: announcing my loyalty to the Emperor...
May 21 11:05:42 raspberrypi uwsgi[428]: Fri May 21 11:05:42 2021 - [emperor] vassal homeguard.ini is now loyal
May 21 11:07:04 raspberrypi uwsgi[428]: [pid: 562|app: 0|req: 2/4] 192.168.178.43 () {42 vars in 730 bytes} [Fri May 21 09:07:04$
May 21 11:07:05 raspberrypi uwsgi[428]: [ WARN:0] global /home/pi/opencv/modules/videoio/src/cap_v4l.cpp (890) open VIDEOIO(V4L2$
May 21 11:07:07 raspberrypi uwsgi[428]: Can't open camera
May 21 11:07:07 raspberrypi uwsgi[428]: Traceback (most recent call last):
May 21 11:07:07 raspberrypi uwsgi[428]:   File "/home/pi/HomeGuard/my_env/lib/python3.7/site-packages/django/utils/text.py", lin$
May 21 11:07:07 raspberrypi uwsgi[428]:     for item in sequence:
May 21 11:07:07 raspberrypi uwsgi[428]:   File "/home/pi/HomeGuard/vision/views.py", line 36, in gen
May 21 11:07:07 raspberrypi uwsgi[428]:     frame = camera.get_frame()
May 21 11:07:07 raspberrypi uwsgi[428]:   File "/home/pi/HomeGuard/vision/views.py", line 26, in get_frame
May 21 11:07:07 raspberrypi uwsgi[428]:     _, jpeg = cv2.imencode('.jpg', image)
May 21 11:07:07 raspberrypi uwsgi[428]: cv2.error: OpenCV(4.5.2) /home/pi/opencv/modules/imgcodecs/src/loadsave.cpp:896: error: $
May 21 11:07:07 raspberrypi uwsgi[428]: [pid: 562|app: 0|req: 3/5] 192.168.178.43 () {42 vars in 761 bytes} [Fri May 21 09:07:05$

  1. 在系统中看到摄像头:

bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12

bcm2835-isp (platform:bcm2835-isp):
        /dev/video13
        /dev/video14
        /dev/video15
        /dev/video16

C922 Pro Stream Webcam (usb-0000:01:00.0-1.3):
        /dev/video0
        /dev/video1

  1. 我的项目目录的权限:

drwxr-xr-x 11 pi video 4096 May 16 19:49 HomeGuard

  1. 当我使用子进程"模块运行 shell 命令v4l2-ctl --list-devices"时,我得到:

CompletedProcess(args=['v4l2-ctl', '--list-devices'], returncode=1, stdout=b'', stderr=b'Failed to open /dev/video0: Permission denied\n')

所以它必须是有权限的东西.

So it must be something with permissions.

推荐答案

我决定使用以下标志重新编译 OpenCV:

I decided to re-compile OpenCV with the following flags:

cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
    -D WITH_TBB=ON \
    -D WITH_V4L=ON \
    -D WITH_FFMPEG=ON \
    -D WITH_GSTREAMER=ON \
    -D ENABLE_VFPV3=ON \
    -D WITH_QT=ON \
    -D WITH_OPENGL=ON \
    -D BUILD_TESTS=OFF \
    -D INSTALL_PYTHON_EXAMPLES=OFF \
    -D OPENCV_ENABLE_NONFREE=ON \
    -D CMAKE_SHARED_LINKER_FLAGS=-latomic \
    -D BUILD_EXAMPLES=OFF ..

与以前的编译相比,唯一的区别是两个标志:WITH_FFMPEG=ON 和 WITH_GTSTREAMER=ON.
根据 documentation 这些标志默认开启,但我没有'没有安装'gstreamer'.我还使用了来自 Learn OpenCV 教程关于在 RPi 4 上安装 OpenCV 的一些说明(第 2 步):

The only difference comparing to previous compilations are two flags: WITH_FFMPEG=ON and WITH_GTSTREAMER=ON.
According to documentation these flags are switched ON by default, but I didn't have 'gstreamer' installed. I also used few instruction from Learn OpenCV tutorial on instalation OpenCV on RPi 4 (Step 2):

sudo apt-get -y install libxine2-dev libv4l-dev  
cd /usr/include/linux  
sudo ln -s -f ../libv4l1-videodev.h videodev.h  

现在可以了:)

这篇关于OpenCV 无法在生产服务器上捕获帧 (Nginx + uWSGI)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆