2. HALCON项目代码的基本构成

在HALCON视觉项目中,代码并不是“一个文件写完所有逻辑”的形态。一个可维护、可复用的项目,通常由若干层次不同的代码单元组成:最底层是HALCON算子(Operator),其上是外部过程(External Procedure)与函数(Procedure/Function),再往上是HDevelop程序(Program)与库(Library),最终由项目文件(Project File)把这些单元组织在一起。理解这些单元的边界与调用关系,是识别“哪些代码值得复用、应该以什么粒度复用”的前提。

一、从算子到过程:代码单元的四个层级

HALCON算子是最小执行单元,例如 read_image、threshold、connection、select_shape、gen_rectangle1。算子由HALCON运行时提供,用户不能修改其内部实现,只能通过参数调用。算子的输入输出以图标参数(Iconic)和控制参数(Control)区分,这一约定贯穿整个HALCON代码体系。

外部过程是用户用HDevelop语言编写、可被其他程序调用的过程文件,扩展名通常为 .hdvp。它有自己的过程名、输入输出参数和局部变量,是HALCON项目中最主要的复用单元。一个外部过程可以封装“图像预处理”“ROI提取”“形状匹配定位”“标定转换”等完整功能。与外部过程相对的是“本地过程”(Local Procedure),它写在某个HDevelop程序内部,只对该程序可见,适合一次性逻辑,不适合跨项目复用。

函数在HDevelop语境中通常指带返回值的Procedure,或通过 procedure 定义、以表达式形式调用的过程。它强调“输入参数→计算→返回结果”的映射关系,适合封装数学计算、坐标变换、参数校验等无状态逻辑。库则是若干过程与函数的集合,可以是HDevelop库(.hdpl)或外部语言库(如C++、C#封装),用于按业务域或功能域批量管理复用单元。

二、项目文件如何组织这些单元

HDevelop程序(.hdev)是开发与调试的入口,它记录主程序流程、本地过程、外部过程引用路径以及程序参数。项目文件(.hproj)则进一步把多个HDevelop程序、外部过程、图像资源、标定文件等组织为一个工程视图。典型组织方式是按“功能域”分目录:

VisionProject/
├── project.hproj
├── main/
│   └── inspect_main.hdev
├── procedures/
│   ├── preprocess.hdvp
│   ├── locate_part.hdvp
│   ├── measure_geometry.hdvp
│   └── calib_transform.hdvp
├── libraries/
│   └── vision_common.hdpl
├── config/
│   ├── camera_params.hdvp
│   └── roi_config.hdvp
└── images/
    └── sample_001.png

这种结构的关键在于:main 只负责流程编排与结果汇总,具体算法逻辑下沉到 procedures;跨项目通用的过程进入 libraries;与现场相关的参数、ROI、标定数据放入 config,避免硬编码在算法过程中。这样,当相机更换或工位调整时,只需修改配置层,算法过程保持不变。

三、调用关系与数据流

HALCON代码的调用关系是“主程序→外部过程→算子”的逐层下沉。主程序通过过程名和参数列表调用外部过程,外部过程内部再调用HALCON算子或其他外部过程。数据以图标变量(Image、Region、XLD)和控制变量(整数、实数、字符串、句柄)在层间传递。识别可复用单元时,应重点观察:哪些过程被多个主程序调用、哪些过程的输入输出参数稳定、哪些过程内部只依赖HALCON算子而不依赖现场配置。

HALCON项目代码单元与调用关系 项目文件层(.hproj) main/*.hdev procedures/*.hdvp libraries/*.hdpl config/*.hdvp images/ HDevelop主程序(.hdev) 流程编排 · 结果汇总 · 参数传入 preprocess.hdvp 灰度化 · 滤波 · 增强 输入: Image → 输出: Image locate_part.hdvp 模板匹配 · 位姿求解 输入: Image → 输出: Pose measure_geometry.hdvp 边缘提取 · 尺寸测量 输入: Image+Pose → 输出: 尺寸 HALCON算子层(Operator) read_image threshold connection select_shape find_shape_model vector_angle_to_rigid 可复用单元判定 参数稳定 · 无现场依赖 被≥2个主程序调用

四、如何识别可复用单元

识别可复用单元不能只看“代码是否重复”,而应从三个维度判断。第一是参数稳定性:过程的输入输出参数是否已经收敛,不会因为换一个工位就全部改变。第二是依赖边界:过程内部是否只依赖HALCON算子和自身参数,而不直接读取某个固定路径的图像或某个写死的相机句柄。第三是调用频次:同一段逻辑是否在两个以上主程序或两个以上工位中出现。

以“定位”为例,如果 locate_part.hdvp 内部把模板文件路径、匹配分数阈值、角度范围都写成常量,那么它只能用于当前工位,复用价值低。更合理的做法是把模板句柄、最小分数、角度搜索范围作为输入参数,把位姿作为输出参数,模板文件由主程序或配置过程加载。这样,同一过程可以用于不同工位,只需传入不同的模板和阈值。

判断一个过程是否值得进入库(.hdpl),可以用一个简单标准:把它复制到另一个项目时,是否需要修改过程内部代码?如果不需要修改,只需改变调用参数,它就具备库级复用价值;如果需要修改内部常量或路径,则应先做参数化改造,再考虑入库。

五、一个可参考的复用单元清单

下表给出HALCON视觉项目中常见的复用单元及其建议归属,可作为整理现有项目代码时的对照参考。表中“归属”指该单元应放在项目目录的哪一层,“复用级别”指它适合在项目内复用还是跨项目复用。

单元名称 类型 典型输入 典型输出 归属 复用级别
preprocess 外部过程 Image, 滤波参数 Image procedures/ 项目内
locate_part 外部过程 Image, 模板句柄, 分数阈值 Pose procedures/ 项目内/跨项目
calib_transform 外部过程 Pose, 标定参数 物理坐标 libraries/ 跨项目
measure_geometry 外部过程 Image, Pose, ROI 尺寸数组 procedures/ 项目内
load_camera_params 函数 配置文件路径 相机参数字典 config/ 项目内
check_result_range 函数 测量值, 上下限 OK/NG libraries/ 跨项目

六、组织方式对复用的影响

项目文件组织方式直接决定复用成本。如果所有过程都堆在同一个 .hdev 里作为本地过程,其他项目无法直接引用,只能复制粘贴,后续维护会出现多份副本。如果外部过程分散在多个目录且没有统一命名,调用时容易找不到或引错版本。推荐的做法是:按功能域建立 procedures 子目录,过程名使用“动词+对象”命名(如 locate_part、measure_geometry),库文件按业务域拆分(如 vision_common.hdpl、calib_common.hdpl),并在项目文件中显式配置外部过程搜索路径。

此外,HDevelop程序中的本地过程应定期审查:如果某个本地过程被复制到第二个程序,就应将其提升为外部过程并放入 procedures;如果某个外部过程在三个以上项目中稳定使用,就应将其纳入库并版本化管理。通过这种“本地→外部→库”的渐进式提升,项目代码会逐步形成清晰的复用层次,而不是一开始就过度设计。

识别可复用单元的核心动作可以概括为:先按“主程序—外部过程—算子”梳理调用链,再对每个外部过程检查参数稳定性、依赖边界和调用频次,最后把满足条件的过程参数化并归入合适的目录或库。这样得到的复用单元,才是后续章节中代码架构与复用策略的真正基础。