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>
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
# 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.py` → `roi.hobj`; the
|
||||
procedure `read_region`s 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≈1–3, 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.
|
||||
Reference in New Issue
Block a user