Circle and Line Measurement in Halcon: Metrology Model Approach
read_image (Image, 'test.bmp')
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle)
dev_display (Image)
dev_set_draw ('margin')
draw_line (WindowHandle, Row1, Column1, Row2, Column2)
draw_circle (WindowHandle, Row, Column, Radius)
Line Measurement Using the Metrology Model
The following code demonstrates how to set up and perform a line measurement using the metrology model. Key parameters such as caliper width, height, spacing, threshold, and edge selection are configured.
set_system ('clip_region', 'false')
* Create metrology model
create_metrology_model (MetrologyHandle)
add_metrology_object_line_measure (MetrologyHandle, StartRow, StartCol, EndRow, EndCol, 100, 20, 1, 30, [], [], Index)
* Set measurement parameters
set_metrology_object_param (MetrologyHandle, Index, 'measure_length1', RuleWidth)
set_metrology_object_param (MetrologyHandle, Index, 'measure_length2', RuleHeight)
set_metrology_object_param (MetrologyHandle, Index, 'measure_distance', RuleSpace)
set_metrology_object_param (MetrologyHandle, Index, 'measure_threshold', RuleThd)
set_metrology_object_param (MetrologyHandle, Index, 'measure_select', RuleSeleP)
set_metrology_object_param (MetrologyHandle, Index, 'measure_transition', RuleMode)
* Apply measurement
apply_metrology_model (Image, MetrologyHandle)
get_metrology_object_result (MetrologyHandle, Index, 'all', 'result_type', ['row_begin', 'column_begin', 'row_end', 'column_end'], Parameter)
if (|Parameter| = 4)
* Retrieve edge point contours
get_metrology_object_measures (Contours, MetrologyHandle, Index, RuleMode, PointRows, PointCols)
* Draw crosses at edge points
gen_cross_contour_xld (Cross, PointRows, PointCols, 5, 0)
* Generate line contour from result
gen_contour_polygon_xld (ContLine, [Parameter[0], Parameter[2]], [Parameter[1], Parameter[3]])
* Compute center and angle of the line
centerRow := (Parameter[0] + Parameter[2]) / 2
centerCol := (Parameter[1] + Parameter[3]) / 2
angle_lx (Parameter[0], Parameter[1], Parameter[2], Parameter[3], Angle)
endif
clear_metrology_model (MetrologyHandle)
Circle Measurement Using the Metrology Model
This example shows how to configure and execute a circle measurement. The approach is similar to line measurement, but the object type is a circle.
set_system ('clip_region', 'false')
* Create metrology model for circle
create_metrology_model (MetrologyHandle)
add_metrology_object_circle_measure (MetrologyHandle, Row, Column, Radius, 20, 5, 1, 30, [], [], Index)
* Set parameters
set_metrology_object_param (MetrologyHandle, Index, 'measure_length1', RuleWidth)
set_metrology_object_param (MetrologyHandle, Index, 'measure_length2', RuleHeight)
set_metrology_object_param (MetrologyHandle, Index, 'measure_distance', RuleSpace)
set_metrology_object_param (MetrologyHandle, Index, 'measure_threshold', RuleThd)
set_metrology_object_param (MetrologyHandle, Index, 'measure_select', RuleSeleP)
set_metrology_object_param (MetrologyHandle, Index, 'measure_transition', RuleMode)
* Execute measurement
apply_metrology_model (Image, MetrologyHandle)
get_metrology_object_result (MetrologyHandle, Index, 'all', 'result_type', ['row', 'column', 'radius'], Parameter)
if (|Parameter| >= 3)
* Find edge points
get_metrology_object_measures (Contours, MetrologyHandle, Index, RuleMode, PointRows, PointCols)
* Draw crosses
gen_cross_contour_xld (Cross, PointRows, PointCols, 5, 0)
* Draw cross at center
gen_cross_contour_xld (CrossCenter, Parameter[0], Parameter[1], 10, rad(45))
* Generate fitted circle contour
gen_circle_contour_xld (ContCircle, Parameter[0], Parameter[1], Parameter[2], 0, 6.28318, 'positive', 1)
endif
clear_metrology_model (MetrologyHandle)
Advanced Circle Measuremant with Multiple Objects
When measuring multiple circles in a single image, hendle each object iteratively. The code below also includes a fallback using least-squares fitting when the metrology model fails to return a result.
set_system ('clip_region', 'false')
tuple_length (Row, Length)
* Initialize model
create_metrology_model (MetrologyHandle)
add_metrology_object_circle_measure (MetrologyHandle, Row, Column, Radius, RuleWidth, RuleHeight, 1, RuleThd, ['min_score'], [0.35], Index)
* Set common parameters for all objects
set_metrology_object_param (MetrologyHandle, 'all', 'measure_distance', RuleSpace)
set_metrology_object_param (MetrologyHandle, 'all', 'measure_select', RuleSeleP)
set_metrology_object_param (MetrologyHandle, 'all', 'measure_transition', RuleMode)
apply_metrology_model (Image, MetrologyHandle)
Parameter := []
gen_empty_obj (Contours)
gen_empty_obj (Cross)
gen_empty_obj (CrossCenter)
gen_empty_obj (ContCircle)
get_metrology_object_result (MetrologyHandle, Index, 'all', 'result_type', ['row', 'column', 'radius'], Parameter)
if (|Parameter| >= 3)
for Index2 := 0 to Length - 1 by 1
get_metrology_object_measures (tempContours, MetrologyHandle, Index2, 'all', PointRows, PointCols)
gen_cross_contour_xld (tempCross, PointRows, PointCols, 5, 0)
gen_cross_contour_xld (tempCrossCenter, Parameter[Index2 * 3 + 0], Parameter[Index2 * 3 + 1], 50, rad(45))
gen_circle_contour_xld (tempContCircle, Parameter[Index2 * 3 + 0], Parameter[Index2 * 3 + 1], Parameter[Index2 * 3 + 2], 0, 6.28318, 'positive', 1)
concat_obj (tempContours, Contours, Contours)
concat_obj (tempCross, Cross, Cross)
concat_obj (tempCrossCenter, CrossCenter, CrossCenter)
concat_obj (tempContCircle, ContCircle, ContCircle)
endfor
else
for Index1 := 0 to Length - 1 by 1
get_metrology_object_measures (tempContours, MetrologyHandle, Index1, 'all', PointRows, PointCols)
gen_cross_contour_xld (tempCross, PointRows, PointCols, 5, 0)
* Least-squares circle fitting
fit_circle_analytic (PointRows, PointCols, tempParameter)
if (|tempParameter| = 3)
gen_cross_contour_xld (tempCrossCenter, tempParameter[0], tempParameter[1], 50, rad(45))
gen_circle_contour_xld (tempContCircle, tempParameter[0], tempParameter[1], tempParameter[2], 0, 6.28318, 'positive', 1)
endif
concat_obj (tempContours, Contours, Contours)
concat_obj (tempCross, Cross, Cross)
concat_obj (tempContCircle, ContCircle, ContCircle)
tuple_concat (tempParameter, Parameter, Parameter)
endfor
endif
clear_metrology_model (MetrologyHandle)
Least-Squares Circle Fitting Function
The function fit_circle_analytic computes the best-fit circle from a set of edge points using an algebraic least-squares method.
* Input: RowList, ColList
* Output: Parameter (row_center, col_center, radius)
Parameter[0] := -999.999
Parameter[1] := -999.999
if (|RowList| <= 3 or |ColList| <= 3 or |RowList| != |ColList|)
return ()
endif
sum_x := 0.0
sum_y := 0.0
sum_x2 := 0.0
sum_y2 := 0.0
sum_x3 := 0.0
sum_y3 := 0.0
sum_xy := 0.0
sum_x1y2 := 0.0
sum_x2y1 := 0.0
tuple_length (ColList, N)
for i := 0 to N - 1 by 1
x := RowList[i]
y := ColList[i]
x2 := x * x
y2 := y * y
sum_x := sum_x + x
sum_y := sum_y + y
sum_x2 := sum_x2 + x2
sum_y2 := sum_y2 + y2
sum_x3 := sum_x3 + x2 * x
sum_y3 := sum_y3 + y2 * y
sum_xy := sum_xy + x * y
sum_x1y2 := sum_x1y2 + x * y2
sum_x2y1 := sum_x2y1 + x2 * y
endfor
C := N * sum_x2 - sum_x * sum_x
D := N * sum_xy - sum_x * sum_y
E := N * sum_x3 + N * sum_x1y2 - (sum_x2 + sum_y2) * sum_x
G := N * sum_y2 - sum_y * sum_y
H := N * sum_x2y1 + N * sum_y3 - (sum_x2 + sum_y2) * sum_y
a := (H * D - E * G) / (C * G - D * D)
b := (H * C - E * D) / (D * D - G * C)
c := -(a * sum_x + b * sum_y + sum_x2 + sum_y2) / N
Parameter[0] := a / (-2)
Parameter[1] := b / (-2)
Parameter[2] := sqrt(a * a + b * b - 4 * c) / 2