Object detection powers everything from smart cameras to autonomous robots. In this post I'll walk through the code behind my RT-DETR Object Detection System, a Python project using the RT-DETR model (PekingU/rtdetr_r50vd) for real-time and batch image processing.
Instead of just running the code, we'll dissect each script to understand how it works, from downloading the model to drawing bounding boxes. Let's explore the magic of computer vision with Python, OpenCV, and Transformers.
What's This Project About?
The RT-DETR Object Detection System uses a transformer-based model to detect objects in webcam feeds or image folders, annotating them with labeled bounding boxes. The project, built with Python, OpenCV, PyTorch, and the Transformers library, consists of three key scripts:
local_save.py: Downloads and saves the RT-DETR model.main.py: Orchestrates detection for webcam or image inputs.utils.py: Handles model loading and visualization.
This walkthrough explains what each script does, line by line, to help you understand object detection under the hood.
Full code is on GitHub: DiamondDolby/rtdetr-object-detector
Script 1: local_save.py — Fetching the RT-DETR Model
The local_save.py script prepares the RT-DETR model for use by downloading it from the Hugging Face Transformers library and saving it locally.
from transformers import AutoImageProcessor, AutoModelForObjectDetection
# Pre-Trained RT-DETR model
model_name = "PekingU/rtdetr_r50vd"
# Local Folder
save_path = "src/rtdetr_model"
# Setting up image processor and neural network
processor = AutoImageProcessor.from_pretrained(model_name)
model = AutoModelForObjectDetection.from_pretrained(model_name)
# Save to local folder
processor.save_pretrained(save_path)
model.save_pretrained(save_path)
What's happening?
- Imports: We use
AutoImageProcessorandAutoModelForObjectDetectionfrom the transformers library to handle image preprocessing and the RT-DETR model. - Model name:
PekingU/rtdetr_r50vdis the pre-trained RT-DETR model hosted on Hugging Face. - Processor and model: the processor prepares images for the model (resizing, normalizing), while the model is the neural network for detection.
- Saving locally:
save_pretrained(save_path)stores the model and processor insrc/rtdetr_modelfor offline use, reducing dependency on internet access.
This script ensures the model is ready before running detection tasks.
Script 2: main.py — The Control Center
The main.py script is the entry point, letting users choose between webcam or image folder modes and coordinating the detection process.
import os
import cv2
import torch
from utils import load_model, draw_boxes
# Load model
processor, model = load_model()
model.eval()
We use cv2 (OpenCV) for image/video handling, torch for model inference, and custom load_model and draw_boxes from utils.py. load_model() retrieves the saved model and processor, and model.eval() sets the model to evaluation mode (disabling training-specific operations).
def detect_from_webcam():
cap = cv2.VideoCapture(0) # Change to 1 if using an external webcam
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
frame_count += 1
if frame_count % 3 != 0: # change number to skip frames
continue # Skip every 3 frames
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
inputs = processor(images=rgb, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
annotated = draw_boxes(frame, outputs, processor, model)
cv2.imshow("RT-DETR Live Feed", annotated)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
This is webcam mode (detect_from_webcam). Here's what's happening:
- Opens the default webcam (
cv2.VideoCapture(0)). - Skips every third frame (
frame_count % 3) for performance. - Converts frames to RGB (
cv2.cvtColor), since RT-DETR expects RGB input. - Processes frames with the processor to create model inputs.
- Runs inference (
model(**inputs)) without gradient computation for efficiency. - Calls
draw_boxesto annotate frames and displays them (cv2.imshow). - Exits on pressing
q.
def detect_from_images():
input_folder = "images"
output_folder = "output"
os.makedirs(output_folder, exist_ok=True)
for filename in os.listdir(input_folder):
if filename.lower().endswith((".jpg", ".png", ".jpeg")):
path = os.path.join(input_folder, filename)
image = cv2.imread(path)
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
inputs = processor(images=rgb, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
annotated = draw_boxes(image, outputs, processor, model)
cv2.imwrite(os.path.join(output_folder, filename), annotated)
print(f"Saved: {filename}")
This is image mode (detect_from_images). It loops through images in the images/ folder, reads and processes each one the same way as webcam mode, then saves annotated images to output/ with cv2.imwrite.
if __name__ == "__main__":
mode = input("Choose mode (1 = webcam, 2 = image folder): ")
if mode == "1":
detect_from_webcam()
elif mode == "2":
detect_from_images()
else:
print("Invalid mode.")
This is the user interface: the if __name__ == "__main__": block prompts the user to choose a mode via input, making the pipeline user-friendly and versatile.
Script 3: utils.py — The Helper Functions
The utils.py script contains reusable functions for loading the model and visualizing detections.
import cv2
import torch
from transformers import AutoImageProcessor, AutoModelForObjectDetection
def load_model():
processor = AutoImageProcessor.from_pretrained("src/rtdetr_model")
model = AutoModelForObjectDetection.from_pretrained("src/rtdetr_model")
return processor, model
load_model() loads the saved processor and model from src/rtdetr_model, and returns both for use in main.py.
def draw_boxes(image, outputs, processor, model, threshold=0.3):
target_sizes = [image.shape[:2][::-1]] # (height, width) -> (width, height)
results = processor.post_process_object_detection(outputs, target_sizes=target_sizes, threshold=threshold)[0]
id2label = model.config.id2label
for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
box = [int(i) for i in box.tolist()]
cv2.rectangle(image, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)
cv2.putText(image, f"{id2label[label.item()]}: {score:.2f}",
(box[0], box[1]-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2)
return image
draw_boxes() takes the input image, model outputs, processor, and model. It converts image dimensions to (width, height) for the processor, uses processor.post_process_object_detection to extract detections (boxes, scores, labels) at a confidence threshold of 0.3, maps label IDs to names via model.config.id2label, and draws green rectangles with labels and confidence scores on the image.
Keeping this logic in utils.py separates model loading and visualization from the main execution, so the codebase stays modular.
Why This Matters
The RT-DETR model leverages transformer architecture, using attention mechanisms to focus on relevant image regions, which makes it fast and accurate. Breaking down the code this way shows how it integrates with OpenCV for visualization and PyTorch for inference, a practical introduction to computer vision that applies whether you're processing real-time video or batch images with a state-of-the-art model.
Try It Yourself
The full project is open-source under the MIT License on GitHub: DiamondDolby/rtdetr-object-detector.
To run it: install dependencies (opencv-python, torch, transformers), download the model with local_save.py, and execute main.py. Try experimenting with the confidence threshold, or add new features like video file support.