Portfolio  ›  Projects  ›  Vehicle Tracking
Computer VisionPythonOpenCV

Vehicle Detection &
Multi-Object Tracking

Detecting a vehicle in one frame is easy. Knowing it is the same vehicle in the next frame is the actual problem — and it is what turns detection into counting, speed estimation and flow analysis.

◆ Verified · video output produced
Context: Computer-vision study project  ·  Role: Sole author
Runs: real time on CPU  ·  Training data required: none
0Training images needed
CPUReal-time, no GPU
2Stage pipeline
🎬 Watch the Run⚙️ How Tracking Works
Vehicle tracking output showing two cars detected and labelled with persistent tracking IDs inside a region of interest
Actual run outputDetection with persistent per-vehicle tracking IDs
Overview

Identity, not just detection

The system watches a fixed camera, isolates whatever is moving inside a defined region of interest, and assigns each moving object an identity that survives from frame to frame. Once an object keeps its identity you can count it once instead of once per frame, measure how long it took to cross the region, and describe flow rather than presence.

It uses no neural network and no labelled data. On a fixed camera, background modelling separates moving foreground from static scene effectively enough that a learned detector is not required — which keeps it real-time on a CPU.

The Problem

Frame-by-frame detection cannot count

A detector that finds three cars in every frame of a thirty-second clip has found nothing useful — it cannot tell you whether that is three cars or three hundred. Counting, dwell time and speed all require knowing that the box in this frame is the same object as the box in the last one.

That association problem is where tracking lives, and it has to be solved under detection noise: boxes jitter, split, merge and disappear for a frame.

Technical Approach

Background modelling, then association

A background model learns what the static scene looks like and reports pixels that deviate from it. Thresholding and contour extraction turn that into candidate boxes, and small contours are discarded so that shadows and sensor noise do not become vehicles.

Association then matches each new box to an existing track by proximity of centre point, within a distance threshold. A box close to a known track inherits its identity; a box that matches nothing becomes a new track; identities not seen in the current frame are retired so the table does not grow without bound.

01 CAPTUREFixed-camera video
02 ROIRestrict to the region of interest
03 SUBTRACTBackground model isolates motion
04 FILTERContours, minimum-area threshold
05 ASSOCIATEMatch to existing tracks by centre distance
06 LABELDraw box and persistent ID
Capabilities

What it does

🚗

Detection

  • Adaptive background modelling
  • Region-of-interest restriction
  • Minimum-area filtering against noise
🏷️

Tracking

  • Centre-point association
  • Persistent IDs across frames
  • Automatic retirement of stale tracks

Practicality

  • No training data
  • No GPU
  • Real time on CPU
Technologies

Actual stack

Vision
OpenCVMOG2 background subtractionContour analysis
Tracking
Euclidean-distance associationTrack lifecycle
Runtime
PythonNumPyCPU only
Limitations

Where this approach breaks

⚠️ Honest about a classical method

Background subtraction assumes a fixed camera. Pan the camera and the whole scene reads as motion. It is also sensitive to lighting change, and hard shadows can be detected as objects.

Centre-distance association is deliberately simple. It holds well for separated vehicles moving predictably, and will swap identities when two objects pass close together or one occludes another. A learned detector with appearance-based re-identification is the upgrade path; this project does not claim to be one.

No accuracy figure is claimed — it has not been evaluated against a labelled tracking benchmark.

Classical CV, still earning its place

No training data, no GPU, real time on a laptop. Worth knowing when a learned model is the right answer and when it is overkill.