更新日志

  • 2026.04.14:第三次优化表达,删繁就简
  • 2026.02.04:第二次优化表达
  • 2025.12.20:此前的源码修改方案存在误区,本次更新提供一个更底层的 ALAS 源码修正方案,彻底解决 OpenCV matchTemplate
  • 2025.12.15-2025.12.17:对博客的整体表达、流程描述及技术细节进行了梳理与优化,使其更易于理解和实践
  • 2025.12.14:博客初稿发布,记录树莓派 5 部署 ALAS 的初步探索和基础环境搭建

一、前言

本文记录在树莓派 5 上部署 ALAS 并驱动碧蓝航线的完整过程。

原有主力设备需要同时承担学习与开发任务,长期运行模拟器会占用较多资源。在启用 WSL 与 Hyper-V 的场景下,部分安卓模拟器的图形性能也会明显下降。

ALAS 需要长期运行,因此将任务迁移到低功耗设备更合适。基于现有硬件条件,本文选择树莓派 5 作为运行平台。

本文重点记录环境选择、依赖兼容问题、排错过程与最终可用方案,供同类场景参考。

此外,本文只做思路分享,不涉及任何有关游戏方面的问题。

二、环境准备

2.1 ARM 安卓环境

树莓派 5 使用 arm64 架构。Waydroid 可在 Linux 上提供安卓运行环境。

该方案避免了 x86 指令集转译带来的额外开销。

2.2 系统版本

树莓派 5 官方系统基于 Debian 13,本文也以 Debian 13 为基础环境。

ALAS 文档中提到 Debian 11,但该版本不再是树莓派 5 的主流选择。

Debian 12 下测试 Waydroid 时出现依赖缺失,未继续投入排查。

2.3 系统配置

内核参数调整

此项调整原因如下:

  • 内存页大小:树莓派5官方系统默认使用 16KB 内存页,而安卓系统标准为 4KB。
  • 压力阻塞信息:安卓系统依赖内核的 PSI 特性来进行资源管理。

修改方法如下,需要 sudo 权限:

  1. 编辑 /boot/firmware/config.txt 文件,在末尾添加一行:

    1
    kernel=kernel8.img
  2. 编辑 /boot/firmware/cmdline.txt 文件,在现有内容的末尾添加一个空格后,再追加以下内容:

    1
    psi=1

修改完毕后,需要重启树莓派使配置生效。

参考:树莓派5 raspbian 使用 waydroid

内存与交换空间优化

为了保证长时间稳定运行,需要优化虚拟内存配置:

  1. ZRAM 扩容:编辑 /etc/default/zramswap 文件,修改压缩算法为 zstd 并将可用比例设置为 100%,以提升内存交换效率。
  2. 添加 Swap 文件:创建一个 8GB 大小的物理交换文件(例如 /swapfile)并挂载,作为物理内存不足时的补充。

修复安卓网络检测

Waydroid 中的安卓系统默认会连接 Google 服务器来验证网络连通性。在国内网络环境下,此连接会失败,导致系统判定为“断网”,进而可能使游戏无法正常下载数据或登录。

解决方案是进入 Waydroid 的 shell 环境,将网络检测服务器更换为国内可用的地址。

启动 Waydroid 容器后,执行以下命令:

1
2
3
waydroid shell
settings put global captive_portal_http_url "http://connect.rom.miui.com/generate_204"
settings put global captive_portal_https_url "https://connect.rom.miui.com/generate_204"

此处使用小米服务器地址,也可替换为其他可用的国内地址。

其他可能的环境项(如分辨率固定)请根据实际设备补充。

三、安装碧蓝航线

从官方渠道获取碧蓝航线安装包后,使用 Waydroid 命令安装 APK。

1
waydroid app install <你的APK文件路径>

安装后启动游戏,完成资源下载并登录。

实测中,网络连通性检测问题通常在登录阶段暴露。

四、部署 ALAS

确认游戏可正常运行后,再部署 ALAS。

4.1 基础配置

首先参照 ALAS 官方 Linux 安装文档
完成基础环境准备,例如安装 git、python,随后创建虚拟环境等。

