The system integrates multiple traffic analysis capabilities into a single pipeline using object detection and multi‑object tracking. It supports YOLO variants from v5 to v11 in combination with DeepSORT to track vehicles, count them by direction, estimate instantaneous speed, detect potential collisions, and identify illegal entries into dedicated lanes. The implementation runs on both x86 and ARM‑based edge devices, accepting video files or live camera streams.
Environment Setup
A Python 3.8 virtual environment is recommended. Install PyTorch according to your hardware; for GPU support with CUDA 10.2:
conda create -n traffic python=3.8.5
conda activate traffic
conda install pytorch==1.8.0 torchvision torchaudio cudatoolkit=10.2
Additional dependencies are installed via requirements.txt:
pip install pycocotools-windows
pip install -r requirements.txt
Vehicle Detection, Tracking, and Counting
Detection is performed by a YOLO model fine‑tuned on a dataset of cars, trucks, and buses. The weight file best.pt is loaded; class filters [0,1,2] correspond to these three categories. DeepSORT associates detections across frames to maintain identity.
Counting logic divides the scene into four quadrants using two perpendicular reference lines. A vehicle whose center crosses from the upper region to the lower region is counted as "downstream", while movement in the opposite direction counts as "upstream". The implementation uses successive if‑elif conditions that compare the bounding box center coordinates against the boundary lines. The total and per‑class counts are overlaid on the top‑left corner of the output frame, and each tracked object is annotated with its class name and ID.
Speed Estimation
Speed is derived from the displacement of a vehicle’s bounding box center between consecutive frames. A initial calibration step relates real‑world width to pixel width using a known vehicle dimension. The ratio real_width / pixel_width serves as a scaling factor. The core computation is:
def compute_speeds(track_history, fps, class_widths):
current_ids = [item[2] for item in track_history[1]]
previous_ids = [item[2] for item in track_history[0]]
common_ids = [cid for cid in current_ids if cid in previous_ids]
speeds = []
for uid in common_ids:
curr = next(x for x in track_history[1] if x[2] == uid)
prev = next(x for x in track_history[0] if x[2] == uid)
dx = curr[0] - prev[0]
dy = curr[1] - prev[1]
scale = class_widths[curr[3]] / (curr[4] + 1e-6)
dist_pixel = (dx**2 + dy**2) ** 0.5
# Convert pixel distance to meters and then to km/h
speed_kmh = dist_pixel * scale * fps / 5 * 3.6 * 2
speeds.append([round(speed_kmh, 1), uid])
return speeds
This linear mapping assumes the camera axis is approximately perpendicular to the traffic flow. For angled views the readings will be underestimated. The result is displayed above each vehicle. A threshold can be applied to flag speeding events.
Collision Detection
The system checks every pair of detected bounding boxes. If the intersection area (or overlapping dimensions) exceeds a threshold, a collision is registered. A tunable parameter overlap_threshold controls sensitivity. The algorithm loops over all unique pairs and evaluates overlap conditions. A simplified, robust version uses intersection over union (IoU) or intersection over smaller area:
def check_collisions(boxes, overlap_px=50):
collisions = []
for i in range(len(boxes)):
for j in range(i+1, len(boxes)):
xA = max(boxes[i][0], boxes[j][0])
yA = max(boxes[i][1], boxes[j][1])
xB = min(boxes[i][2], boxes[j][2])
yB = min(boxes[i][3], boxes[j][3])
inter_w = max(0, xB - xA)
inter_h = max(0, yB - yA)
if inter_w > overlap_px and inter_h > overlap_px:
collisions.append((i, j))
return collisions
When a collision is detected, the involved IDs are loggged and a warning is rendered on the frame. Adjusting overlap_px controls how aggressively the system warns; a lower value acts as a proximity alert.
Restricted Lane Violation Detection
A polygonal region representing, for example, a bus lane or emergency shoulder, is defined interactively. The user clicks four clockwise vertices on the first frame; the coordinates and the line equations of the four edges are saved. During inference, the center of each detected vehicle is tested against these lines:
# For each vehicle center (cx, cy) and class
inside = (slopes[0]*cx + intercepts[0] <= cy and
slopes[1]*cx + intercepts[1] >= cy and
slopes[2]*cx + intercepts[2] >= cy and
slopes[3]*cx + intercepts[3] <= cy)
if inside and vehicle_class != BUS_CLASS:
cv2.putText(frame, 'Entering illegally!', (cx-140, cy),
cv2.FONT_HERSHEY_PLAIN, 1.5, (0,0,255), 2)
The rule can be extended with time‑based permissions by reading the system clock and comparing against allowed intervals. The same mechanism applies to detecting vehicles parked in forbidden zones or driving on the hard shoulder.
All modules share the same detection backbone and tracking state, making the pipeline efficient for real‑time applications on edge hardware.