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_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 工程文件、过程、配置、数据、输出、依赖和入口脚本之间的依赖关系集中呈现出来,便于理解“谁调用谁、谁依赖谁”。
从骨架到可复现:一个最小闭环
把上述内容串起来,一个可复现的最小闭环是:入口脚本检查环境 → 读取配置 → 调用 main.hdev → main.hdev 调用过程库 → 过程库读取 data/ 中的图像和模型 → 结果写入 output/ → 入口脚本检查结果文件是否存在。这个闭环中,任何一环缺失都会导致“换机失败”。例如,配置里写死了 D:\images\batch01,换到 Linux 就找不到;依赖里没写 HALCON 版本,升级后算子行为变化;输出目录不存在,程序直接报错。
建议在项目初期就建立 docs/README.md,写明:HALCON 版本、许可证类型、运行命令、配置字段含义、结果文件格式。每次修改参数或 ROI,在 changelog.md 中记录日期、修改人、修改内容和原因。这样即使原开发者离开,接手人也能在半天内跑通并理解工程。
src/export/,并在 README 中说明导出时的 HALCON 版本和编译选项。导出代码与 .hdev 应保持同步,避免“脚本改了、导出没更新”的常见问题。最后强调一点:工程骨架不是一次性设计完就固定不变的。随着产品型号增加、相机更换、算法迭代,目录和配置需要演进。关键是保持“代码、配置、数据、输出、依赖”五类边界清晰,任何新增内容都能归入其中一类。做到这一点,HALCON 项目才真正具备可复现、可交接、可维护的工程属性。