All projects

SYSTEMS / UCT · CSC3022 / 2024

Structure inside grayscale images

Turn grayscale pixels into countable regions using thresholding, breadth-first flood fill and component-size filtering in C++.

C++Image processingBFS
New synthetic input beside the mask produced by the original connected-component algorithm

UCT / COURSE CONTEXT / 2024

CSC3022F · C++ and Machine Learning

C++ language and memory-model foundations followed by Python-based machine-learning implementation.

Science handbook · 2024

ENGINEERING PERSPECTIVE

Inside the work

Turn a grayscale raster into discrete regions that can be counted and filtered. It demonstrates classical segmentation, traversal and C++ resource ownership without claiming a trained vision model.

C++ / std::queue
Manage pixel buffers and run breadth-first flood fill.
PGM / tests
Read binary grayscale rasters, write masks and check component behaviour on bounded inputs.
STEP 1 / 3

Select foreground

Read a grayscale image and apply the chosen intensity threshold.

Source-derived walkthrough

What it is

Extract connected foreground regions from PGM images, inspect component statistics and write filtered masks.

Why it was built

Identify connected foreground regions and remove components outside a chosen size range in grayscale images.

My contribution

Individual C++ coursework implementation. The public release uses authored synthetic fixtures and new verification; supplied images, Catch and original fixture-dependent tests remain privately preserved.

How it works

Apply a grayscale threshold, traverse connected neighbours using a queue-based flood fill, store component pixels and filter by minimum/maximum size.

  1. 01PGM image
  2. 02Threshold
  3. 03BFS traversal
  4. 04Size filter
  5. 05Output mask

Technical implementation

  • Read a PGM raster, threshold grayscale pixels, then use four-neighbour queue traversal to discover connected components.
  • Store component pixels, derive size statistics and filter using minimum/maximum limits before writing a mask.
  • The class implements copy/move ownership behaviour. Labelled 2026 changes add bounded input parsing, reject zero thresholds, release temporary components and erase filtered elements safely without replacing the traversal algorithm.
  • Private historical verification passed 19 assertions in two submitted cases. Public release-day verification separately passed six synthetic regressions, ten malformed-input cases and four additional safety/output checks.

Results & evidence

  • The submitted processor compiled, passed 19 assertions in two private tests and generated a mask from a new synthetic input.
  • The public release passed six synthetic regressions, ten malformed-input checks and four additional safety/output checks on 12 October 2026. Supplied fixtures and teaching tests remain excluded.

Engineering challenges

Connectivity, threshold boundaries, image parsing and object ownership need to agree; test expectations cover only a small surface.

Scope & limitations

Classical image processing, with no trained model. Only 8-bit P5 is supported; threshold zero is rejected because the original traversal uses zero as its visited marker. Safety fixes are labelled post-project improvements.

What I learned

Viewing an image as a graph and combining traversal algorithms with C++ resource management.

What I would improve now

Add sanitizer coverage, copy/move edge-case tests and an independent per-pixel reference across more synthetic connectivity cases. Improve boundary counting and clarify empty-component summary semantics.

NEXT PROJECTCoordinating peers over a network