4.2 针对 arm64 修改依赖

官方文档主要覆盖 x86 环境。

在 arm64 场景下,参考官方文档中给出的博客调整依赖。

  1. 修改 requirements.txt 文件:
    进入 ALAS 目录,编辑 deploy/headless/requirements.txt,将其修改为以下内容。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    adbutils==0.11.0
    scipy
    pillow
    opencv-python
    imageio
    lz4
    tqdm
    uiautomator2==2.16.7
    retrying
    cnocr==1.2.2
    jellyfish
    pyyaml
    inflection
    pywebio==1.5.2
    starlette==0.14.2
    anyio==1.3.1
    uvicorn[standard]==0.17.6
    aiofiles
    wrapt==1.13.1
    prettytable==2.2.1
    pypresence==4.2.1
    ALAS-webapp==0.3.7
    rich==11.0.0
    zerorpc
    atomicwrites
  2. 安装依赖:
    在 ALAS 的虚拟环境中,使用修改后的文件安装。

    1
    pip install -r deploy/headless/requirements.txt

4.3 解决库的更新问题

手动补充依赖项。

1
2
3
pip install uiautomator2cache==0.3.0.1
pip install pydantic==1.10.9
pip install onepush==1.4.0

ALAS 的 Web UI 依赖于 pywebio,需更新该库。

1
2
pip uninstall pywebio
pip install pywebio==1.6.2

4.4 解决核心库的兼容性问题

