P&ID / DWG 识图抽取 —— macOS 实战 SOP
适用:用户(流程模拟工程师,常处理 P&ID / 设备布置图 DWG)在 macOS 上用 drawing-extractor 技能识别工程图纸。
底层技能:drawing-extractor__skillhub(位于 ~/.workbuddy/skills/drawing-extractor__skillhub)。
关键结论(先读)
- 本流程是信息抽取层,不是工艺理解层:能抽全文字/位号/图块+坐标,但不重建工艺拓扑(不解析连线),也不解析表格行/列(只做扁平文字清单)。
- 工艺拓扑只能来自独立的《管道数据表/管线表》的 from/to 列,本 skill 不会自动「表格→图」。
- DWG 必须经 ODA 转 DXF(或让用户另存 DXF)才能抽;macOS 无 ODA 时需手动下载。
环境踩坑(本机实测,必看)
- 本机无 sudo、brew 被 Xcode license 卡死、conda 无 libredwg → 本地 DWG→DXF 编译路线全堵。
- managed python venv 的 pip 指向私有索引,
pip install Pillow报 "from versions: none"。
→ 改用 anaconda python 建 venv +--system-site-packages(anaconda 自带 Pillow/fitz/openpyxl),只额外装ezdxf、pytesseract。 - soffice(LibreOffice)无 DWG 过滤器,
--convert-to dxf报 "source file could not be loaded" → 此路不通。 - ODA 官方 macOS 包:opendesign.com 可达。先用浏览器/curl 打开
https://www.opendesign.com/guestfiles/oda_file_converter,
从页面 HTML 里抓取*.dmg链接(Apple Silicon 形如ODAFileConverter_QT6_macOsX_arm64_*.dmg)。
⚠️ 该下载链接是 60 秒有效的 S3 签名 URL,会过期;若抓到的链接 404,重新打开页面抓新链接即可。
下载后hdiutil attach xxx.dmg -nobrowse(无需 sudo),二进制在:
/Volumes/ODA ODAFileConverter sample/ODAFileConverter.app/Contents/MacOS/ODAFileConverter - ODA CLI 是 GUI app,
--help会挂起无输出。正确用法是 6 参命令行(见下),转换完进程不自动退出,需轮询产物后杀进程。
标准流程
# 0) venv(anaconda + system-site-packages,避开私有 pip 源)
ANA=/Applications/anaconda3/bin/python3
VENV=~/.workbuddy/drawing-extractor-venv
"$ANA" -m venv --system-site-packages "$VENV"
"$VENV/bin/pip" install "ezdxf>=1.3,<2" "pytesseract>=0.3,<1"
# 1) 复制原 DWG 到工作区(只读保护原文件)
mkdir -p ~/WorkBuddy/<proj>/pid_drawing/{src,out}
cp "<原图>.dwg" ~/WorkBuddy/<proj>/pid_drawing/src/
# 2) DWG→DXF(ODA 六参 CLI:源目录 输出目录 版本 DXF audit recursive)
ODA="/Volumes/ODA ODAFileConverter sample/ODAFileConverter.app/Contents/MacOS/ODAFileConverter"
SRC=~/WorkBuddy/<proj>/pid_drawing/out/_src/pid
DXF=~/WorkBuddy/<proj>/pid_drawing/out/_dxf/pid
mkdir -p "$SRC" "$DXF"; cp src/<图>.dwg "$SRC"/
"$ODA" "$SRC" "$DXF" ACAD2018 DXF 1 0
# 产物: $DXF/<图名>.dxf(ODA 不自动退出,轮询到文件大小稳定即杀进程)
# 3) 抽取 + 出表(直接喂 DXF,跳过 ODA;矢量图无需 OCR)
SKILL=~/.workbuddy/skills/drawing-extractor__skillhub
"$VENV/bin/python" "$SKILL/scripts/run_all.py" \
--input "$DXF/<图名>.dxf" --outdir ~/WorkBuddy/<proj>/pid_drawing/out \
--table --no-offline-ocr
# 产出: <图名>.extract.json / <图名>.xlsx(带标记列) / 自检.md / 自检汇总.md
# 4) 位号核查(run_all 单文件时不跑,手动调)
"$VENV/bin/python" - <<'PY'
import sys; sys.path.insert(0, "$SKILL/scripts")
import check_tags
idx,n = check_tags.scan("<outdir>")
bad=check_tags.check_naming(idx); conf=check_tags.check_conflicts(idx)
open("<outdir>/位号核查.md","w").write(check_tags.build_md(idx,n,bad,conf))
# idx: {tag: [{tag,file,page,type_guess,class}]} class∈device/instrument/pipe
PY
实测数据(参考量级)
- 一份 P&ID 2B 版 DWG(3.1MB)→DXF(21.7MB),抽取 6771 文字 / 602 图块 / 247 位号(设备20 仪表148 管道79),自检高置信。
- 管道号结构:
介质-线号-DN-等级,如FML-2406-150-600E6(DN150/600LB/E6材质)。 - 版本修改注释藏在
2B/2C/R版/入库前/报价阶段发送后修改图层,可单独捞 66 条工程变更说明。
能力边界(对客户/自己都要照实说)
- ✅ 矢量文字/位号/管道号/仪表号/表格文字 ≈100% 准,坐标完整可回图定位。
- ⚠️ 匿名图块(
A$…)认不出具体是什么阀/仪表:CAD 代理无名块,只能靠图例或多模态截图补认。 - ⚠️ 不重建工艺拓扑:只抽孤立文字/图块占位,不解析 LINE/POLYLINE 连线与设备接口连接点。
- ⚠️ 不解析表格行/列:extract_dxf/make_table 只做扁平文字清单,SKILL.md 所谓"按坐标重建表格"本版未实现。
- ⚠️
DN100/DN135…会被分类器误标为"仪表"(实为管径),使用时剔除。 - ⚠️ 工艺拓扑只能从独立的《管道数据表/管线表》(带 from/to) 抽取得到;P&ID 图形本身不含该表。
给客户的下一步话术
"拓扑不在管道号里,在管道数据表的 from/to 列里。本 skill 能抽到表,但建表→建图最后一步要另做;且这份图没有那张表。如有独立管线表(PDF/DWG/Excel),我走路线 A:抽取+重建为「起点→终点→介质→管径」边表,再渲染拓扑图。"