Files
goldyard2025 3fe919e37c refactor(halcon): single-skill plugin layout → invoke as /halcon (not /halcon:halcon)
Move SKILL.md + references/ scripts/ evals/ from skills/halcon/ up to the
plugin root. Per Claude Code plugins-reference, a plugin with SKILL.md at its
root and no skills/ subdir is auto-loaded as a single-skill plugin (v2.1.142+),
so the invocation name = frontmatter name = halcon → clean /halcon.
Bump plugin.json 2.0.0 → 2.0.1 so existing installs receive the update.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 23:14:39 +08:00

8.6 KiB
Raw Permalink Blame History

HALCON task recipes

Ready-to-adapt pipelines for common vision tasks. Each recipe is a procedure (a reusable method), not a one-off — read the operator names, adapt parameters, then run via HDevEngine (scripts/run_procedure.py) or hrun. For exact parameter semantics open the referenced pages (see doc-map.md); for the authoritative operator signature, target reference_hdevelop.pdf.

Conventions used below: Image = input, Region/Roi = ROI, Contours = XLD (subpixel contours), *Handle = a model handle that must be clear_*ed.

Meta-pattern: procedure + Python driver (the house style)

This is how the tested pipeline in references/examples/ is built — copy it.

  1. Write an .hdvp external procedure with control inputs/outputs only (paths in, numbers/tuples out). No draw_*, no stop(). Validate inside and throw on unexpected results.
  2. Persist any human-taught ROI once with teach_roi.pyroi.hobj; the procedure read_regions it.
  3. Drive from Python with HDevEngine: loop images, set_input_control_param_by_name, execute (wrapped in try/except HDevEngineError), get_output_control_param_by_name, aggregate, write CSV.

Reference implementation (bundled): references/examples/find_circles.hdvp + references/examples/run_compare.py. Skeleton procedure body:

read_image (Image, ImageFile)
read_region (Roi, RoiFile)
reduce_domain (Image, Roi, ImageReduced)      * restrict processing to the ROI
* ... task-specific operators ...
if (|Result| != Expected)
    throw ('unexpected count: ' + |Result|)   * driver catches & skips
endif

Blob analysis (segment by gray value, measure regions)

Goal: find objects that differ in brightness, count/measure them.

threshold (ImageReduced, Region, MinGray, MaxGray)   * or auto_threshold / binary_threshold
connection (Region, ConnectedRegions)                * split into individual blobs
select_shape (ConnectedRegions, Selected, 'area', 'and', MinArea, MaxArea)
area_center (Selected, Area, Row, Col)               * features per blob

Key knobs: pick the threshold from the histogram (gray_histo), or use dyn_threshold against a smoothed copy for uneven lighting. Morphology (opening_circle, closing_circle) cleans speckle before connection. Guide: solution_guide_i.pdf ch.4 (p33).

Subpixel edges, contours, and shape fitting

Goal: precise geometry (circle/line/ellipse) from contours.

edges_sub_pix (ImageReduced, Edges, 'canny', Alpha, Low, High)   * Alpha≈13, higher=smoother
select_contours_xld (Edges, Sel, 'contour_length', MinLen, MaxLen, -0.5, 0.5)
union_adjacent_contours_xld (Sel, Union, 10, 1, 'attr_keep')      * join broken arcs
sort_contours_xld (Union, Sorted, 'character', 'true', 'column')  * deterministic order
fit_circle_contour_xld (Sorted, 'algebraic', -1, 0, 0, 3, 2, Row, Col, Radius, S, E, Order)
* fit_line_contour_xld / fit_ellipse_contour_xld for other shapes

Gotchas: canny thresholds and the length window are the tuning that decides how many contours survive — if the fitted count is wrong, adjust MinLen/MaxLen and the ROI tightness before anything else. Guides: solution_guide_i.pdf ch.7,9 (p63, p79).

2D measuring — metrology model (robust circle/line/rectangle fitting)

Goal: high-accuracy, repeatable geometry with built-in edge measurement. This is the metrology-model half of the tested find_circles.hdvp.

create_metrology_model (MetrologyHandle)
set_metrology_model_image_size (MetrologyHandle, Width, Height)
add_metrology_object_circle_measure (MetrologyHandle, Row, Col, Radius, RadiusTol, \
        MeasureLen1, MeasureLen2, MeasureSigma, [], [], Indices)
set_metrology_object_param (MetrologyHandle, Indices, 'num_instances', 1)
set_metrology_object_param (MetrologyHandle, Indices, 'measure_transition', 'positive')
set_metrology_object_param (MetrologyHandle, Indices, 'min_score', 0.3)
apply_metrology_model (Image, MetrologyHandle)
get_metrology_object_result (MetrologyHandle, Indices, 'all', 'result_type', 'all_param', Param)
* circle params come back interleaved: Row=Param[0::3], Col=Param[1::3], Radius=Param[2::3]
clear_metrology_model (MetrologyHandle)

