Ubuntu 18.04 部署 roLabelImg 旋转框标注工具实战指南

发布时间:2026/10/22 10:16:45
Ubuntu 18.04 部署 roLabelImg 旋转框标注工具实战指南
1. 为什么要在 Ubuntu 18.04 上折腾 roLabelImg如果你做过目标检测相关的标注工作大概率绕不开 LabelImg 这个工具。它轻量、上手快、支持 VOC 和 YOLO 格式导出几乎是入门标注的标配。但当你真正进入工业级场景尤其是处理遥感影像、航拍图、文档版面分析、工业质检这类数据时会发现一个很尴尬的问题标准 LabelImg 只能画水平矩形框遇到倾斜目标就彻底歇菜了。roLabelImg 就是在这个背景下出现的。它是 LabelImg 的一个分支版本核心增强点在于支持**旋转矩形框Rotated Bounding Box**的标注输出格式兼容 DOTA 数据集规范也能导出成带角度信息的 XML。简单说它能让你在图上画一个带旋转角度的框把斜着的飞机、船舰、路牌、文本行准确地框出来。这个工具本身并不复杂但它在 Ubuntu 18.04 上的部署和使用坑比想象中多。Ubuntu 18.04 自带的 Python 版本、Qt 库版本、PyQt5 与 Python 的绑定关系再加上 roLabelImg 本身代码里一些历史遗留问题导致很多人第一次跑起来就报错然后卡在环境配置上出不来。我前后在三台不同配置的 Ubuntu 18.04 机器上部署过这个工具踩过的坑包括但不限于libQt5Core.so版本冲突、sip模块缺失、canvas.py里的浮点运算报错、中文路径读取失败、标注文件角度值异常等等。这篇文章面向的是需要在 Ubuntu 18.04 上使用 roLabelImg 做旋转框标注的从业者不管你是做遥感解译、OCR 数据准备还是工业缺陷检测只要涉及倾斜目标标注这套流程都能直接参考。我会从环境准备讲起把依赖关系、安装步骤、参数配置、实操标注流程、常见报错排查全部拆开讲清楚最后再分享一些我在实际标注中总结出来的效率技巧和避坑经验。内容偏实操不堆理论能直接抄作业。2. 环境准备与依赖关系梳理2.1 Ubuntu 18.04 的 Python 环境现状Ubuntu 18.04 默认自带 Python 3.6.9这个版本本身不算太老但问题在于系统级的 Python 环境被大量系统工具依赖你如果直接用sudo pip3 install往系统环境里装包很容易把系统工具搞崩。我见过有人装完 PyQt5 之后系统自带的软件更新器直接打不开了就是因为 PyQt5 的版本和系统 Qt 库产生了冲突。所以第一步强烈建议用虚拟环境隔离。Python 3.6 自带的venv模块就够用了不需要额外装 virtualenv。创建虚拟环境的命令很直接sudo apt update sudo apt install python3-venv python3-pip -y python3 -m venv ~/rolabelimg_env source ~/rolabelimg_env/bin/activate激活之后你的终端提示符前面会出现(rolabelimg_env)字样后续所有 pip 安装都只影响这个虚拟环境不会污染系统。这一步看起来简单但它是后面所有操作不出问题的前提。2.2 系统级依赖库的安装roLabelImg 基于 PyQt5 构建界面而 PyQt5 在 Linux 上运行时需要一批系统级的 Qt 库支持。这些库不能用 pip 装必须用 apt。具体需要哪些取决于你的 Ubuntu 18.04 是最小化安装还是桌面完整版。如果你装的是桌面版大部分库已经有了如果是服务器版或者最小化安装需要手动补齐。我整理了一份实测可用的依赖清单sudo apt install -y libqt5gui5 libqt5core5a libqt5widgets5 \ libqt5xml5 libqt5svg5 libqt5opengl5 \ python3-pyqt5 python3-pyqt5.qtsvg \ libxcb-xinerama0 libxcb-icccm4 libxcb-image0 \ libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 \ libxcb-shape0 libxcb-xfixes0 libxkbcommon-x11-0这里面的libxcb-*系列库特别容易被忽略。PyQt5 在启动时会通过 xcb 插件连接显示服务如果缺少这些库程序会直接报could not load the Qt platform plugin xcb然后退出。这个报错非常常见很多人以为是 PyQt5 装错了其实是系统库没补齐。提示如果你是在纯命令行环境下操作没有图形界面roLabelImg 是跑不起来的因为它本质上是一个 GUI 工具。你需要确保操作环境有可用的显示服务或者通过远程桌面等方式接入图形界面。2.3 Python 包依赖的版本选择roLabelImg 的原始仓库里有一个requirements.txt但里面的版本约束比较宽松直接装最新版反而容易出问题。根据我的实测下面这套版本组合在 Ubuntu 18.04 Python 3.6.9 下最稳定包名推荐版本说明PyQt55.12.3与系统 Qt 5.9.5 兼容性最好lxml4.5.2解析 XML 标注文件numpy1.19.5最后支持 Python 3.6 的稳定版安装命令pip install PyQt55.12.3 lxml4.5.2 numpy1.19.5为什么不装最新版因为 PyQt5 5.15 之后的版本对 Python 3.6 的支持开始减弱而且和 Ubuntu 18.04 系统自带的 Qt 库版本差距太大容易出现符号冲突。numpy 1.20 之后也放弃了对 Python 3.6 的支持。所以这套版本组合不是随便选的是在兼容性和功能性之间找到的平衡点。2.4 roLabelImg 源码的获取与目录结构roLabelImg 的源码可以从公开的代码托管平台获取。下载下来之后先别急着运行花两分钟看一下目录结构对后面排查问题很有帮助roLabelImg/ ├── labelImg.py # 主入口 ├── canvas.py # 画布逻辑旋转框的核心实现 ├── shape.py # 形状定义包含旋转矩形的数据结构 ├── libs/ # 工具库 │ ├── labelFile.py # 标注文件读写 │ ├── yolo_io.py # YOLO 格式导出 │ └── ... ├── resources/ # 图标等资源 └── requirements.txt其中canvas.py和shape.py是旋转框功能的核心。如果你后续想改快捷键、改默认角度步长、改导出格式基本都在这两个文件里动手。我建议在正式标注之前先把这个目录备份一份因为标注过程中如果误改了源码恢复起来很麻烦。3. 安装部署与首次启动的完整流程3.1 从源码启动的正确姿势进入 roLabelImg 源码目录在虚拟环境激活的状态下执行cd ~/roLabelImg python labelImg.py如果一切正常会弹出一个图形界面窗口。但根据我的经验第一次启动大概率不会这么顺利。下面我按报错出现的频率从高到低排列逐个说明排查方法。3.2 常见启动报错与即时修复报错一ModuleNotFoundError: No module named libs这个问题的根源是 Python 的模块搜索路径没有包含当前目录。解决方法有两种一是用python -m方式运行二是手动设置 PYTHONPATH。export PYTHONPATH$PWD:$PYTHONPATH python labelImg.py报错二qt.qpa.plugin: Could not load the Qt platform plugin xcb前面提到的 xcb 库缺失问题。先确认库是否装全ldd ~/rolabelimg_env/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so | grep not found这条命令会列出所有缺失的动态库。根据输出结果用 apt 安装对应的包即可。常见的缺失包括libxcb-xinerama0、libxkbcommon-x11-0等。报错三TypeError: arguments did not match any overloaded call这个报错通常出现在canvas.py里原因是 PyQt5 版本差异导致某些方法签名不匹配。比如QPainter.drawText()在某些版本里不接受浮点数坐标。修复方法是把相关代码里的浮点数强制转成整数# 修改前 painter.drawText(x, y, text) # 修改后 painter.drawText(int(x), int(y), text)具体改哪一行报错信息里会给出文件名和行号照着改就行。报错四中文界面乱码或中文路径读取失败Ubuntu 18.04 的默认 locale 可能是C.UTF-8或者en_US.UTF-8导致中文显示异常。检查当前 localelocale如果LANG不是zh_CN.UTF-8或en_US.UTF-8建议设置成 UTF-8export LANGen_US.UTF-8 export LC_ALLen_US.UTF-8另外标注文件的路径里尽量避免中文和空格虽然理论上支持但实际用下来中文路径在某些导出环节还是会出问题。3.3 首次启动后的界面配置程序启动后先别急着打开图片。有几个配置项需要提前设好否则后面标注效率会大打折扣。点击左侧工具栏的PascalVOC按钮切换到PascalVOC格式roLabelImg 默认就是这个但确认一下更稳妥。然后勾选View菜单里的Auto Save mode这样每次画完一个框、切换到下一张图时标注会自动保存不用手动按 CtrlS。这个习惯能帮你省下大量重复操作。还有一个关键设置是Save目录。默认情况下标注文件会保存在图片同级目录。如果你的图片和标注需要分开存放可以在File菜单里设置Change Save Dir指定一个专门的标注输出目录。我个人的习惯是图片放images/标注放annotations/两个目录平级方便后续训练脚本读取。4. 旋转框标注的核心操作与参数详解4.1 旋转矩形的数据结构长什么样在讲操作之前先搞清楚 roLabelImg 输出的旋转框到底是怎么表示的。这直接关系到你后续怎么解析标注文件、怎么转换成训练框架需要的格式。roLabelImg 的标注文件是 XML 格式一个典型的旋转框节点长这样object namevehicle/name poseUnspecified/pose truncated0/truncated difficult0/difficult robndbox cx512.0/cx cy384.0/cy w120.0/w h60.0/h angle0.785/angle /robndbox /object和标准 VOC 格式最大的区别在于bndbox变成了robndbox里面用cx, cy, w, h, angle五个参数来描述一个旋转矩形。cx, cy是矩形中心的像素坐标w, h是矩形的宽和高angle是旋转角度单位是弧度范围是[-π/2, π/2]。这里有一个非常容易踩的坑angle 的参考方向。roLabelImg 里角度是相对于水平方向的旋转量逆时针为正。但不同版本的代码在这个定义上可能有细微差异有的版本是顺时针为正。我建议你在正式标注之前先画一个明显倾斜的框导出 XML 看一眼角度值的正负确认清楚再批量操作。否则标了几百张之后发现角度方向反了返工成本极高。4.2 画旋转框的完整操作流程打开一张图片后画旋转框的操作和普通矩形框类似但多了旋转步骤。具体流程如下按W键或者点击左侧的Create RectBox按钮进入画框模式。在目标左上角按下鼠标左键拖到右下角松开先画出一个水平矩形。此时矩形四个角会出现控制点。把鼠标移到矩形边线中间的控制点上光标会变成旋转样式。按住鼠标左键拖动矩形就会绕中心旋转。转到和目标方向对齐后松开。在弹出的类别输入框里输入标签名回车确认。这里有个细节旋转的控制点是在边的中点不是在角上。角上的控制点是用来缩放矩形的。很多人第一次用的时候找不到旋转入口就是因为一直在角上找。注意旋转的时候矩形的宽高会随着旋转发生变化。如果你先画了一个很扁的矩形再旋转旋转后宽高可能会互换。建议先画一个大致覆盖目标的框旋转对齐后再微调宽高。4.3 快捷键体系与效率提升roLabelImg 的快捷键和 LabelImg 基本一致但有几个在旋转框场景下特别有用快捷键功能使用场景W创建新框开始标注新目标A上一张图回看检查D下一张图快速推进CtrlS保存手动保存当前标注CtrlR修改当前框类别标错类别时快速修正Delete删除选中框删除误标的框方向键微调框位置精细调整我个人的习惯是左手放在 W、A、D 三个键上右手握鼠标形成画框-切图-画框的流水线节奏。熟练之后一张有十几个目标的图标注时间可以控制在两分钟以内。另外Edit菜单里有一个Rotate功能可以对选中的框进行精确角度旋转。如果你需要标注的角度非常精确比如文本行标注要求角度误差小于1度用鼠标拖拽很难做到这时候就用Rotate功能手动输入角度值。4.4 类别管理与预定义标签如果你的标注任务涉及多个类别每次都手动输入标签名效率很低而且容易打错字。roLabelImg 支持预定义标签列表。在源码目录下创建一个predefined_classes.txt文件每行一个类别名vehicle ship aircraft storage_tank harbor然后在界面里勾选View菜单下的Use default label之后画框时就会弹出下拉列表让你选不用再手动输入。这个功能在多类别标注任务里能显著降低出错率。5. 标注数据的导出、转换与质量检查5.1 导出格式的选择与差异roLabelImg 支持多种导出格式但在旋转框场景下真正可用的其实只有 PascalVOC 格式也就是带robndbox的 XML。YOLO 格式的导出在旋转框支持上并不完整导出的还是水平框的坐标角度信息会丢失。所以如果你要做旋转目标检测训练标注阶段就用 PascalVOC 格式后续再写脚本转换成训练框架需要的格式。这一点很重要我见过有人标完之后直接导出 YOLO 格式结果角度全丢了几百张标注白做。记住roLabelImg 的旋转框信息只完整保存在 PascalVOC XML 里。5.2 从 XML 到训练格式的转换思路不同训练框架对旋转框的格式要求不一样。常见的几种表示方式包括DOTA 格式x1 y1 x2 y2 x3 y3 x4 y4 category difficult四个角点的坐标。COCO 旋转格式[cx, cy, w, h, angle]和 roLabelImg 的输出基本一致。四边形格式直接给四个顶点坐标。从 roLabelImg 的cx, cy, w, h, angle转换成四个角点坐标核心就是旋转矩阵运算。下面是一段可直接用的 Python 转换代码import math def rolabelimg_to_dota(cx, cy, w, h, angle): # 计算四个角点相对于中心的偏移 dx w / 2.0 dy h / 2.0 corners [(-dx, -dy), (dx, -dy), (dx, dy), (-dx, dy)] # 旋转矩阵 cos_a math.cos(angle) sin_a math.sin(angle) points [] for x, y in corners: rx x * cos_a - y * sin_a cx ry x * sin_a y * cos_a cy points.extend([rx, ry]) return points这段代码的逻辑很直白先把矩形四个角相对于中心的偏移算出来然后用旋转矩阵旋转最后平移回中心坐标。注意 angle 的正负方向要和你的标注定义一致如果发现转出来的框方向反了把sin_a的符号取反即可。5.3 标注质量的批量检查方法标注做完之后一定要做质量检查。人工一张张看效率太低我通常写一个脚本做自动化检查重点查以下几类问题第一类坐标越界。检查cx, cy是否在图片尺寸范围内w, h是否为正数。如果出现负数宽高或者中心点跑到图片外面说明标注时出了问题。第二类角度异常。正常角度范围是[-π/2, π/2]如果出现超出这个范围的值可能是旋转操作时出了问题。第三类类别名拼写。统计所有出现过的类别名和预定义列表对比找出拼写不一致的。第四类空标注文件。有些图片可能确实没有目标但也要确认不是漏标。下面是一个检查脚本的框架import os import xml.etree.ElementTree as ET import math def check_annotation(xml_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() issues [] for obj in root.findall(object): name obj.find(name).text robndbox obj.find(robndbox) if robndbox is None: issues.append(f缺少robndbox: {name}) continue cx float(robndbox.find(cx).text) cy float(robndbox.find(cy).text) w float(robndbox.find(w).text) h float(robndbox.find(h).text) angle float(robndbox.find(angle).text) if w 0 or h 0: issues.append(f宽高异常: {name} w{w} h{h}) if cx 0 or cx img_w or cy 0 or cy img_h: issues.append(f中心越界: {name} cx{cx} cy{cy}) if abs(angle) math.pi / 2: issues.append(f角度异常: {name} angle{angle}) return issues这个脚本可以批量跑整个标注目录把有问题的文件列出来然后针对性修复。比人工翻看效率高得多。6. 实操中遇到的典型问题与排查实录6.1 标注文件保存失败或保存为空这个问题我遇到过好几次表现是画完框之后按 CtrlS看起来保存了但打开 XML 文件发现里面是空的或者只有图片基本信息没有 object 节点。排查下来原因通常有两个。第一个是保存目录没有写权限。如果你把保存目录设到了一个需要 root 权限的位置程序写入时会静默失败。解决方法就是chmod给写权限或者换一个用户目录下的路径。第二个原因是图片文件名包含特殊字符。比如文件名里有#、、空格等在某些版本的代码里会导致 XML 写入异常。建议在标注之前先把图片文件名批量规范化只保留字母、数字、下划线和短横线。# 批量重命名示例 for f in *.jpg; do newname$(echo $f | sed s/[^a-zA-Z0-9._-]/_/g) mv $f $newname done6.2 旋转框显示异常或拖拽卡顿在标注大尺寸图片比如 4000x3000 以上的遥感图时roLabelImg 可能会出现拖拽卡顿、框显示错位的情况。这主要是 Qt 的渲染性能问题不是程序 bug。我的处理办法是先把大图切分成小块再标注。比如把 4000x3000 的图切成 1000x1000 的瓦片标注完再合并。这样不仅标注流畅而且后续训练时也需要切图一举两得。切图可以用 GDAL 或者 OpenCV 写个简单脚本import cv2 def split_image(img_path, output_dir, tile_size1000, overlap100): img cv2.imread(img_path) h, w img.shape[:2] idx 0 for y in range(0, h, tile_size - overlap): for x in range(0, w, tile_size - overlap): tile img[y:ytile_size, x:xtile_size] cv2.imwrite(f{output_dir}/tile_{idx}.jpg, tile) idx 1overlap 设置为 100 像素是为了避免目标被切断。切图之后标注最后再把坐标映射回原图这是遥感标注的标准流程。6.3 角度值在转换后出现偏差有朋友反馈说在 roLabelImg 里看着框是对齐的但转成 DOTA 格式之后框的方向偏了。这个问题十有八九是角度定义不一致导致的。roLabelImg 内部的角度定义、XML 里保存的角度值、以及你转换脚本里用的角度定义这三者必须统一。我的建议是拿一张有明显倾斜目标的图在 roLabelImg 里标一个框导出 XML然后手动用转换脚本算一遍四个角点把角点画回图上看是否和原框重合。如果不重合就调整转换脚本里的角度符号或旋转方向直到完全对齐。这个验证步骤花不了十分钟但能避免后面几千张标注全部返工。6.4 常见问题速查表问题现象可能原因解决方法启动报 xcb 插件加载失败系统缺少 xcb 相关库apt 安装 libxcb-* 系列库画框后无法旋转没找对控制点位置鼠标移到边线中点不是角点保存的 XML 为空目录无写权限或文件名特殊字符检查权限规范化文件名角度转换后方向反了角度定义不一致验证并调整转换脚本符号大图标注卡顿Qt 渲染性能瓶颈切图后标注再合并坐标中文标签显示乱码locale 设置问题设置 LANGen_US.UTF-8导出的 YOLO 格式没有角度格式本身不支持旋转框用 PascalVOC 格式后续转换7. 提升标注效率的实战经验7.1 建立自己的标注规范文档在开始批量标注之前花半小时写一份标注规范把以下内容定清楚类别定义和边界、旋转框的贴合标准是紧贴目标还是留一点余量、最小可标注目标尺寸、遮挡目标的处理方式、角度标注的精度要求。这份文档看起来是额外工作但实际用下来它能帮你省下大量返工时间。尤其是多人协作标注时没有规范文档不同人标出来的框风格差异很大后续训练效果会受影响。7.2 分批标注与交叉检查不要一次性标完所有数据再检查。我的做法是每标 100 张就停下来做一次抽查随机抽 10 张检查质量。如果发现系统性问题比如某个类别定义不清、角度方向标反了及时修正避免错误累积。抽查的时候可以用前面提到的检查脚本先跑一遍自动化检查再人工看几张。自动化检查能抓住坐标越界、角度异常这类硬错误人工检查则关注框的贴合度和类别正确性。7.3 利用预标注减少重复劳动如果你的数据里同类目标比较多可以考虑先用一个粗略训练的模型做预标注然后导入 roLabelImg 里微调。roLabelImg 支持读取已有的 XML 标注文件你可以把模型输出的旋转框转成 roLabelImg 格式的 XML然后人工只需要微调角度和边界不用从零画框。这个流程的前提是你已经有一个能输出旋转框的模型。如果没有也可以先用水平框模型做预标注导入后手动旋转调整。虽然还是要人工旋转但至少省去了画框和输入类别的步骤。7.4 定期备份标注文件标注数据是真正的劳动成果丢了就没了。我建议每天标注结束后把标注目录打包备份一次。可以用简单的tar命令tar -czf annotations_backup_$(date %Y%m%d).tar.gz annotations/如果标注量大可以配合rsync同步到另一块硬盘或者网络存储。这个习惯看起来不起眼但真出问题的时候能救命。我见过有人标了两周的数据因为硬盘故障全没了只能从头再来。8. 从标注到训练的数据流转建议标注只是第一步标注数据最终要喂给训练框架。这里简单说一下数据流转的链路帮你把整个流程串起来。roLabelImg 输出 PascalVOC XML这是标注的原始格式建议永久保存。然后写一个转换脚本把 XML 转成训练框架需要的格式。如果你用的是基于 DOTA 的旋转检测框架就转成 DOTA 格式的 txt如果用 COCO 风格的框架就转成 COCO JSON 的旋转框扩展格式。转换之后建议做一次可视化验证把转换后的框画回原图和原标注对比确认没有偏差。这个验证步骤可以用 OpenCV 写个简单脚本完成import cv2 import numpy as np def draw_rotated_box(img, cx, cy, w, h, angle, color(0, 255, 0)): rect ((cx, cy), (w, h), np.degrees(angle)) box cv2.boxPoints(rect) box np.int0(box) cv2.drawContours(img, [box], 0, color, 2) return img把转换后的参数传进去画出来的框如果和原图目标对齐说明转换没问题。这个验证做一次就够了确认脚本正确之后后续批量转换都可以放心用。数据集的划分也要在转换阶段完成。通常按 8:1:1 划分训练集、验证集、测试集。划分时要注意同一场景的图片尽量分到同一个集合避免数据泄漏。比如同一张遥感大图切出来的瓦片应该全部放在训练集或者全部放在测试集不能混着放。最后再分享一个小技巧在标注目录里放一个README文件记录标注规范、类别列表、标注人员、标注日期、使用的 roLabelImg 版本。过几个月再回头看这批数据这些信息能帮你快速回忆起当时的标注背景避免因为时间久了记不清而误用数据。