【问题标题】:OpenCV can't capture frames on production server (Nginx + uWSGI)OpenCV 无法在生产服务器上捕获帧(Nginx + uWSGI)
【发布时间】:2021-05-28 18:11:29
【问题描述】:

我正在 Raspberry Pi 4 上构建生产服务器。Web 应用程序是用 Django 编写的。我使用 uWSGI 作为应用服务器,使用 Nginx 作为反向代理。我遵循了来自Digital Ocean 的许多提示。 其中一项任务是从连接到 RPi 的 USB 摄像头流式传输帧。我的灵感来自 PyImageSearch 的 post,但我想在 Django 中进行。我的 OpenCV 版本是 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 之后收到以下消息:
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”添加到“视频”组。

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

[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只是为了检查是否有问题,但没有帮助,我稍后会更改它。

  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命令后,日志如下:
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')

所以一定是有权限的东西。

【问题讨论】:

    标签: raspberry-pi uwsgi opencv-python


    【解决方案1】:

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

    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 tutorial on instalation OpenCV on RPi 4 的一些指令(第 2 步):

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

    现在它可以工作了:)

    【讨论】:

      猜你喜欢
      • 2019-06-28
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      相关资源
      最近更新 更多