Seed the metrology objects from a rough fit (e.g. fit_circle_contour_xld), then let the model refine. Tune min_score, measure_transition (positive/negative/all), and the radius tolerance. Guide: solution_guide_iii_b_2d_measuring.pdf (Basic Tools p11, Tool Selection p27, Examples p35).

1D measuring (calipers along a line or arc)

Goal: edge positions/widths along a profile (e.g. pin pitch, gap width).

gen_measure_rectangle2 (Row, Col, Phi, Length1, Length2, Width, Height, 'nearest_neighbor', Handle)
measure_pos (Image, Handle, Sigma, Threshold, 'all', 'all', RowEdge, ColEdge, Amp, Distance)
* gen_measure_arc + measure_pos for circular profiles
close_measure (Handle)

Use the fuzzy measure object (fuzzy_measure_pos) when edges are noisy/ambiguous. Guide: solution_guide_iii_a_1d_measuring.pdf.

2D matching (locate a known template)

Goal: find where a trained pattern appears (with rotation/scale), get pose.

Default = shape-based matching (robust to illumination, occlusion):

* --- train once, persist the model ---
create_shape_model (TemplateImageReduced, 'auto', 0, rad(360), 'auto', 'auto', \
        'use_polarity', 'auto', 'auto', ModelID)
write_shape_model (ModelID, 'model.shm')
* --- match at runtime ---
read_shape_model ('model.shm', ModelID)
find_shape_model (Image, ModelID, 0, rad(360), 0.5, 0, 0.5, 'least_squares', 0, 0.9, \
        Row, Col, Angle, Score)

Alternatives (pick by solution_guide_ii_b_matching.pdf ch.3): NCC (create_ncc_model) for pure translation/known illumination; component matching for articulated parts; local-deformable/descriptor for deformation/perspective. Guide overview: solution_guide_i.pdf ch.10 (p89).

2D data codes (DataMatrix, QR, PDF417) and bar codes

create_data_code_2d_model ('Data Matrix ECC 200', [], [], DataCodeHandle)
find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, 'stop_after_result_num', 1, \
        ResultHandles, DecodedStrings)
clear_data_code_2d_model (DataCodeHandle)

If decoding fails: raise find_data_code_2d search effort/timeout params, or preprocess (contrast, gray_range_rect, mean_image) — see solution_guide_ii_c_2d_data_codes.pdf ch.4 (Preprocessing p25), ch.5 (Problem Handling p29). Bar codes: create_bar_code_model / find_bar_code (solution_guide_i.pdf ch.16 p159). Print-quality grading: ch.6 (p45).

Camera calibration & world coordinates

Goal: convert pixel measurements to metric units / correct lens distortion.

* grab N images of the HALCON calibration plate at varied poses
create_calib_data ('calibration_object', 1, 1, CalibHandle)
set_calib_data_cam_param (CalibHandle, 0, [], StartCamPar)
set_calib_data_calib_object (CalibHandle, 0, 'caltab.descr')
* for each image: find_calib_data_object / set_calib_data_observ_points
calibrate_cameras (CalibHandle, Error)
get_calib_data (CalibHandle, 'camera', 0, 'params', CamParam)
* then set_origin_pose / image_points_to_world_plane for metric measurement in a plane

Prefer the Calibration Assistant in HDevelop to generate this code (hdevelop_users_guide.pdf p184). Theory + full workflow: solution_guide_iii_c_3d_vision.pdf ch.2 (p13) and ch.3 (single-camera metric, p59).

3D surface-based matching (point clouds)

Goal: find the 3D pose of an object in a point cloud / from a CAD model.

create_surface_model (ObjectModel3D, RelSamplingDist, [], [], SurfaceModelID)
find_surface_model (SurfaceModelID, SceneModel3D, RelSamplingDist, KeyPointFrac, \
        MinScore, 'true', [], [], Pose, Score, SurfaceMatchingResultID)

Data must be a real 3D point cloud with normals. If matches are poor, work through surface_based_matching.pdf ch.4 (Troubleshooting p17) and ch.5 (Tips p22); remove the dominant background plane first (ch.6, p26).

OCR & classification (brief)

  • Deep OCR (default for reading text): create_deep_ocr / apply_deep_ocr — pretrained, no training needed. solution_guide_i.pdf ch.19 (p209).
  • Classic OCR: segment characters → do_ocr_multi_class_mlp with a pretrained font. ch.18 (p183).
  • Feature classification (MLP/SVM/GMM/k-NN): train on region features, then classify. solution_guide_ii_d_classification.pdf ch.5 (p31).

When a recipe isn't enough

  1. Read the matching chapter/pages from doc-map.md.
  2. Confirm exact operator parameters in reference_hdevelop.pdf (target pages, don't browse).
  3. Prototype interactively in HDevelop (or runScriptInGui), then freeze the working logic into an .hdvp and drive it headless — see the meta-pattern.