Connected Components & Small Region Merging
High-Level Algorithmβ
- Labeling / connected-component flood-fill: iterate pixels, perform a breadth-first (queue) flood-fill whenever an unlabeled pixel is found. Two pixels are considered connected if they are 4-neighbours (up, down, left, right) and their RGBA values are exactly equal.
- While flood-filling,
Regionmetadata is collected (size,minX,maxX,minY,maxY) and labeled according to an index (labels). - After all components are labeled and regions metadata computed,
iterate pixels again. For a pixel whose region is considered small
(fails
isBigEnough(minArea,minWidth,minHeight)), check its four immediate neighbors. If any neighbor belongs to a big region, copy that neighbor's RGBA into the small pixel (effectively assigning the small pixel to the big region; over time, the small region is consumed by bigger neighboring regions).
This merges only small-region pixels which are adjacent to large regions. The order of iteration means small pixels near large regions are captured first β the implementation stops at first qualifying neighbour.
Mathematical Backgroundβ
Connected componentsβ
The algorithm computes connected components on a planar grid using 4-connectivity. Formally, we can describe the image as a function:
- is the image function.
- is the set of all integer pairs representing pixel coordinates.
- is the set of all possible RGBA values:
- is the color of the pixel at coordinates .
In simple terms, each pixel at position has a color given by . :::
Two pixels, and , are 4-adjacent if . A connected component is a maximal set of pixels, , such that any two pixels in are connected by a path of 4-adjacent pixels with identical colors.
A flood-fill (BFS / DFS) computes these components exactly.
Bounding box & geometric heuristicsβ
For each component we compute an axis-aligned bounding box with integer coordinates:
The bounding-box width and height are:
See the source code in the Region struct to understand how this is used.
The area (component size) is simply the number of pixels in the component, .
The heuristics used to classify small vs big regions rely on thresholds on both area and bounding box dimensions.
This avoids keeping long thin noise (e.g. a long 1-pixel-wide arm) even if its area is above minArea.
Why 4-connectivity, not 8?β
4-connectivity treats diagonally touching pixels as disconnected. This is stricter and avoids connecting components that only meet at a corner. Depending on the data, 8-connectivity (connect diagonally too) may be preferred β see the Variants & Improvements page.
What does merging mean here?β
The code does not merge region graphs with union operations. Instead, it performs a pixel-wise recoloring of small-region pixels to the color of an adjacent big region. That has the practical effect of attaching each small pixel to a neighboring large region. This is a cheap and local merge β it wonβt always choose the most semantically correct neighbor if multiple are present.