The problem
Low-cost ADAS often has only a single front camera, so it must infer range without a radar or stereo pair. Monocular range relies on assumptions such as a flat road, a known camera height or a typical vehicle width, and each assumption fails in different situations. Quantifying those errors shows when a camera-only warning can be trusted.
Objectives
- Calibrate a camera and understand the pinhole projection model.
- Implement ground-contact and known-width distance estimators.
- Evaluate both against lidar-derived ground truth from KITTI.
- Smooth the distance with a filter and compute time to collision.
- Analyse error sources: pitch, slope, width variation and detection box error.
What you need
Tools and toolboxes
- Python — Estimators, filtering, evaluation and plots.
- OpenCV — Chessboard calibration, undistortion and drawing.
- Ultralytics YOLO — A pretrained detector to provide vehicle bounding boxes.
- NumPy — Projection maths and a constant-velocity Kalman filter.
Software
- Python 3 with OpenCV, NumPy and Ultralytics
- KITTI object detection dataset with calibration files and 3-D labels
- Matplotlib and pandas
Extra parts and data
- Webcam or phone camera and a printed chessboard — Needed to practise intrinsic calibration and to check distances against tape-measured targets in a car park or corridor.
Key concepts
- Pinhole camera model
- A point at depth Z projects to image coordinates scaled by the focal length f divided by Z. Calibration finds f, the principal point and lens distortion.
- Ground-contact method
- With known camera height h and a flat road, the image row of the vehicle's bottom edge gives distance as approximately f·h divided by the row offset below the horizon.
- Known-width method
- If a vehicle's real width W is assumed, distance is f·W divided by the box width in pixels. Errors come from width variation between vehicle types.
- Time to collision
- Distance divided by closing speed. It is the main quantity for forward collision warning thresholds.
Step-by-step guide
- 1
Set requirements and assumptions
Define the target: distance error within a stated percentage up to 40 metres and a usable time-to-collision estimate for a forward collision warning. List the assumptions each method needs: flat road and known camera height for ground contact, known vehicle width for the width method, and correct detection boxes for both. Plan to test each assumption explicitly, because the purpose is to learn where each method breaks.
Checkpoint: A requirements and assumptions table linked to planned tests.
- 2
Calibrate a camera
Print a chessboard, capture 15 to 25 images at different angles and distances, and run cv2.findChessboardCorners and cv2.calibrateCamera to get the camera matrix and distortion coefficients. Check the reprojection error and undistort a test image. This step builds understanding of the intrinsics before using KITTI's provided calibration, and the same camera is used later for a tape-measured check. Store the camera matrix and distortion coefficients in a file that every later script loads, rather than copying numbers by hand.
Checkpoint: A reprojection error below about half a pixel and a visibly corrected undistorted image.
- 3
Prepare KITTI ground truth
Load KITTI object labels, which give each car's 3-D location in camera coordinates, and the calibration file with the projection matrix. For each labelled car ahead, take the longitudinal distance Z as ground truth. Select frames where the car is roughly in the ego lane and not truncated. Split the selected frames into a tuning set for choosing parameters and a test set for reporting.
Checkpoint: A table of selected KITTI objects with image boxes and true distances, split into tuning and test.
- 4
Implement the ground-contact estimator
Find the horizon row from the camera height and pitch (KITTI gives a near-level camera mounted about 1.65 m above the road). For each car, take the bottom edge of its box as the ground contact row and compute Z = f·h / (y_bottom − y_horizon). Evaluate first with ground-truth boxes to isolate the geometric error, then with detector boxes to add detection error.
Checkpoint: Distance error against true distance, plotted for ground-truth and detected boxes.
- 5
Implement the known-width estimator
Compute Z = f·W / w_pixels with an assumed width, for example 1.8 m for cars. Evaluate with ground-truth boxes and then detector boxes. Compare the error spread with the ground-contact method and check how it depends on true vehicle width by using KITTI's 3-D dimensions. Note that the width method does not depend on road slope but is sensitive to box width errors at long range.
Checkpoint: Error plots for the width method and a comparison table with ground contact.
- 6
Detect vehicles and associate the lead car
Run a pretrained YOLO model on the frames, keep car, bus and truck detections and match them to KITTI labels with IoU above 0.5. For sequences, pick the lead vehicle as the nearest detection whose box centre lies in the ego-lane region. Record detection misses and box errors, since they propagate into distance error. Measure box error as the pixel difference in bottom edge and width between matched detections and labels, since these are exactly the quantities each distance estimator uses. Report it by distance band.
Checkpoint: Matched detections with measured box error and a lead-vehicle selection that works on test sequences.
- 7
Filter distance and compute TTC
On KITTI tracking sequences, run a constant-velocity Kalman filter on the per-frame distance from the better estimator, with state [distance, relative speed]. Tune process and measurement noise on tuning sequences. Compute time to collision as distance divided by closing speed when closing, and compare filtered against raw estimates. Note how noisy the speed estimate is, because TTC depends on it directly.
Checkpoint: Filtered distance and TTC plots showing reduced noise compared with raw values.
- 8
Test the assumptions
Break the assumptions deliberately: change the assumed camera pitch by one or two degrees and measure the change in ground-contact error, use widths for trucks and two-wheelers with the car width assumption, and evaluate frames on slopes if present. Do a small physical check with your own calibrated camera and a parked car at tape-measured distances in a car park, with permission and the vehicle stationary.
Checkpoint: A sensitivity table of error against pitch error and vehicle type, and results from the physical check.
- 9
Report
Present the calibration, both estimators, test-set error by distance band, filtered TTC results and the assumption tests. Conclude which method to use in which situation and what a fusion of both would look like. State the limitations: flat-road assumption, few vehicle types and detector box quality. Include code and the list of KITTI frames used so the numbers can be reproduced.
Checkpoint: A report with error tables by distance band and reproducible scripts.
Testing & validation
- Distance error by distance band for both estimators on KITTI test frames.
- Separate error contributions from geometry and from detection boxes.
- Sensitivity to pitch error and vehicle width.
- Physical check against tape-measured distances.
Expected results
Two monocular range estimators with measured accuracy against lidar ground truth, a filtered TTC estimate and a clear map of the assumptions that limit camera-only ranging.
Take it further
- Fuse both estimators in the Kalman filter with distance-dependent noise.
- Compare with a learned monocular depth network on the same frames.
- Estimate pitch online from lane vanishing points.
- Use the TTC estimate to drive a simple forward collision warning.
Viva and review questions
Why does ground-contact error grow quickly with distance?
Distant vehicles sit only a few pixels below the horizon, so a one-pixel error in the bottom edge or a small pitch error causes a large change in computed distance.
Which method is insensitive to road slope?
The known-width method, because it uses the vehicle's apparent size rather than its position relative to the horizon, though it depends on the assumed width.
Why filter distance before computing TTC?
TTC divides by closing speed, which is a derivative of distance; differentiating raw noisy distance gives very noisy speed and unusable TTC.
What does the camera calibration give you?
The focal lengths, principal point and lens distortion coefficients, which are needed to relate pixel positions to real angles and distances.
Learn it at DIYguru
These DIYguru courses and programmes teach what this project needs.
