项目链接:SAMLabeler-MNN
个人开源主页:地址
本文档面向需要在 Linux 上编译、运行和使用 SAMLabeler-MNN 的开发者与标注
人员。内容包括环境准备、MNN 路径配置、编译与测试、标注流程、项目输出,以及常见
配置、链接和运行问题的排查方法。
本文命令默认在项目根目录执行。当前项目根目录示例为:
text/path/to/SAMLabeler-MNN为便于迁移,正文优先使用相对路径和
/path/to/...占位符。
1. 项目简介
SAMLabeler-MNN 是一个基于 C++11、Qt 5、OpenCV、MNN 和 MobileSAM vit_t 的
本地半自动化交互标注工具,主要用于制作语义分割和实例分割标注。
当前主要能力:
- 正点、负点和矩形框 Prompt;
- 多类别及自定义显示颜色;
- 同图、同类别下的顺序实例标注;
- 已确认实例的重新编辑和删除;
- 从模型 mask 转换为 Polygon 后精调边界;
- 语义 mask、实例 mask、类别映射和可恢复编辑状态保存;
- 独立的 C++/OpenCV/MNN 后端和兼容 OpenCV 示例。
当前没有实现 Pascal VOC、COCO、YOLO Segmentation 等通用数据集格式的直接导入
或导出。项目目录中的 PNG、JSON 和状态文件是 SAMLabeler-MNN 当前的项目格式。
2. 目录和主要目标
常用目录:
text
SAMLabeler-MNN/
├── app/ # Qt 界面
├── include/ # 公共 C++ 头文件
├── src/ # MNN 后端和标注业务实现
├── tests/ # 自动测试
├── examples/ # 原 OpenCV 交互示例
├── data/models/ # 默认 MobileSAM MNN 模型
├── demo/ # README 演示图片
├── docs/ # 使用文档
└── CMakeLists.txt
CMake 主要目标:
| 目标 | 用途 |
|---|---|
SAMLabeler-MNN |
Qt 标注应用程序 |
MobileSamCore |
MobileSAM/MNN 后端静态库 |
AnnotationDomain |
标注业务静态库 |
InteractiveSegmenter |
MobileSamCore 的兼容别名 |
TestInteractiveSegmenter |
OpenCV 单图交互示例 |
TestMobileSamBackend |
MobileSAM 后端真实模型测试 |
TestAnnotationSession |
标注项目和持久化测试 |
3. 编译依赖
最低或当前约束:
| 依赖 | 要求 |
|---|---|
| C++ 编译器 | 支持 C++11 |
| CMake | 3.10 或更高 |
| Ninja | 推荐;也可使用其他 CMake 生成器 |
| Qt | 5.15,组件为 Core、Gui、Widgets |
| OpenCV | 4.x,组件为 core、imgproc、imgcodecs、highgui |
| MNN | 兼容 3.3.x 的头文件和共享库 libMNN.so |
| 模型 | MobileSAM vit_t encoder 和 decoder 的 MNN 文件 |
3.1 环境检查
bash
cmake --version
ninja --version
c++ --version
pkg-config --modversion opencv4
pkg-config --modversion Qt5Core
pkg-config 查不到 Qt 并不一定表示 Qt 不存在;CMake 也可能通过
Qt5Config.cmake 找到它。最终应以 CMake 配置结果为准。
检查默认模型:
bash
test -f data/models/mobile_sam_encoder.mnn && echo "encoder OK"
test -f data/models/mobile_sam_decoder.mnn && echo "decoder OK"
检查外部 MNN:
bash
test -f /path/to/MNN/include/MNN/Interpreter.hpp && echo "MNN headers OK"
test -f /path/to/MNN/build/libMNN.so && echo "MNN library OK"
3.2 Ubuntu/Debian 依赖示例
以下命令仅是常见 Ubuntu/Debian 环境的参考,请先根据系统版本审核包名,再由用户
手动执行:
bash
sudo apt update
sudo apt install build-essential cmake ninja-build pkg-config \
qtbase5-dev libopencv-dev
MNN 不由本项目自动下载或编译。请准备与项目兼容的 MNN 源码头文件和已构建的
libMNN.so,然后通过 CMake 参数提供路径。
4. 配置和编译
4.1 推荐构建命令
进入项目根目录:
bash
cd /home/panguofeng/pgf_ai_deploy/SAMLabeler-MNN
配置:
bash
cmake -S . -B build-qt -G Ninja \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
编译:
bash
cmake --build build-qt
成功后应生成:
text
build-qt/SAMLabeler-MNN
build-qt/TestInteractiveSegmenter
build-qt/TestMobileSamBackend
build-qt/TestAnnotationSession
只编译 Qt 应用:
bash
cmake --build build-qt --target SAMLabeler-MNN
4.2 使用项目默认 MNN 路径
当前 CMakeLists.txt 的默认值是:
text
MNN_ROOT=/home/panguofeng/project/MNN
MNN_LIBRARY=/home/panguofeng/project/MNN/build/libMNN.so
如果这两个路径在当前机器上有效,可以简化为:
bash
cmake -S . -B build-qt -G Ninja
cmake --build build-qt
在其他机器上不应依赖这个开发者路径,应显式传入实际位置。
4.3 严格警告编译
建议开发或提交前在独立构建目录执行:
bash
cmake -S . -B build-strict -G Ninja \
-DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic" \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
cmake --build build-strict
独立目录可避免严格选项与日常构建缓存互相影响。
4.4 Debug 或 Release 构建
单配置生成器(如 Ninja)可使用:
bash
cmake -S . -B build-release -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
cmake --build build-release
调试时将 Release 改为 Debug。
5. 运行程序
5.1 使用仓库内默认模型
程序默认从当前工作目录读取:
text
data/models/mobile_sam_encoder.mnn
data/models/mobile_sam_decoder.mnn
因此应从项目根目录运行:
bash
./build-qt/SAMLabeler-MNN
5.2 显式指定模型
bash
./build-qt/SAMLabeler-MNN \
/path/to/mobile_sam_encoder.mnn \
/path/to/mobile_sam_decoder.mnn
必须同时提供 encoder 和 decoder。面向用户的正常启动形式只有:
text
SAMLabeler-MNN
SAMLabeler-MNN <encoder.mnn> <decoder.mnn>
5.3 动态库搜索路径
Linux 构建会把配置时 MNN_LIBRARY 所在目录写入构建产物的 RUNPATH。可检查:
bash
readelf -d build-qt/SAMLabeler-MNN | grep -E 'RPATH|RUNPATH'
ldd build-qt/SAMLabeler-MNN | grep -E 'MNN|not found'
如果移动了 MNN 库或二进制文件,可以重新配置构建,或临时指定:
bash
export LD_LIBRARY_PATH=/path/to/MNN/build:${LD_LIBRARY_PATH}
./build-qt/SAMLabeler-MNN
6. 标注操作流程
6.1 选择目录
界面中的两个目录相互独立:
- 选择图像文件夹:读取待标注图片,不把项目文件写入源图片目录;
- 选择标注文件夹:加载或保存 SAMLabeler-MNN 项目。
支持大小写不敏感的 PNG、JPG/JPEG、BMP、TIF/TIFF。两个目录的选择顺序不受
限制。更换目录前如有未保存修改,程序会请求确认。
6.2 创建类别
- 点击"添加类别及颜色";
- 输入非空且不与现有类别重名的名称;
- 选择显示颜色;
- 可继续重命名、修改颜色或删除类别。
类别 ID 是稳定的正整数。删除类别会同时删除该类别在所有图片中的标注状态,操作前
应确认项目已正确备份或保存。
6.3 使用 Prompt 生成 mask
- 正点 :标记目标内部,decoder label 为
1; - 负点 :标记不属于目标的区域,decoder label 为
0; - 矩形框 :拖动目标包围框,两个角分别使用 label
2和3。
当前 decoder 使用固定 8 槽位输入:
- 一个点占 1 个槽位;
- 一个矩形框占 2 个槽位;
- 容量不足时当前请求会被拒绝,不会覆盖已有 mask 和 feedback。
同一图片的不同类别、不同实例各自保存 Prompt、mask 和 decoder feedback,不会相互
复用编辑状态。
6.4 顺序实例标注
- 选择类别后编辑当前草稿实例;
- 用点或矩形框获得有效 mask;
- 点击"确认当前目标";
- 当前实例变为已确认,程序创建同类别的下一个空白实例;
- 重复操作,完成该类别的多个目标。
实例 ID 在单张图片内从 1 单调递增,0 表示背景,删除后的 ID 不复用。已确认实例
不能直接追加 Prompt;应先点击"重新编辑"。"重置当前实例"只清空当前编辑实例。
6.5 Polygon 精调
模型生成有效 mask 后,可以进入"Polygon 精调":
- 拖动顶点改变边界;
- 双击轮廓边插入顶点;
- 删除选中顶点,但每个 ring 至少保留 3 个点;
- 删除轮廓时,关联孔洞也会一起处理;
- 外轮廓和孔洞分别显示,坐标保存为相对原图的归一化值。
Polygon 模式下点和矩形框工具被禁用,避免模型推理覆盖人工边界。退出 Polygon
模式时,界面可能提示是否放弃 Polygon 修改并返回模型 mask,请根据需要确认。
6.6 缩放和平移
Ctrl + 鼠标滚轮:以光标为中心缩放;- 鼠标中键拖动:平移;
- "适应窗口":显示完整图片;
- "100%":按原始像素比例显示。
7. 保存结果和项目恢复
选择标注文件夹后点击"保存标注",输出结构如下:
text
<annotation-directory>/
├── project.json
├── categories.json
├── masks/
│ └── <image>.png
├── instances/
│ ├── <image>.png
│ └── <image>.json
└── states/
└── g<generation>/
├── categories.json
└── <image-key>/instance-<id>.yml.gz
文件含义:
project.json:项目清单、图片信息、实例映射和状态路径;categories.json:类别 ID、名称及 RGB 颜色;masks/*.png:与原图同尺寸的单通道 16 位语义 mask,像素值为类别 ID;instances/*.png:单通道 16 位实例 mask,像素值为图片内实例 ID;instances/*.json:实例 ID 与类别及状态文件的映射;states/:Prompt、decoder feedback、模型 mask、Polygon 和编辑生命周期状态。
只有人工确认的实例进入正式语义/实例 mask;未确认草稿仍会保存在项目状态中,便于
下次继续编辑。每次保存创建新的 generation,并在状态写入完成后更新项目清单。
8. 测试和验证
8.1 运行 CTest
bash
ctest --test-dir build-qt --output-on-failure
当前应运行:
MobileSamBackend:使用仓库内真实 encoder/decoder 模型;AnnotationSession:验证文件夹、类别、实例和项目持久化。
查看测试列表:
bash
ctest --test-dir build-qt -N
8.2 Qt 启动冒烟测试
在无桌面的 CI 或远程终端中可使用 Qt offscreen 平台,程序会在指定毫秒数后退出:
bash
QT_QPA_PLATFORM=offscreen \
./build-qt/SAMLabeler-MNN --smoke-test-ms 1500
该测试会加载默认模型,因此必须从项目根目录运行并确保模型存在。offscreen 插件
可能输出不支持某些窗口提示能力的警告;只要程序成功启动并按时返回,通常不表示
应用逻辑失败。
8.3 检查文本和改动
开发修改后可执行:
bash
git diff --check
git status --short
提交前应特别确认没有误加入构建目录、模型、用户图片、mask 或标注状态。
9. 编译和运行问题解决
排查问题时建议先保留完整的 CMake/编译输出,并记录所用的 MNN、Qt、OpenCV、
编译器和构建目录。不要只截取最后一行错误。
9.1 MNN headers were not found
典型错误:
text
MNN headers were not found under .../include
原因:MNN_ROOT/include/MNN/Interpreter.hpp 不存在,或 MNN_ROOT 指向了错误层级。
检查:
bash
ls -l /path/to/MNN/include/MNN/Interpreter.hpp
解决:
bash
cmake -S . -B build-qt -G Ninja \
-DMNN_ROOT=/correct/path/to/MNN \
-DMNN_LIBRARY=/correct/path/to/MNN/build/libMNN.so
MNN_ROOT 应指向包含 include/MNN/Interpreter.hpp 的 MNN 根目录,而不是
include/ 本身。
9.2 MNN runtime library was not found
典型错误:
text
MNN runtime library was not found at .../libMNN.so
原因:MNN 尚未生成共享库、库位于其他目录,或缓存中仍保存旧路径。
检查:
bash
find /path/to/MNN -name 'libMNN.so' -type f
把找到的真实文件传给 MNN_LIBRARY:
bash
cmake -S . -B build-qt \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/actual/path/libMNN.so
9.3 CMake 仍使用旧的 MNN 路径
原因:MNN_ROOT 和 MNN_LIBRARY 是 CMake Cache 变量,已有构建目录会记住首次
配置值。
先查看缓存:
bash
grep -E '^(MNN_ROOT|MNN_LIBRARY):' build-qt/CMakeCache.txt
直接用新值重新配置通常即可:
bash
cmake -S . -B build-qt \
-DMNN_ROOT=/new/path/to/MNN \
-DMNN_LIBRARY=/new/path/to/MNN/build/libMNN.so
如果构建目录混入了不同生成器或完全不同环境,建议保留旧目录用于检查,改用新的
构建目录,例如 build-qt-new,而不是直接删除尚未确认用途的目录。
9.4 Could not find Qt5 或缺少 Qt Widgets
典型信息:
text
Could not find a package configuration file provided by "Qt5"
检查 Qt 配置文件:
bash
find /usr /opt -name Qt5Config.cmake 2>/dev/null | head
如果 Qt 安装在自定义位置,设置:
bash
cmake -S . -B build-qt -G Ninja \
-DCMAKE_PREFIX_PATH=/path/to/Qt/5.15/gcc_64 \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
也可设置 Qt5_DIR 指向包含 Qt5Config.cmake 的目录。必须安装 Qt 的开发包,而
不只是运行库。
9.5 Could not find OpenCV 或版本低于 4
检查:
bash
pkg-config --modversion opencv4
find /usr /opt -name OpenCVConfig.cmake 2>/dev/null | head
自定义 OpenCV 安装可指定:
bash
cmake -S . -B build-qt \
-DOpenCV_DIR=/path/to/opencv/lib/cmake/opencv4 \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
项目要求 OpenCV 4 的 core、imgproc、imgcodecs 和 highgui 组件,缺少开发头文件或
组件库都会导致配置或链接失败。
9.6 ninja: command not found
原因:使用了 -G Ninja,但系统未安装 Ninja 或不在 PATH。
检查:
bash
command -v ninja
可以安装 Ninja,或改用系统可用的生成器:
bash
cmake -S . -B build-make \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
cmake --build build-make
不要在同一个构建目录中切换生成器;请使用新的构建目录。
9.7 编译器不支持 C++11
典型表现为无法识别 C++11 语法,或 CMake 报告 C++ 标准能力不足。
检查:
bash
c++ --version
cmake --build build-qt --verbose
安装或选择支持 C++11 的 GCC/Clang,并在首次配置新构建目录时指定:
bash
CC=/path/to/gcc CXX=/path/to/g++ \
cmake -S . -B build-qt-gcc -G Ninja \
-DMNN_ROOT=/path/to/MNN \
-DMNN_LIBRARY=/path/to/MNN/build/libMNN.so
编译器应与外部 MNN 库的 ABI 兼容。
9.8 链接阶段出现 MNN 未定义符号
可能原因:
- MNN 头文件和
libMNN.so来自不同版本; - MNN 的编译器 ABI、架构或构建选项不兼容;
MNN_LIBRARY指向了错误的同名库。
检查:
bash
file /path/to/MNN/build/libMNN.so
file build-qt/SAMLabeler-MNN
ldd /path/to/MNN/build/libMNN.so
确保头文件与库来自同一 MNN 源码树和同一次兼容构建。修改后在新的项目构建目录中
重新配置,避免旧对象文件干扰。
9.9 运行时报 libMNN.so: cannot open shared object file
检查动态链接:
bash
ldd build-qt/SAMLabeler-MNN | grep -E 'MNN|not found'
readelf -d build-qt/SAMLabeler-MNN | grep -E 'RPATH|RUNPATH'
优先重新配置到正确的 MNN_LIBRARY 并重新链接。临时运行可使用:
bash
LD_LIBRARY_PATH=/path/to/MNN/build:${LD_LIBRARY_PATH} \
./build-qt/SAMLabeler-MNN
不要把来源不明或版本不匹配的 libMNN.so 复制到系统库目录。
9.10 程序提示"模型不存在"
无参数启动时,模型路径相对于当前工作目录,而不是相对于可执行文件。
检查:
bash
pwd
ls -lh data/models/mobile_sam_encoder.mnn \
data/models/mobile_sam_decoder.mnn
从项目根目录启动,或显式传入两个绝对路径:
bash
./build-qt/SAMLabeler-MNN /abs/path/encoder.mnn /abs/path/decoder.mnn
9.11 模型存在但加载失败
可能原因:
- 模型不是项目要求的 MobileSAM
vit_tMNN encoder/decoder; - MNN 运行时与模型版本不兼容;
- 模型损坏或 encoder/decoder 顺序传反;
- decoder 不符合静态 8 Prompt 槽位契约。
检查文件大小和校验值,并确认来源:
bash
ls -lh /path/to/encoder.mnn /path/to/decoder.mnn
sha256sum /path/to/encoder.mnn /path/to/decoder.mnn
再运行后端测试获得更明确的契约错误:
bash
ctest --test-dir build-qt -R MobileSamBackend --output-on-failure
9.12 Qt 报 could not connect to display
原因:当前终端没有可用的 X11/Wayland 显示环境,常见于 SSH、容器和 CI。
只做启动测试:
bash
QT_QPA_PLATFORM=offscreen \
./build-qt/SAMLabeler-MNN --smoke-test-ms 1500
需要人工操作 GUI 时,应在有桌面会话的终端运行,或正确配置 SSH X11 转发。不要把
offscreen 模式用于实际交互标注。
9.13 Qt 平台插件 xcb 无法初始化
典型信息:
text
Could not load the Qt platform plugin "xcb"
检查插件搜索过程:
bash
QT_DEBUG_PLUGINS=1 ./build-qt/SAMLabeler-MNN
检查 Qt 插件依赖:
bash
find /usr -name libqxcb.so 2>/dev/null | head
ldd /path/to/libqxcb.so | grep 'not found'
根据缺失库安装与当前 Qt 版本匹配的系统依赖,避免混用系统 Qt、Conda Qt 和自定义
Qt 的插件目录。必要时检查并清理当前 shell 中错误的 QT_PLUGIN_PATH,但应先记录
其原值。
9.14 编译进程被 Killed 或内存不足
原因通常是并行编译占用过多内存。
限制并行度:
bash
cmake --build build-qt --parallel 1
确认是否由 OOM 引起:
bash
dmesg | tail -n 50
free -h
也可关闭其他高内存程序,或在资源更充足的机器上构建。
9.15 修改代码后界面或行为没有变化
检查实际运行的是哪个二进制:
bash
realpath build-qt/SAMLabeler-MNN
stat build-qt/SAMLabeler-MNN
cmake --build build-qt --verbose
确认当前源码目录和构建目录匹配:
bash
grep '^SAMLabeler-MNN_SOURCE_DIR:' build-qt/CMakeCache.txt
项目移动后,旧构建目录可能仍引用旧绝对路径。此时应在新项目路径创建新的构建目录
并重新配置。
9.16 CTest 找不到测试或测试使用错误模型
先确认配置和测试列表:
bash
ctest --test-dir build-qt -N
grep '^SAMLabeler-MNN_SOURCE_DIR:' build-qt/CMakeCache.txt
测试中的模型路径在 CMake 配置时由源码目录生成。项目移动后应重新运行 CMake,
最好使用新构建目录,确保测试引用当前仓库的 data/models/。
9.17 图片目录为空或图片没有出现
确认目录包含受支持扩展名:PNG、JPG/JPEG、BMP、TIF/TIFF,并检查当前用户有读取
权限:
bash
find /path/to/images -maxdepth 1 -type f | head
namei -l /path/to/images
图像文件夹只负责源图片;如果误选标注输出目录,列表可能没有可识别的源图。
9.18 保存失败或项目无法恢复
检查:
- 标注文件夹是否已选择;
- 当前用户是否有目录写权限;
- 磁盘空间和 inode 是否充足;
project.json、categories.json与states/是否来自同一个项目保存过程;- 源图片文件名和尺寸是否被外部修改。
诊断命令:
bash
df -h /path/to/annotation-directory
df -i /path/to/annotation-directory
namei -l /path/to/annotation-directory
不要手工只移动 project.json 而遗漏其引用的 states/ 文件。迁移项目时应整体复制
标注文件夹,并保留相对目录结构。
10. 问题报告建议
提交问题时建议附上:
- 操作系统和 CPU 架构;
cmake --version、c++ --version;- Qt、OpenCV 和 MNN 版本;
- 完整 CMake 配置命令;
- 从第一条错误开始的完整构建或运行日志;
grep -E '^(MNN_ROOT|MNN_LIBRARY|CMAKE_BUILD_TYPE):' build-qt/CMakeCache.txt;ldd build-qt/SAMLabeler-MNN中与not found有关的行;- 是否使用默认模型、显式模型路径、桌面环境或 offscreen 模式。
请勿上传包含隐私的原始图片、业务标注、模型权重或本机凭据。必要时使用可公开的
最小复现数据,并对绝对路径和用户名做脱敏处理。