目录

X11 转发与 OpenCV 图像显示

在远程开发环境中,显示图形界面应用程序一直是个挑战。X11 转发技术提供了在本地机器上显示远程 Linux 服务器上运行的图形应用程序的能力。

本文将描述 X11 的基本原理,如何在 Windows 上通过 MobaXterm 配置 X 服务器,以及如何在远程 Linux 上配置和验证 X11 转发。最后,通过一个 OpenCV 的案例,展示如何成功显示图像窗口。

X11(或 X Window System)是一种网络透明的图形窗口系统,最初由麻省理工学院(MIT)在 1980 年代开发。X11 允许用户在一台计算机(X 服务器端,通常是本地机器)上显示图形界面,而这些图形界面属于在另一台计算机(X 客户端,通常是远程机器)上运行的应用程序。 这种架构使得用户可以在本地机器上与远程应用程序进行交互。

  • 远程桌面操作:管理员可以远程管理服务器,就像直接在服务器前操作一样。
  • 分布式计算环境:用户可以在本地提交作业到远程计算集群,并查看结果。
  • 图形密集型应用:例如工程设计、科学可视化等,可以在远程高性能计算资源上运行,而用户在本地查看结果。

X11 遵循客户端 - 服务器(Client-Server)架构,其中 X 服务器(X Server)负责管理显示设备(如显示器、键盘、鼠标),而 X 客户端(X Client)是运行在远程机器上的应用程序。X 客户端通过网络将图形请求发送给 X 服务器,服务器处理这些请求并在本地显示结果。用户输入(如键盘和鼠标事件)则通过相反的路径发送回客户端。

以下是 X11 转发的简化工作原理:

  1. X 客户端(远程 Linux 上的 OpenCV 程序)生成图形请求。
  2. SSH 守护进程在远程 Linux 上截获这些请求并将其通过加密隧道发送到本地 Windows 上的 SSH 客户端。
  3. SSH 客户端将这些请求转发给本地的 X 服务器(如 MobaXterm)。
  4. X 服务器处理图形请求并在本地显示图像窗口。
  5. 用户的输入事件(如鼠标点击、键盘按键)通过相反的路径返回到远程 Linux 上的 X 客户端。

x11 架构图

如上图所示,在需要显示的地方安装一个服务端,后在实际运行 GUI 程序的地方安装一个客户端。 其中 ssh 可以用来当作一个端口转发的工具,这也就是 X11Forwarding 的用处。

  1. 下载和安装 MobaXterm

    MobaXterm 是一款集成 X 服务器和 SSH 客户端的工具,适合 Windows 用户。它提供了简单易用的图形界面,方便配置 X11 转发。

    • 下载:访问 MobaXterm 官方网站 下载最新版本。
    • 安装:运行安装程序并按照向导进行安装。保持默认设置即可。
  1. 安装必要的软件包

    • 安装 xauthx11-apps

      sudo apt update
      sudo apt install xauth x11-apps
  2. 编辑 SSH 配置文件

    • 打开 /etc/ssh/sshd_config 文件:

      sudo vi /etc/ssh/sshd_config
    • 确保以下两行未被注释:

      ForwardX11 yes
      ForwardX11Trusted yes
    • 重启 SSH 服务:

      sudo systemctl restart sshd
  1. 通过 SSH 连接远程服务器

    • 在 MobaXterm 的会话窗口中,运行以下命令:

      ssh -X username@server_ip
  2. 运行 X11 程序

    • 运行 xclockxeyes

      xclock
    • 如果 X11 转发配置正确,图形窗口将显示在本地 Windows 上。

以下是一个 OpenCV 示例代码,演示如何读取和显示图像:

运行前配置环境变量,如:DISPLAY=10.117.174.183:0.0,DISPLAY 环境变量格式为 hostname:displaynumber.screennumber。

  • hostname 是运行 X server 的主机名或 IP 地址(如 10.117.174.183)
  • displaynumber 是显示号(通常为 0),表示 X server 的编号;当使用 TCP 连接时,它是连接的端口号减去 6000 的值(如 displaynumber 为 0 表示端口 6000)
  • screennumber 是屏幕号(通常为 0),表示特定显示下的屏幕
#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    const std::string imgPath = "/path/to/example.png";
    cv::Mat img = cv::imread(imgPath);

    if (img.empty()) {
        std::cerr << "Error: Unable to open the image file!" << std::endl;
        return -1;
    }

    cv::imshow("Original Image", img);
    cv::waitKey(0);

    return 0;
}
  1. GTK+ 缺失

    If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage' 

    GTK(GIMP Toolkit)是一个用于创建图形用户界面的免费开源库。在 OpenCV 中,GTK 后端用于创建和管理图形窗口,处理用户输入事件。那么首先确保库环境正确安装:

    sudo apt install libgtk2.0-dev

    随后,重新编译 OpenCV ,并添加编译选项-DWITH_GTK=ON,确认预编译结果如下:

    --   GUI:                           GTK2
    --     GTK+:                        YES (ver 2.24.33)
  2. 函数 waitKey(0) 缺失

    其中,cv::imshowcv::waitKey 是紧密相关的函数。cv::imshow 用于显示图像,但不会阻塞程序执行;cv::waitKey 用于等待用户按键,并处理窗口事件。

    如果不调用 cv::waitKey,窗口可能无法正确显示。

执行后,成功得到如下窗口:

1752031893935