2. HALCON开发环境与工程骨架

在工业视觉项目里,算法本身往往只占最终交付的一部分。真正决定项目能否被复现、被交接、被长期维护的,是开发环境与工程骨架是否稳定。HALCON 提供了 HDevelop 这一集成开发环境,它既能交互式调试算子,也能导出可被 C++、C#、Python 调用的程序。但很多团队把 HDevelop 当成“临时试验工具”,脚本散落在桌面、参数写死在代码里、依赖版本靠记忆,最终导致换一台机器就运行失败。本节要解决的就是:如何把 HDevelop 从“个人调试器”升级为“可复现工程”的入口。

HDevelop 与 HDevelop 脚本的定位

HDevelop 的核心产物是 .hdev 程序文件,内部由若干过程(procedure)组成,每个过程包含算子序列、变量、控制流和参数。它有两种典型使用方式:一是交互式执行,逐行运行并观察图像、区域、轮廓、测量结果;二是导出为脚本或代码,供外部程序调用。需要区分两个概念:.hdev 是 HDevelop 工程文件,而“HDevelop 脚本”通常指可被 hdevengine 加载执行的程序文件,也可导出为 .hdvp 等格式。工程化时,建议把“可复用过程”与“顶层执行流程”分开:过程负责图像处理、标定、测量、通信等原子能力,顶层流程负责编排、参数注入和结果输出。

一个常见的误区是把所有逻辑写在一个过程里,导致无法单独测试。更合理的做法是:每个过程只做一件事,输入输出明确,例如 read_image_safe、calibrate_camera、measure_pin_distance、send_result_tcp。这样在 HDevelop 中可单独运行验证,导出后也能被外部程序按需调用。

项目目录规范

目录结构是工程骨架的物理体现。推荐按“代码、配置、数据、输出、文档、依赖”六类划分,避免把图像、日志、模型混在一起。下面给出一个可直接落地的目录示例:

vision_project/
├─ src/
│  ├─ main.hdev              # 顶层流程,负责编排
│  ├─ procedures/
│  │  ├─ preprocess.hdvp
│  │  ├─ calibrate.hdvp
│  │  └─ measure.hdvp
│  └─ export/
│     └─ vision_core.cpp     # 导出给 C++ 调用的代码
├─ config/
│  ├─ camera.yaml            # 相机参数、曝光、增益
│  ├─ calib.yaml             # 标定板参数、标定结果路径
│  └─ recipe.yaml            # 产品配方:ROI、阈值、公差
├─ data/
│  ├─ images/                # 原始图像,按批次或日期分目录
│  ├─ calib/                 # 标定图像与标定文件
│  └─ models/                # 形状模板、OCR 模型等
├─ output/
│  ├─ logs/                  # 运行日志
│  ├─ results/               # 测量结果 CSV/JSON
│  └─ debug/                 # 中间图像、区域可视化
├─ docs/
│  ├─ README.md              # 环境要求、运行方式
│  └─ changelog.md           # 版本变更记录
├─ deps/
│  └─ requirements.txt       # HALCON 版本、Python 包、外部依赖
└─ run.bat / run.sh          # 一键运行入口

关键原则是:代码与数据分离、配置与逻辑分离、输出与源码分离。图像路径、标定文件路径、结果输出路径都应通过配置文件或环境变量注入,而不是硬编码在 .hdev 中。这样同一套代码可以在开发机、测试机、产线机上运行,只需切换配置。

版本控制与依赖记录

HALCON 工程纳入 Git 时,要注意二进制与大文件问题。.hdev 是文本格式,适合版本控制;但图像、标定文件、模型文件通常较大,建议使用 Git LFS 或单独的数据仓库。每次提交应附带变更说明,尤其是参数调整、ROI 修改、阈值变化,这些直接影响检测结果。

依赖记录至少包含三类:HALCON 版本(如 HALCON 20.11 Progress)、外部库版本(如 OpenCV、NumPy)、以及运行时环境(操作系统、编译器、Python 版本)。建议在 deps/requirements.txt 中明确写出,并在 README 中说明安装顺序。HALCON 的许可证类型(开发版、运行版)也应记录,因为运行版和开发版在算子可用性上可能不同。

