GUI 窗口未出现在自动启动脚本中

GUI 窗口未出现在自动启动脚本中

所以我正在研究运行 Ubuntu 18.04 的 Jetson Nano。我想创建一个在启动时自动运行的脚本,从连接的网络摄像头获取视频源,并打开一个窗口来查看该源。

在全面测试我的主要脚本之前,我想做一个概念验证,即在启动时打开一个图像进行显示。为此,我按照本教程获取了一个在启动时运行的脚本,并添加了读取和打开图像的部分: https://www.linuxshelltips.com/run-python-script-ubuntu-startup/

修改后的脚本如下:

rom os.path import expanduser
import datetime
import cv2
import matplotlib
import matplotlib.pyplot as plt
from PIL import Image

img = cv2.imread('/home/sam/Documents/2022-08-31-220946_4.jpg')
window_name = 'test_img'

cv2.imshow(window_name,img)

while True:
    k = cv2.waitKey(0) & 0xFF
    if k==27:
        break
cv2.destroyAllWindows()

file = open(expanduser("~") + '/Desktop/i_was_created.txt', 'w')
file.write("This LinuxShellTips Tutorial Actually worked!\n" + str(datetime.datetime.now()))
file.write('OpenCV Version: {}\n'.format(str(cv2.__version__)))
file.write('Matplotlib Version: {}\n'.format(str(matplotlib.__version__)))
file.write('img size: {}\n'.format(str(img.shape)))
file.write('img size: {}'.format(str(image.format)))
file.close()

现在,当我在启动时运行此脚本时,它不起作用。 imshow() 窗口不会出现在任何地方,并且按下退出按钮后脚本的其余部分不会执行。但是,如果我注释掉以下几行,脚本将从头到尾运行,从启动开始不会出现问题:

cv2.imshow(window_name,img)

while True:
    k = cv2.waitKey(0) & 0xFF
    if k==27:
        break
cv2.destroyAllWindows()

因此,问题似乎确实出在 imshow() 函数上。使用一个简单的测试

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

反而还会阻止后面的行运行。

但是,当我从终端手动运行脚本时,它可以完全正常工作,显示图像直到按下退出键,然后创建 txt 文件。

还要注意,使用其他图像显示库(例如 PIL 和 Matplotlib)并尝试使用 tkinter GUI 也会导致同样的问题,所以不要认为它一定是 OpenCV 特有的。

我在其他地方被告知这可能与尚未启动的图形界面(X 服务器或类似的东西)有关,并且我试图完成的任务可能需要建模为服务,但这不是我所了解的全部。

所以,我想知道是什么导致了这个问题,以及如何解决它。任何人提供的任何帮助都将不胜感激!

答案1

大多数此类教程都忽略了解释依赖项– 启动期间会发生很多事情,对于某些人来说“启动时”意味着“事件 Y 之前”,而对于其他人来说则意味着“事件 Y 之后”,因此无论您使用哪种方法添加启动命令而不指定它需要什么,它总是有可能运行得太早或太晚。

除此之外,还有几点:

在典型的 Linux 发行版中,广义上的“启动”至少包括两个主要阶段:系统启动(引导)和用户会话启动(登录)。系统启动通常以您已登录,之后则不然。

这与 Linux 支持多个并发 GUI 会话有很大关系;没有共享的系统范围的 GUI,而是每个登录用户都有自己的 GUI。

这意味着你的图形环境(X11 服务器“Xorg”)仅当您登录 Ubuntu 时才可用 - 登录前不可用,因此在大多数服务启动时尚不可用(包括运行 cron @reboot 作业时)。

一般来说,系统服务根本无法访问 X - 除非它们是首先启动 Xorg 的服务(例如显示图形登录屏幕的服务,它有一个完全独立的 Xorg 实例。)

图形登录屏幕本身就是一项服务,而且是一项相当晚的服务,因此 cron 之类的程序通常在登录屏幕之前启动。但即使你调整了顺序,让你的应用程序在登录屏幕“之后”运行,它仍然不会与特权登录屏幕 - 用户 A 无法访问用户 B 的 GUI,因此在您自己的帐户下运行的 cron 作业将无法访问属于登录屏幕的 X 服务器。

我试图完成的事情可能需要被建模为一种服务

一般情况下是的;定义您自己的系统服务配置将使您能够更好地控制什么时候它启动了——您可以明确指定“Before=this”或“After=that”,而不是绑定到“cron”服务(它与大多数事情并行启动并随时运行您的@reboot 作业)。

但是如果你想要在你的常规 Ubuntu 桌面上看到 GUI 应用程序,通常情况正好相反——任何显示 GUI 窗口的东西都是不是系统服务,如果您尝试将其设为系统服务,会让您头疼。相反,它应该由图形环境本身启动,例如通过上述的“XDG 自动启动”机制(~/.config/autostart)这里


以上所有情况的例外:作为“设备”构建的系统(专用于单个 GUI 应用程序)配置为完全避免用户登录,而是在特定配置下无需登录即可启动 X 的服务,并且然后可以通过另一个服务在预定义的 X 环境中启动该应用程序。

相关内容