Raspberry Pi - 自动启动OpenCv-Script - cv :: imshow()

时间:2017-11-21 11:16:11

标签: bash opencv raspberry-pi systemd autostart

简短说明:

我想在启动后通过systemd服务脚本自动启动可执行文件(opencv二进制文件,通过c ++生成),但我没有成功。

我将错误缩小到代码语句" cv :: imshow(....)"这会打开一个窗口并显示图像。此时,代码抛出错误:" QXcbConnection:无法连接到显示"

但是,如果我手动执行sh-script或二进制文件,两者都可以正常工作。我在stackoverflow周围搜索了最常见的错误,我试图修复我能找到的所有错误。我很确定,那:

  1. 我的服务文件实际上是在开始时运行(直到发生错误)
  2. 手动执行二进制文件可以正常工作
  3. 手动执行.sh脚本正常
  4. 我没有运行时链接错误(请参阅.sh-script)
  5. 我将不胜感激任何帮助。请帮我修复错误,请向我解释为什么这个错误甚至首先发生。非常感谢:)

    我的系统:

    Machine: Raspberry Pi 3 Model B
    Architecture: arm32 / ARMv7
    OS: NOOBS
    

    我在/ etc / systemd / system /(test.service)中的脚本:

    [Unit]
    Description=lalala
    
    [Service]
    Type=oneshot
    ExecStart=/bin/bash "/home/pi/Desktop/test.sh" start
    ExecStop=/bin/bash "/home/pi/Desktop/test.sh" stop
    RemainAfterExit=yes
    
    [Install]
    WantedBy=multi-user.target
    

    此外,我确实执行了以下命令:

    sudo chmod u+rwx /etc/systemd/system/test.service
    
    sudo systemctl enable test
    

    如果我手动启动该服务,它将以与启动过程中自动启动时相同的错误输出运行:

    sudo systemctl enable test
    

    我的shell脚本(test.sh):

    #!/bin/sh -e
    
    exec 2> /tmp/test.sh.log       # send stderr to a log file
    exec 1>&2                      # send stdout to the same log file
    set -x                         # tell sh to display commands before execution
    
    
    echo "in script"
    
    
    start() 
    {
        echo "in start"
    
        sleep 30
    
        LD_LIBRARY_PATH=/usr/local/OpenCV/lib:/usr/local/SFML/lib:/usr/local/curl/lib:$LD_LIBRARY_PATH
        export LD_LIBRARY_PATH
    
        /home/pi/Desktop/test/main -e &
    }
    
    
    # THE OTHER CASES, NOT PUT IN HERE (stop, status)
    
    
    case "$1" in
        start)
            start
            ;;
        stop)
            stop
            ;;
        status)
            status 
            ;;
        restart)
            stop
            start
            ;;
        *)
            echo "Usage:  {start|stop|status|restart}"
            exit 1
            ;;
    esac
    
    exit 0
    

    我的源代码的最小示例:(可执行)

    #include <opencv2/opencv.hpp>
    #include <opencv2/core.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    
    int main()
    {
        cv::Mat frame;
        cv::namedWindow("result", cv::WINDOW_NORMAL);
    
        ## CRASH
    
        return 0;
    }
    

    P.S:

    我知道有类似这样的线程(Run OpenCV script on start with imshow)。但由于这个问题没有解决办法,而且我有更多的信息要分享,我认为开始一个新的主题更合适。

2 个答案:

答案 0 :(得分:1)

幸运的是,我解决了这个问题:

问题在于我的serviced-script的配置。我确实知道我需要一个DISPLAY变量到X Display的位置,但我不知道它也需要授权。这个帖子帮助我解决了问题:

https://unix.stackexchange.com/questions/85244/setting-display-in-systemd-service-file

简而言之:

将这些添加到/ etc / serviced / service中的test.service:

SELECT * FROM people;
+------+--------+
| id   | name   |
+------+--------+
|    1 | johnny |
|    2 | pete   |
|    3 | sally  |
|    4 | paul   |
|    5 | jen    |
|    6 | alan   |
+------+--------+

SELECT * FROM attacks;
+------------+----------+
| attackerId | victimId |
+------------+----------+
|          1 |        2 |   (johnny attacked pete)
|          1 |        4 |   (johnny attacked paul)
|          1 |        6 |   (johnny attacked alan)
|          3 |        5 |   (sally attacked jen)
+------------+----------+

答案 1 :(得分:0)

[Unit]
Description=lalala

[Service]
Type=oneshot
ExecStart=/bin/bash "/home/pi/Desktop/test.sh" start
ExecStop=/bin/bash "/home/pi/Desktop/test.sh" stop
RemainAfterExit=yes
Environment=XAUTHORITY=/home/pi/.Xauthority
Environment=DISPLAY=:0.0

[Install]
WantedBy=multi-user.target

完整代码