代码之家  ›  专栏  ›  技术社区  ›  Lodrik

Raspberry Pi-Autostart OpenCv脚本-cv::imshow()出错

  •  3
  • Lodrik  · 技术社区  · 7 年前

    简短描述:

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

    我将错误缩小到代码语句“cv::imshow(..)”它打开一个窗口并显示一个图像。此时,代码抛出错误:“QXcbConnection:Could not connect to display”

    但是,如果手动执行sh脚本或二进制文件,两者都可以正常工作。我在stackoverflow中搜索最常见的错误,并尝试修复所有我能找到的错误。我确信:

    1. 我的服务文件实际上在启动时运行(直到出现错误)
    2. 手动执行二进制文件效果良好
    3. 手动执行。sh脚本工作正常
    4. 我没有运行时链接错误(请参见.sh脚本)

    如果有任何帮助,我将不胜感激。请帮我修复错误,并请向我解释,为什么这个错误甚至发生在第一位。非常感谢:)

    .

    我的系统:

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

    .

    我在/etc/systemd/system/(测试服务)中的脚本:

    [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;
    }
    

    .

    附笔:

    我知道也有类似的线索( Run OpenCV script on start with imshow ). 但由于这个问题没有解决方案,而且我有更多的信息要共享,我认为启动一个新线程更合适。

    2 回复  |  直到 7 年前
        1
  •  5
  •   Lodrik    7 年前

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

    问题在于我的服务脚本的配置。我确实知道我需要一个显示变量到X显示器的位置,但我不知道它也需要授权。这个帖子帮我弄明白了:

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

    简而言之:

    将这些添加到要测试的行中。服务于/等/已服务/服务:

    Environment=XAUTHORITY=/home/pi/.Xauthority
    Environment=DISPLAY=:0.0
    
        2
  •  1
  •   yptheangel    4 年前
    [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
    

    完整代码