← Back to the collection
VISUAL COMPUTING / 2021 / HISTORICAL EXPERIMENT

Finding the shape inside the pixels.

Connected Components

Treat a grayscale image as a graph. Traverse neighboring pixels to discover connected regions.

MEDIUM
  • C++
BUILT WITH
  • Image processing
  • Breadth-first search
  • PGM
  • STL
ACCESS

Public source

01

Pixels become a graph

The program reads a binary PGM image, applies an intensity threshold, and uses four-neighbor breadth-first traversal to build connected components. Each component keeps an identity and a collection of pixel coordinates.

02

Separate the responsibilities

The driver handles arguments, PGMimageProcessor owns image parsing and traversal, and ConnectedComponent represents a region. The project also explores copy and move semantics alongside explicit memory management.

SYSTEM SKETCH / CONCEPTUAL OVERVIEW
PGM IMAGE → THRESHOLD → BFS FRONTIER → COMPONENTS
                           │
                   four neighbours
                       ↑
                     ← + →
                       ↓
A reading of the architecture, not an application screenshot.
SYSTEM MAP / CLASS RELATIONSHIPS / EXTRACTION PIPELINE

An image becomes a collection of regions.

driver.cpp → PGMimageProcessor: construct / load. PGMimageProcessor → extractComponents(): pixels + threshold. extractComponents() → ConnectedComponent: create / addPixel. ConnectedComponent → components: collect. components → writeComponents(): retained coordinates.1234501 / ENTRY POINTdriver.cppParse threshold + output optionsConstruct PGMimageProcessor02 / CLASSPGMimageProcessorread_from_file()imageArray · rows · cols03 / TRAVERSALextractComponents()isValidPixel() → bfsAdd()Queue · visited · four neighbours04 / CLASSConnectedComponentcomponentId · pixelCountvector<pair<int,int>> pixels05 / OWNED COLLECTIONcomponentsvector<ConnectedComponent>Region statistics / size filtering06 / OUTPUTwriteComponents()Rasterize component coordinatesWrite binary PGM
  1. 01 / entry point

    driver.cpp

    Parse threshold + output options

    Construct PGMimageProcessor

    • construct / load → 2. PGMimageProcessor
  2. 02 / class

    PGMimageProcessor

    read_from_file()

    imageArray · rows · cols

    • pixels + threshold → 3. extractComponents()
  3. 03 / traversal

    extractComponents()

    isValidPixel() → bfsAdd()

    Queue · visited · four neighbours

    • create / addPixel → 4. ConnectedComponent
  4. 04 / class

    ConnectedComponent

    componentId · pixelCount

    vector<pair<int,int>> pixels

    • collect → 5. components
  5. 05 / owned collection

    components

    vector<ConnectedComponent>

    Region statistics / size filtering

    • retained coordinates → 6. writeComponents()
  6. 06 / output

    writeComponents()

    Rasterize component coordinates

    Write binary PGM

    1. 1driver.cpp PGMimageProcessorconstruct / load
    2. 2PGMimageProcessor extractComponents()pixels + threshold
    3. 3extractComponents() ConnectedComponentcreate / addPixel
    4. 4ConnectedComponent componentscollect
    5. 5components writeComponents()retained coordinates
    The films use actual C++ exports. The isolated inverse writer changes output polarity only. The historical size-range predicate is defective; the photographs demonstrate threshold extraction, not repaired size filtering.
    Read from the implementation
    • driver.cpp
    • PGMimageProcessor.h / .cpp
    • ConnectedComponent.h / .cpp
    03

    Thirteen thresholds, one photograph

    Each film keeps the grayscale input beside actual output files while the threshold increases from 32 to 224 in steps of 16. Every frame comes from a separate native C++ run. The paired viewer is a capture aid for a command-line program, not a simulated segmentation or a native GUI.

    04

    Ten photographs, two output polarities

    A portrait, coins, leaves, ceramics, tools, fruit, windows, stones, a bicycle, and seashells give the extractor recognizable subjects. These AI-generated photographs are converted to 512 × 512 PGM and processed at thirteen thresholds. A second C++ export swaps foreground and background without changing component membership. Switch colours during playback to compare the exact same threshold. Auto-next moves to the next study only after the current film finishes.

    05

    What the archive actually contains

    The CLI advertises size filtering, but the checked-in predicate compares both bounds against the minimum and cannot implement the stated range. This is preserved as a learning project. The extraction approach is interesting; the archive is not presented as a finished image-processing library.

    CONTINUE EXPLORING

    Neural Networks, from Scratch →

    From a hand-written perceptron learning rule to noisy XOR inputs and a handwritten-digit classifier.

    2021
    • Python