不要只记录“HALCON 最新版”。工业现场往往锁定版本,升级前必须回归测试。建议在配置文件中写入 halcon_version: 20.11,启动时校验,不匹配则给出明确提示。

一键运行入口设计

一键运行入口的目标是:任何人拿到工程,执行一条命令就能跑通示例。入口脚本应完成四件事:检查环境、加载配置、执行主流程、输出结果与日志。下面是一个 run.bat 的示例(Windows 环境,示例参数为合理假设):

@echo off
setlocal
set PROJECT_ROOT=%~dp0
set CONFIG=%PROJECT_ROOT%config\recipe.yaml
set LOG_DIR=%PROJECT_ROOT%output\logs
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"

echo [1/4] 检查 HALCON 环境...
where hdevelop >nul 2>nul
if errorlevel 1 (
  echo 未找到 HDevelop,请检查 PATH 或 HALCONROOT
  exit /b 1
)

echo [2/4] 加载配置: %CONFIG%
if not exist "%CONFIG%" (
  echo 配置文件缺失: %CONFIG%
  exit /b 1
)

echo [3/4] 执行主流程...
hdevelop -r "%PROJECT_ROOT%src\main.hdev" -config "%CONFIG%" -log "%LOG_DIR%\run_%date:~0,4%%date:~5,2%%date:~8,2%.log"

echo [4/4] 检查输出...
if exist "%PROJECT_ROOT%output\results\result.json" (
  echo 运行成功,结果已生成。
) else (
  echo 运行失败,请查看日志。
  exit /b 2
)
endlocal

在 Linux 下对应 run.sh,逻辑一致。入口脚本不要写复杂业务逻辑,只做环境检查、参数传递和结果判断。真正的图像处理仍在 .hdev 中完成。这样调试时可以在 HDevelop 里单独运行,交付时用入口脚本统一执行。

工程骨架的整体关系

下图把 HDevelop 工程文件、过程、配置、数据、输出、依赖和入口脚本之间的依赖关系集中呈现出来,便于理解“谁调用谁、谁依赖谁”。

HALCON 工程骨架与依赖关系 一键运行入口 run.bat / run.sh 环境检查 · 参数传递 顶层流程 main.hdev 编排 · 参数注入 · 结果汇总 调用各过程 过程库 procedures/ preprocess · calibrate · measure 可单独运行验证 配置 config/ camera.yaml calib.yaml · recipe.yaml 数据 data/ images · calib · models 按批次/日期组织 输出 output/ logs · results · debug 结果 JSON / CSV · 中间图像 依赖 deps/ HALCON 版本 外部库 · 运行时环境 版本控制 Git .hdev 文本跟踪 大文件用 LFS 文档 docs/ README · changelog 环境要求 · 运行方式 图例: 调用/执行 参数注入 依赖约束 文档指导 说明:实线表示运行时调用或数据传递,虚线表示工程约束与文档依赖。

从骨架到可复现:一个最小闭环

把上述内容串起来,一个可复现的最小闭环是:入口脚本检查环境 → 读取配置 → 调用 main.hdev → main.hdev 调用过程库 → 过程库读取 data/ 中的图像和模型 → 结果写入 output/ → 入口脚本检查结果文件是否存在。这个闭环中,任何一环缺失都会导致“换机失败”。例如,配置里写死了 D:\images\batch01,换到 Linux 就找不到;依赖里没写 HALCON 版本,升级后算子行为变化;输出目录不存在,程序直接报错。

建议在项目初期就建立 docs/README.md,写明:HALCON 版本、许可证类型、运行命令、配置字段含义、结果文件格式。每次修改参数或 ROI,在 changelog.md 中记录日期、修改人、修改内容和原因。这样即使原开发者离开,接手人也能在半天内跑通并理解工程。

如果团队使用 HDevelop 的“导出为 C++”功能,建议把导出代码放在 src/export/,并在 README 中说明导出时的 HALCON 版本和编译选项。导出代码与 .hdev 应保持同步,避免“脚本改了、导出没更新”的常见问题。

最后强调一点:工程骨架不是一次性设计完就固定不变的。随着产品型号增加、相机更换、算法迭代,目录和配置需要演进。关键是保持“代码、配置、数据、输出、依赖”五类边界清晰,任何新增内容都能归入其中一类。做到这一点,HALCON 项目才真正具备可复现、可交接、可维护的工程属性。