Section 21.6.1
Purpose
Combine nearby Mini-Boxes into a single enclosing bounding box. This utility processes detections from one neural network and one inference frame.
Section 21.6.2
Why It Exists
Mini-Boxes can identify small regions of highly variable objects or artifacts, such as scratches, dents, or anomalies. Several boxes may describe different parts of one artifact.
If you need to report how many scratches are present, counting the original boxes can overcount the artifacts. Combining nearby boxes provides a way to group them before counting.
Nearby boxes do not necessarily represent the same physical artifact. Choose and validate the merge distance against representative images; the book explicitly describes this as an imperfect approach.
Section 21.6.3
Input
Supply an array<BoundingBox@>, named bbox_arr in the example, from your inference process. Select the labels to combine and a pixel-distance threshold:
array<int> target_label_id_arr = {0,1};
int pixel_distance_to_combine = 100;The example processes labels 0 and 1, but keeps their families separate. Boxes with different label IDs never merge.
Each input provides upper-left pixel coordinates, width, height, label ID and name, confidence, and display colors. Use valid objects with positive dimensions in the same image coordinate system.
This utility’s input code reads bbox.probability. If your local BoundingBox class uses confidence, replace the two bbox.probability references in the code. The output class always uses confidence.
Only selected labels are retained in the output. Preserve any other detections separately if your application still needs them.
Review 21.1 · Inference Data & BoundingBox →Section 21.6.4
Output
Results are stored in merged_bbox_dict. Each key is a label ID converted to a string; its value is an array<CustomBBox> containing the final families for that label.
dictionary merged_bbox_dict;
// "0" -> array<CustomBBox> for label 0
// "1" -> array<CustomBBox> for label 1A CustomBBox contains geometry, an integer center point, label information, display colors, mean confidence, and the confidence sum/count used to calculate that mean.
| Fields | Meaning |
|---|---|
x, y, width, height | The rectangle enclosing the family. |
center_x, center_y | Integer center of that rectangle. |
label_id, label_name and colors | Retained from the existing family. |
sum_confidence, freq_confidence | Cumulative input confidence and contributing-box count. |
confidence | The arithmetic mean after finalization. Unmerged boxes retain their original confidence. |
A small example
Two label-0 boxes at (10, 10, 20, 20) and (35, 10, 20, 20) have an edge gap of 5 pixels. At a threshold of 5, they merge into (10, 10, 45, 20). Input confidences of 0.8 and 0.6 produce a mean of 0.7.
A label-1 box remains separate even if it overlaps that label-0 family. The final box count describes the resulting families, not a guaranteed count of real-world artifacts.
Distance and merge behavior
The distance is the minimum edge-to-edge Euclidean gap, not the distance between centers. Overlap, edge contact, and corner contact all have distance zero.
Each incoming box joins the first existing family of the same label within the threshold. Otherwise it starts a new family. The algorithm does not repeatedly merge existing families together, and its results can depend on input order.
Section 21.6.5
How To Use
Add the supplied classes, dictionary, and helper instance to your inference scripting environment. This is AngelScript-style runtime code, not a standalone Python utility.
For each new frame, obtain bbox_arr from your model and run these steps in order:
// Reset state for this frame.
box_merge_class.reset_box_merge_class();
// Group selected detections.
box_merge_class.box_merge(bbox_arr, target_label_id_arr,
pixel_distance_to_combine);
// Finalize confidence values after all boxes are merged.
box_merge_class.calc_average_confidence();
// Count the final families.
int total_new_box_count = box_merge_class.count_custom_bbox();Retrieve a label’s results
array<CustomBBox> label_0_boxes;
bool found = merged_bbox_dict.get("0", label_0_boxes);
if (found) {
for (uint i = 0; i < label_0_boxes.length(); i++) {
CustomBBox merged_box = label_0_boxes[i];
// Draw or report merged_box in your application.
}
}Preserve the original image without its original boxes, then draw the merged results onto that image using your application’s drawing functions. Inference acquisition and box drawing are not included in this helper.
Do not carry families across frames. Merge all input boxes before calculating average confidence, and read or draw the results before resetting for the next frame. The counting helper uses the global target_label_id_arr; use that same configured array when calling box_merge.
Before integrating
- Set the target label IDs and a non-negative threshold appropriate to your image resolution.
- Check the
probability/confidenceinput-member name. - Supply the runtime’s
BoundingBox, array and dictionary support, and itssqrt,min, andmaxfunctions. - Validate close but separate artifacts, overlapping boxes, different labels, and input-order effects.
No Linux / Windows terminal setup is required for this helper. Integration and drawing depend on your inference runtime.
Section 21.6.6
Code
The complete helper from section 21.6, with PDF line wrapping and indentation restored. Your application supplies bbox_arr and the input BoundingBox class.
// User settings. Supply bbox_arr from one model's inference output.
array<int> target_label_id_arr = {0,1};
int pixel_distance_to_combine = 100;
// Input BoundingBox uses probability for model confidence.
// If your runtime uses confidence instead, replace bbox.probability below.
class CustomBBox {
int label_id;
string label_name;
float confidence;
int x;
int y;
int width;
int height;
int center_x;
int center_y;
int label_color_r;
int label_color_g;
int label_color_b;
float sum_confidence;
int freq_confidence;
};
// String label_id key -> array<CustomBBox>.
dictionary merged_bbox_dict;
class BoxMergeClass {
void reset_box_merge_class() {
merged_bbox_dict.deleteAll();
}
void box_merge(array<BoundingBox@> bbox_arr, array<int> target_label_id_arr,
int pixel_distance_to_combine) {
if (bbox_arr.length() == 0) {
return;
}
for (uint i = 0; i < bbox_arr.length(); i++) {
BoundingBox@ a_bbox = bbox_arr[i];
if (target_label_id_arr.find(a_bbox.label_id) < 0) {
continue;
}
int label_id = a_bbox.label_id;
string label_id_key = label_id + "";
CustomBBox temp_custom_bbox = create_custom_bbox(a_bbox);
if (merged_bbox_dict.exists(label_id_key) == false) {
array<CustomBBox> custom_bbox_arr;
custom_bbox_arr.insertLast(temp_custom_bbox);
merged_bbox_dict.set(label_id_key, custom_bbox_arr);
continue;
}
bool found = false;
array<CustomBBox> existing_custom_bbox_arr;
found = merged_bbox_dict.get(label_id_key, existing_custom_bbox_arr);
if (found == false) {
continue;
}
bool found_family = false;
for (uint j = 0; j < existing_custom_bbox_arr.length(); j++) {
CustomBBox existing_custom_bbox = existing_custom_bbox_arr[j];
if (existing_custom_bbox.label_id != label_id) {
continue;
}
float distance = calc_bbox_distance(existing_custom_bbox, temp_custom_bbox);
if (distance <= pixel_distance_to_combine) {
found_family = true;
CustomBBox family_box = combine_bboxes(existing_custom_bbox, temp_custom_bbox);
existing_custom_bbox_arr[j] = family_box;
merged_bbox_dict.set(label_id_key, existing_custom_bbox_arr);
break;
}
}
if (found_family == false) {
existing_custom_bbox_arr.insertLast(temp_custom_bbox);
merged_bbox_dict.set(label_id_key, existing_custom_bbox_arr);
}
}
}
CustomBBox create_custom_bbox(BoundingBox@ bbox) {
CustomBBox output;
output.label_id = bbox.label_id;
output.label_name = bbox.label_name;
output.confidence = bbox.probability;
output.x = bbox.x;
output.y = bbox.y;
output.width = bbox.width;
output.height = bbox.height;
output.center_x = bbox.x + (bbox.width / 2);
output.center_y = bbox.y + (bbox.height / 2);
output.label_color_r = bbox.label_color_r;
output.label_color_g = bbox.label_color_g;
output.label_color_b = bbox.label_color_b;
output.sum_confidence = bbox.probability;
output.freq_confidence = 1;
return output;
}
float calc_bbox_distance(const CustomBBox &in box1, const CustomBBox &in box2) {
int box_1_min_x = box1.x;
int box_1_max_x = box1.x + box1.width;
int box_1_min_y = box1.y;
int box_1_max_y = box1.y + box1.height;
int box_2_min_x = box2.x;
int box_2_max_x = box2.x + box2.width;
int box_2_min_y = box2.y;
int box_2_max_y = box2.y + box2.height;
if (box_1_max_x >= box_2_min_x && box_2_max_x >= box_1_min_x &&
box_1_max_y >= box_2_min_y && box_2_max_y >= box_1_min_y) {
return 0.0f;
}
float x_gap = 0.0f;
float y_gap = 0.0f;
if (box_1_max_x < box_2_min_x) {
x_gap = float(box_2_min_x - box_1_max_x);
} else if (box_2_max_x < box_1_min_x) {
x_gap = float(box_1_min_x - box_2_max_x);
}
if (box_1_max_y < box_2_min_y) {
y_gap = float(box_2_min_y - box_1_max_y);
} else if (box_2_max_y < box_1_min_y) {
y_gap = float(box_1_min_y - box_2_max_y);
}
return sqrt(x_gap * x_gap + y_gap * y_gap);
}
CustomBBox combine_bboxes(CustomBBox existing_box1, CustomBBox new_box2) {
CustomBBox combined;
int left = min(existing_box1.x, new_box2.x);
int top = min(existing_box1.y, new_box2.y);
int right = max(existing_box1.x + existing_box1.width, new_box2.x + new_box2.width);
int bottom = max(existing_box1.y + existing_box1.height, new_box2.y + new_box2.height);
combined.x = left;
combined.y = top;
combined.width = right - left;
combined.height = bottom - top;
combined.center_x = combined.x + combined.width / 2;
combined.center_y = combined.y + combined.height / 2;
combined.label_id = existing_box1.label_id;
combined.label_name = existing_box1.label_name;
combined.label_color_r = existing_box1.label_color_r;
combined.label_color_g = existing_box1.label_color_g;
combined.label_color_b = existing_box1.label_color_b;
combined.confidence = -1;
combined.sum_confidence = existing_box1.sum_confidence + new_box2.confidence;
combined.freq_confidence = existing_box1.freq_confidence + 1;
return combined;
}
void calc_average_confidence() {
array<string> label_ids_arr = merged_bbox_dict.getKeys();
for (uint i = 0; i < label_ids_arr.length(); i++) {
string label_id_key = label_ids_arr[i];
array<CustomBBox> custom_bbox_arr;
bool found = merged_bbox_dict.get(label_id_key, custom_bbox_arr);
if (found == false) {
continue;
}
for (uint j = 0; j < custom_bbox_arr.length(); j++) {
CustomBBox a_custom_bbox = custom_bbox_arr[j];
if (a_custom_bbox.confidence == -1) {
a_custom_bbox.confidence = float(a_custom_bbox.sum_confidence) /
float(a_custom_bbox.freq_confidence);
custom_bbox_arr[j] = a_custom_bbox;
}
}
merged_bbox_dict.set(label_id_key, custom_bbox_arr);
}
}
int count_custom_bbox() {
int total_count = 0;
array<string> label_ids_arr = merged_bbox_dict.getKeys();
for (uint i = 0; i < label_ids_arr.length(); i++) {
string label_id_key = label_ids_arr[i];
array<CustomBBox> bbox_arr;
bool found = merged_bbox_dict.get(label_id_key, bbox_arr);
if (found == false) {
continue;
}
for (uint j = 0; j < bbox_arr.length(); j++) {
CustomBBox a_custom_bbox = bbox_arr[j];
if (target_label_id_arr.find(a_custom_bbox.label_id) < 0) {
continue;
}
total_count++;
}
}
return total_count;
}
};
BoxMergeClass box_merge_class;
Section 21.6.7
Prompt to Reproduce This Utility with AI
Copy the complete request into your AI chat. Review and test the result before integrating it.
Replace [your favorite programming language] with your chosen language. The supplied download retains the book’s inference-scripting syntax and first-match merge behavior.
Programming language: [your favorite programming language]
Create a script that merges nearby bounding boxes belonging to the same label ID. Process the output of a single neural network only. Do not support multiple networks in the data structure.
The user supplies:
- An array of BoundingBox objects from one inference frame.
- Each BoundingBox contains label_id, label_name, probability, x, y, width, height, label_color_r, label_color_g, and label_color_b.
- An array of target label IDs to process.
- A non-negative pixel-distance threshold for merging boxes.
Coordinates use the upper-left corner and integer pixel dimensions in the same image coordinate system. Supply valid, non-null input objects with positive widths and heights. If the local input class uses confidence instead of probability, adapt that member name.
Create a CustomBBox class containing label_id, label_name, confidence, x, y, width, height, center_x, center_y, label_color_r, label_color_g, label_color_b, sum_confidence, and freq_confidence.
Store merged results in a dictionary whose keys are string representations of label IDs and whose values are arrays of CustomBBox objects.
For each input box in order:
- Ignore labels not in the target label array.
- Create a CustomBBox with sum_confidence equal to the input probability and freq_confidence equal to 1.
- If its label has no dictionary entry, create an array containing this box.
- Otherwise, compare it with the existing box families for that label in array order.
- Calculate minimum edge-to-edge Euclidean distance. Overlapping boxes, edge contact, and corner contact have distance zero. Use the horizontal and vertical gaps between rectangles, not center-to-center distance.
- If the distance is less than or equal to the threshold, merge into the first matching family and stop searching. The new rectangle must fully enclose both boxes. Update its integer center, add the incoming confidence to the cumulative confidence, and increment the count. Retain the existing family's label name and display colors.
- If no family matches, append the new box as another family for that label.
Never merge boxes with different label IDs. Support multiple target IDs in the same call. Preserve this first-match, one-pass behavior; do not replace it with a transitive or repeated global clustering algorithm. Results may depend on input order.
Provide helpers to convert an input box, calculate rectangle distance, combine a family with an incoming box, calculate mean confidence from sum_confidence divided by freq_confidence, count final families for the selected labels, and reset the dictionary for the next frame. Leave unmerged boxes with their original confidence.
Include an integration example that resets state, merges one frame, finalizes mean confidence, and counts the output families. Explain how to retrieve each label's results. Do not include inference acquisition or image drawing; those belong to the caller's application.