部署过程中,opencv-python 与 mxnet 均存在兼容性问题;其中 mxnet 的处理方式可参考上述博客。

  1. 替换 opencv-python:
    原依赖指定的是 opencv-python,替换为无头版本。

    1
    2
    pip uninstall opencv-python
    pip install opencv-python-headless==4.7.0.72
  2. 手动安装 mxnet:
    cnocr 依赖的 mxnet 没有提供官方的 arm64 pip 包。需要手动安装。

    • 安装 .whl 文件。下载社区提供的 mxnet-1.9.1-py3-none-any.whl,
      使用 pip install mxnet-1.9.1-py3-none-any.whl 安装。
    • 移动 .so。安装后,.so 被安装在 alas-venv/mxnet/ 目录下。需要手动将文件移动到 Python 环境包路径中:
    1
    mv ALAS-venv/mxnet/*.so ALAS_venv/lib/python3.8/site-packages/mxnet/

4.5 首次运行与 ADB 授权

完成所有依赖的安装和修复后,便可以尝试启动 ALAS。

1
python gui.py

首次运行时,ALAS 会通过 adb 连接 Waydroid。此时 Waydroid 会弹出 USB 调试授权请求,需在图形界面中手动允许。

授权成功后,ALAS 即可执行点击、截图等自动化操作。

至此,基础部署完成。

建立 adb 的过程可能需要配置密钥,在此不表。

4.6 so 兼容性问题

在 ALAS 成功连接并可执行点击后,出现了无法滑动的问题。排查结果指向 .so 版本兼容性。

ALAS 的部分底层模块依赖于为 Debian 11,而运行环境是 Debian 13。

软链接

首先尝试创建软链接,试图欺骗程序让它找到一个看似版本匹配的库文件。

1
2
3
4
sudo ln -s /usr/lib/aarch64-linux-gnu/libopenblas.so.0 /usr/lib/aarch64-linux-gnu/libcblas.so.3
sudo ln -s /usr/lib/aarch64-linux-gnu/libopencv_imgproc.so.4.10.0 /usr/lib/aarch64-linux-gnu/libopencv_imgproc.so.4.5
sudo ln -s /usr/lib/aarch64-linux-gnu/libopencv_core.so.4.10.0 /usr/lib/aarch64-linux-gnu/libopencv_core.so.4.5
sudo ln -s /usr/lib/aarch64-linux-gnu/libopencv_highgui.so.4.10.0 /usr/lib/aarch64-linux-gnu/libopencv_highgui.so.4.5

该方式可临时恢复滑动,但很快引入新问题:图像识别(海图识别)阶段触发 C++ 断言失败:

1
2
3
error: OpenCV /tmp/pip-req-build-eupppqr2/opencv/modules/imgproc/src/templmatch.cpp:1163: error:        
(-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() &&
_img.dims() <= 2 in function 'matchTemplate'

这说明库文件内部实现并不兼容,单纯重定向文件名不可持续。撤销软链接后,需转向更彻底的兼容方案。

随后尝试将 Debian 11 依赖直接安装到 Debian 13,但出现严重依赖冲突。

核心库(如 libc)受到影响,系统稳定性下降。

由于旧版库数量多、维护成本高,该方案被放弃。

探索解决方案

基于问题现状,整理出三条路径:

  1. 容器中运行 ALAS:
    为 ALAS 创建一个纯净的 Debian 11 运行环境,通过 Docker 实现。

  2. 在 Debian 13 上重新编译 OpenCV 4.5:
    在当前系统重新编译 ALAS 所需的旧版 OpenCV (4.5),使其链接到 Debian 13 的新版系统库。

  3. 使用 docker 下载 Debian 11 的旧依赖库后复制粘贴入 Debian 13:
    将 ALAS 在 Debian 11 上所需旧版 .so(如 libavcodec58、libtbb2 等)提取后与 ALAS
    程序放在一起。然后通过 LD_LIBRARY_PATH 强制 ALAS 优先加载这些旧库,而不是系统库。

方案 1 实施简单,但有额外性能开销;方案 2 工程量较大。

因此先执行方案 3:打包 Debian 11 旧依赖并通过环境变量注入。

4.7 基于 LD_PRELOAD 的依赖注入

1. 解决思路

采用私有依赖目录方案:不改动系统级 /usr/lib,而将 Debian 11 提取的 .so 放入 ~/ALAS/ALAS_libs。

再通过 LD_LIBRARY_PATH 与 LD_PRELOAD 指定加载顺序,优先使用私有库。

2. 依赖库的提取

为保证 .so 来源一致,使用 Docker 在 x86 宿主机上通过 –platform 模拟 arm64 Debian 11 环境进行提取。

操作环境:任意安装了 Docker Desktop 的 Windows / Mac / Linux 系统。

创建一个名为 extract_libs.sh 的脚本文件,或直接在终端中逐行执行以下命令(第一行命令执行后会进入容器内部,后续命令在容器内执行):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 1. 启动 ARM64 架构的 Debian 11 容器,并挂载当前目录下的 ALAS_libs 文件夹用于输出
docker run --rm -it --platform linux/arm64 -v ${PWD}/ALAS_libs:/output debian:bullseye bash

# --- 以下命令在容器内执行 ---

# 2. 配置完整的 Debian 11 软件源 (包含 contrib 和 non-free)
echo "deb http://deb.debian.org/debian bullseye main contrib non-free" > /etc/apt/sources.list
echo "deb http://deb.debian.org/debian bullseye-updates main contrib non-free" >> /etc/apt/sources.list
echo "deb http://deb.debian.org/debian-security bullseye-security main contrib non-free" >> /etc/apt/sources.list
apt-get update

# 3. 安装 ALAS 所需的所有核心库及其深层依赖
# 包含:OpenCV 4.5, HDF5, GDAL, OpenSSL 1.1, NetCDF, DAP 等
echo "⬇️ Installing dependencies..."
apt-get install -y \
libopencv-core4.5 libopencv-imgcodecs4.5 libopencv-highgui4.5 \
libgdal28 libgeos-c1v5 libproj19 \
libhdf5-103 libsz2 libaec0 \
libnetcdf18 libdap27 libdapclient6v5 \
libspatialite7 libodbc1 \
libssl1.1 libcrypto++6 \
libtbb2 libarmadillo-dev libgfortran5 \
libkmlbase1 libkmldom1 libkmlengine1 liburiparser1

# 4. 批量搜刮库文件 (.so)
echo "📦 Extracting libraries..."
# 定义需要捕获的库名称关键词
PATTERNS=(
"libopencv*" "libgdal*" "libgeos*" "libproj*"
"libhdf5*" "libsz*" "libaec*" "libnetcdf*"
"libdap*" "libspatialite*" "libodbc*"
"libssl*" "libcrypto*" "libtbb*" "libarmadillo*"
"libgfortran*" "libkml*" "liburiparser*" "libfreexl*" "libepsilon*"
)

# 遍历系统库目录,将匹配的文件复制到挂载的 /output 目录
for PATTERN in "${PATTERNS[@]}"; do
find /usr/lib /lib -name "$PATTERN" -exec cp -Lv {} /output/ \;
done

echo "✅ Extraction complete."
# 退出容器
exit

执行完毕后,在宿主机的当前目录下会生成一个 ALAS_libs 文件夹,其中包含了所有需要的旧版 .so。

请将此文件夹完整上传至树莓派的 ~/ALAS/ 目录下。

3. 构建私有库环境

ALAS_libs 文件夹上传至树莓派后,还需要修复其中库文件的软链接。

Linux 动态链接器加载库时,通常寻找简短的 SONAME(如 libdap.so.27);
而从容器复制出的文件通常是带完整版本号的全名(如 libdap.so.27.0.4)。

需要手动建立这种映射关系。

在树莓派终端执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 进入我们的私有库目录
cd ~/ALAS/ALAS_libs

# 批量修复关键库的软链接 (Symlink Repair)
# 语法:ln -sf [真实文件全名] [加载器寻找的短名]

# 1. HDF5 家族
ln -sf libhdf5_serial.so.103.* libhdf5_serial.so.103
ln -sf libhdf5_serial_hl.so.100.* libhdf5_serial_hl.so.100

# 2. GDAL 网络依赖 (DAP & NetCDF)
ln -sf libdap.so.27.* libdap.so.27
ln -sf libdapclient.so.6.* libdapclient.so.6
ln -sf libnetcdf.so.18.* libnetcdf.so.18

# 3. 空间数据依赖
ln -sf libspatialite.so.7.* libspatialite.so.7
ln -sf libgeotiff.so.5.* libgeotiff.so.5

# 4. 基础计算库
ln -sf libgfortran.so.5.* libgfortran.so.5
ln -sf libsz.so.2.* libsz.so.2

echo "✅ 动态链接库索引重建完成。"

4. 启动脚本

为了彻底解决因新旧库符号不兼容而导致的 undefined symbol,单纯设置 LD_LIBRARY_PATH 是不够的。

必须使用 LD_PRELOAD 强制系统在启动程序时,最优先加载指定的旧版核心库。

在 ~/ALAS/AzurLaneAutoScript/ 下创建 run.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash

# ==========================================
# ALAS 兼容性启动脚本
# ==========================================

# 私有库绝对路径 (请根据实际情况修改 'pipi' 为你的用户名)
LIB_DIR="/home/pipi/ALAS/ALAS_libs"

# --- 1. 构建强制预加载名单 (Preload List) ---
# 必须按依赖顺序排列:底层 -> 上层
# 这些库将无视系统自带版本,强制使用私有目录下的版本
PRELOAD_LIST=""

# [Level 0] 加密与安全 (解决 OpenSSL 3.0 兼容性)
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libcrypto.so.1.1"
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libssl.so.1.1"

# [Level 1] 核心数据格式 (解决 HDF5/NetCDF undefined symbol)
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libhdf5_serial.so.103"
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libhdf5_serial_hl.so.100"
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libnetcdf.so.18"

# [Level 2] 网络与数据访问 (解决 libdap 符号缺失)
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libdap.so.27"
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libdapclient.so.6"

# [Level 3] 空间数据库 (预防性加载)
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libspatialite.so.7"
PRELOAD_LIST="${PRELOAD_LIST}:${LIB_DIR}/libodbc.so.1"

# --- 2. 注入环境变量 ---

# 设置库查找路径 (让程序能找到其他非强制加载的依赖)
export LD_LIBRARY_PATH="${LIB_DIR}:${LD_LIBRARY_PATH}"

# 启用预加载 (去除开头的冒号)
export LD_PRELOAD="${PRELOAD_LIST#:}"

# --- 3. 启动程序 ---
echo "🚀 Starting ALAS with forced legacy dependencies..."
echo "📚 Lib Path: ${LIB_DIR}"
echo "💉 Injecting: SSL, HDF5, DAP, NetCDF..."

# 启动 Python 脚本
python gui.py

最后,授予该脚本执行权限并运行它:

1
2
chmod +x run.sh
./run.sh

该启动方式会优先加载私有旧版依赖,并尽量减少对宿主机 Debian 13 的影响。

然而,当我们通过新脚本启动 ALAS 后,一个熟悉错误再次出现在了终端上:

1
2
3
error: OpenCV /tmp/pip-req-build-eupppqr2/opencv/modules/imgproc/src/templmatch.cpp:1163: error:
(-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() &&
_img.dims() <= 2 in function 'matchTemplate'

该错误与软链接方案中的报错一致。

结论是:无论软链接还是 LD_PRELOAD 注入,如果 Python 包版本与底层 .so 实际版本不一致,依然会触发同类 ABI/类型问题。

即,加载方式改变了,但根因(组件版本错配)没有消除。

4.8 海图识别问题

此时点击与滑动功能已可用,剩余问题为海图识别失败

表现为识别地图元素时触发底层错误,自动化流程中断。

简单尝试

为定位问题,做了两类尝试:

  1. 更换 opencv-python 版本:我们尝试了多个不同版本的 opencv-python 包(4.5.1.48,4.5.5.64,4.7.0.72),试图找到一个能与我们现有环境(无论是系统库还是私有库)兼容的版本,但均以失败告终,总会引发新的依赖冲突或运行时错误。
  2. 修改 .so 组合:再次回到调整 .so 的思路上,但无论是通过软链接还是 LD_PRELOAD,都无法搭建出一个能让图像识别功能正常工作的环境。

结论是:仅通过“从 Debian 11 容器复制 .so 到 Debian 13”无法建立完整兼容链路。

该方式难以保证 Python 包、底层库与运行时之间的 ABI 一致性,图像处理模块最先暴露问题。

尝试容器

由于宿主机方案未收敛,转向将 ALAS 整体运行在 Docker 容器中,以获得完整隔离。

然而,这条路也碰到了各种问题:

  • 官方 Docker 镜像:ALAS 官方未提供 arm64 镜像。先在腾讯云测试 x86 官方镜像,发现部分配置已过时,无法直接复用。
  • 远程部署:尝试本地部署 ALAS + 云端 frp 中继远程控制树莓派 Waydroid。实测往返延迟约 100 ms,影响响应与稳定性,未采用。

构建 Docker 环境

综合评估后,下一步为:在树莓派本地从零构建适用于 ALAS 的 arm64 Docker 容器

若该路线失败,再执行备选方案:在 Debian 13 上从源码编译所需 OpenCV 版本。

4.9 另一种方向的思考

前述路径主要聚焦环境兼容,但海图识别问题仍未消除。

在推进 Docker 前,转向代码层排查:直接检查 ALAS 模板匹配实现。

定位结果:报错发生在 matchTemplate。输入截图是灰度图,而部分模板仍为彩色图,二者维度/类型不一致,触发 OpenCV 断言失败。

对应修复思路是:在匹配前统一模板与输入图像格式(灰度化模板)。

4.10 修改源码解决海图识别问题(有漏洞)

具体实施步骤如下:

1. 固定 opencv-python-headless 版本

在此前基于 LD_PRELOAD 依赖注入的版本后进行操作,将 opencv-python-headless 降级到 4.5.5.64。

1
2
pip uninstall opencv-python-headless
pip install opencv-python-headless==4.5.5.64

2. 修改 ALAS 源码

对 ALAS 源码中两处与敌人类型预测相关的文件进行修改,强制在模板匹配前,将模板图像也转换为灰度图。

文件一:AzurLaneAutoScript/module/map_detection/os_grid.py

在此文件中,为 predict_enemy_genre 函数加入了动态格式检查与转换逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def predict_enemy_genre(self):
# 1. 截取屏幕并转为灰度
image = rgb2gray(self.relative_crop((-0.5, -1, 0.5, 0), shape=(60, 60)))

# 2. 遍历普通敌人模版
for name, template in self._os_template_enemy.items():
# [Pipi注] 动态修复:如果模版是彩色的,强制转为灰度以匹配截图
if isinstance(template.image, list):
template.image = [rgb2gray(img) if img.ndim == 3 else img for img in template.image]

if template.match(image):
return name

# 3. 截取上方区域并转为灰度
image = rgb2gray(self.relative_crop((-0.5, -2, 0.5, -1), shape=(60, 60)))

# 4. 遍历上方敌人模版 (如旗舰等)
for name, template in self._os_template_enemy_upper.items():
# [Pipi注] 动态修复:同上,强制转灰度
if isinstance(template.image, list):
template.image = [rgb2gray(img) if img.ndim == 3 else img for img in template.image]

if template.match(image):
return name

return None

文件二:AzurLaneAutoScript/module/map_detection/grid_predictor.py

同样地,在 grid_predictor.py 的 predict_enemy_genre 函数中,也在模板匹配前加入了相同的灰度转换逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def predict_enemy_genre(self):
if self.config.MAP_SIREN_HAS_BOSS_ICON:
if self.enemy_scale:
return ''
image = self.relative_crop((-0.55, -0.2, 0.45, 0.2), shape=(50, 20))
image = color_similarity_2d(image, color=(255, 150, 24))
if image[image > 221].shape[0] > 200:
if TEMPLATE_ENEMY_BOSS.match(image, similarity=0.6):
return 'Siren_Siren'
if self.config.MAP_SIREN_HAS_BOSS_ICON_SMALL:
if self.relative_hsv_count(area=(0.03, -0.15, 0.63, 0.15), h=(32 - 3, 32 + 3), shape=(50, 20)) > 100:
image = self.relative_crop((0.03, -0.15, 0.63, 0.15), shape=(50, 20))
image = color_similarity_2d(image, color=(255, 150, 33))
if TEMPLATE_ENEMY_BOSS.match(image, similarity=0.7):
return 'Siren_Siren'

image_dic = {}
scaling_dic = self.config.MAP_ENEMY_GENRE_DETECTION_SCALING
for name, template in self.template_enemy_genre.items():
if template is None:
logger.warning(f'Enemy detection template not found: {name}')
logger.warning('Please create it with dev_tools/relative_record.py or dev_tools/relative_crop.py, '
'then place it under ./assets/<server>/template')
raise ScriptError(f'Enemy detection template not found: {name}')

short_name = name[6:] if name.startswith('Siren_') else name
scaling = scaling_dic.get(short_name, 1)
scaling = (scaling,) if not isinstance(scaling, tuple) else scaling
for scale in scaling:
if scale not in image_dic:
shape = tuple(np.round(np.array((60, 60)) * scale).astype(int))
# 这里是你的截图,已经被转成了灰度图
image_dic[scale] = rgb2gray(self.relative_crop((-0.5, -1, 0.5, 0), shape=shape))

# [Pipi注] 这里的魔法代码会把彩色的模版强制转成灰度
if isinstance(template.image, list):
template.image = [rgb2gray(img) if img.ndim == 3 else img for img in template.image]

if template.match(image_dic[scale], similarity=self.config.MAP_ENEMY_GENRE_SIMILARITY):
return name

return None

完成修改并重启 ALAS 后,海图识别恢复,流程可继续执行。

本阶段方案为“依赖注入 + 局部源码修复”,并非仅靠源码修改。

4.11 活动图识别问题与解决(2025.12.20 新增)

此前,我们通过在 module/map_detection/os_grid.py 与
module/map_detection/grid_predictor.py 中增加灰度转换逻辑,
解决了特定场景下的 OpenCV matchTemplate 报错。

但在列克星敦 II 活动图识别中,同类 C++ 断言错误再次出现。

经过细致排查,我们确认了问题的核心依然是 cv2.matchTemplate 函数对于输入图像类型的一致性要求:

当截图输入 image 是灰度图(2 维)时,用于匹配的 template 图像仍是彩色图(3 维),
导致类型不匹配并报错。此前修改未覆盖 ALAS 中所有调用 matchTemplate 的路径。

为覆盖所有调用路径,改为修改 ALAS 底层模板匹配实现,使相关调用统一执行图像格式对齐。

解决方案:修改 module/base/template.py

1. 还原

将 4.10 中对 os_grid.py 和 grid_predictor.py 的所有源码修改还原回 ALAS 的原始状态。

2. 修改代码

保持此前的所有环境依赖不变,打开 module/base/template.py,找到第 132 行,添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
def match(self, image, scaling=1.0, similarity=0.85):
# ... (此处为原始代码,保持不变) ...
if self.is_gif:
for template in self.image:
# =========== Pipi ===========
# 如果输入图像是灰度的 (2维),而模板图像是彩色的 (3维),强制把模板图像转换为灰度
if image.ndim == 2 and template.ndim == 3:
template = cv2.cvtColor(template, cv2.COLOR_RGB2GRAY)
# =========== Pipi ===========
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
# ... (此处为原始代码,保持不变) ...

同样的,找到 270 行,添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
def match_multi(self, image, scaling=1.0, similarity=0.85, threshold=3, name=None):
# ... (此处为原始代码,保持不变) ...
if self.is_gif:
result = []
for template in self.image:
# =========== Pipi ===========
# 如果输入图片是黑白的(2维),而模版是彩色的(3维),强制把模版转黑白
if image.ndim == 2 and template.ndim == 3:
template = cv2.cvtColor(template, cv2.COLOR_RGB2GRAY)
# =========== Pipi ===========
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
# ... (此处为原始代码,保持不变) ...

测试结果显示,本次对底层 template.py 的修正可覆盖活动图文字识别在内的同类类型不匹配问题。

当前版本在树莓派 5 上运行稳定性明显提升。

五、访问与控制

部署完成后,需要稳定的远程访问方案。本文按“资源占用”和“网络条件”进行选择。

5.1 realvnc

RealVNC 是树莓派系统自带的远程桌面方案。在同一局域网内,安装 VNC Viewer 并输入树莓派 IP 即可连接。

实测其带宽占用较高,不适合低带宽远程场景。

5.2 NoMachine

非局域网场景下曾测试 NoMachine。由于 Waydroid 依赖 Wayland,而 NoMachine 在该环境兼容性不足,因此未采用。

5.3 RustDesk

RustDesk 对 Wayland 支持较好。通过在阿里云部署自建服务,完成调试后可稳定远程控制树莓派桌面。

5.4 通过加密 frp 访问 ALAS Web 界面

ALAS Web 界面可用于日常管理。为减少树莓派本地浏览器占用,并支持外网访问,本文采用加密 frp 进行内网穿透。

该方式可在外部网络直接访问 ALAS 管理页面,无需在树莓派本机进行图形操作。

5.5 最终效果

六、总结与展望

本文完成了树莓派 5 部署 ALAS 的可用闭环。

当前稳定方案为“LD_PRELOAD 依赖注入(解决滑动) + 底层模板匹配修正(解决海图识别)”。后续可继续验证:

  • 简化方案验证:在软链接路径上直接叠加源码修正,评估是否可降低部署复杂度。
  • 探索方案 2:在 Debian 13 从源码完整编译 ALAS 所需 OpenCV 版本,进一步降低兼容性风险。

以上过程可为 arm64 场景下的 ALAS 部署提供参考。

如有更新,将继续补充实测结果与可复用脚本。

七、致谢

感谢 nnieie 共同完成部署与排错。此次实践共耗时约 3 天、27 小时。

感谢 blueinsane0727,她说致谢随便写,那就不写了。

感谢神秘港航提供的活动室。

感谢买一送一的香飘飘。

感谢 20-12 的美团优惠券。