Object Detection Yolo R-CNN Real-Time Localization
# Object Detection: YOLO, R-CNN & Real-Time Localization
## Introduction & Motivation
Object detection: localize and classify objects. YOLO: single-stage detector; real-time (45+ fps). R-CNN: region-based; more accurate. Anchor-free (CenterNet), anchor-based trade-offs. Applications: autonomous driving, surveillance, robotics.
Motivation: Classification insufficient; need bounding box. Real-time constraint (YOLO) vs. accuracy (R-CNN).
Applications: Autonomous vehicles, video surveillance, medical imaging, robotics.
---
## Core Concepts & Theory
### Bounding Box Regression
Predict (x, y, w, h) or (x1, y1, x2, y2) coordinates. Loss: smooth L1.
### Anchor Boxes
Pre-defined aspect ratios/scales; model predicts offsets.
### Non-Maximum Suppression (NMS)
Remove duplicate detections; keep highest confidence.
---
## Mathematical Formulation
YOLO loss (bbox + objectness + class):
$$\mathcal{L} = \sum_i^{S^2} \sum_j^B \mathbb{I}_{ij}^{ ext{obj}} \left[ (x_i - \hat{x}_i)^2 + (y_i - \hat{y}_i)^2
ight] + \cdots$$
IOU (Intersection over Union):
$$ ext{IoU} = \frac{A \cap B}{A \cup B}$$
NMS selection rule:
$$ ext{keep if } ext{IoU}( ext{box}, ext{best}) < ext{threshold}$$
---
## Advanced Theory & Extensions
### Feature Pyramid Networks (FPN)
Multi-scale detection; handle objects at different scales.
### Region Proposal Networks (RPN)
Generate region proposals; reduce search space.
### Focal Loss
Address class imbalance; weight hard negatives.
---
## Computational Considerations
YOLO: O(1) forward pass; real-time feasible.
R-CNN: O(N) region proposals; slower but accurate.
NMS: O(N²) pairwise IoU; can be optimized.
---
## Practical Implementation Strategies
### Anchor Design
Multiple scales/aspect ratios; balance coverage.
### Loss Weighting
Balance classification, bbox regression, objectness.
### Hard Negative Mining
Focus on hard examples; improve convergence.
---
## Benchmark Datasets & Evaluation
COCO: 80 classes; standard detection benchmark.
Pascal VOC: 20 classes; historical baseline.
Metrics: mAP (mean Average Precision), [email protected], [email protected].
---
## Key Challenges & Limitations
### Scale Variation
Objects vary greatly in size; FPN helps.
### Class Imbalance
Background examples vastly outnumber objects.
### Real-Time Constraint
Accuracy-speed trade-off; YOLO faster but less accurate.
---
## Hyperparameter Tuning
Anchor scales: 3-5 scales; aspect ratios 1:1, 2:1, 1:2.
NMS threshold: 0.3-0.5; lower = more aggressive.
Confidence threshold: 0.3-0.5; varies by application.
---
## Real-World Applications & Case Studies
Autonomous Driving: YOLO/Faster R-CNN for real-time detection.
Medical Imaging: R-CNN for tumor/pathology detection.
Surveillance: Real-time person/vehicle detection via YOLO.
---
## Integration with Other Methods
Object Detection + Tracking → temporal consistency.
Object Detection + Segmentation → instance segmentation.
---
## Summary & Key Takeaways
Object detection combines classification and localization via anchor-based or anchor-free methods, with YOLO prioritizing speed and R-CNN prioritizing accuracy.
Principles:
1. Bounding box regression: predict coordinates offset from anchors.
2. YOLO: single-stage, real-time; R-CNN: region-based, accurate.
3. IoU measures overlap; NMS removes duplicates.
4. Multi-scale features (FPN) handle scale variation.
5. Focal loss addresses background class imbalance.
---
---
## Appendix: Practical Labs
### Lab 1: IoU Computation
import torch
import numpy as np
def compute_iou(box1, box2):
"""Compute IoU between two bounding boxes (x1, y1, x2, y2)"""
x1_min, y1_min, x1_max, y1_max = box1
x2_min, y2_min, x2_max, y2_max = box2
# Intersection
inter_x_min = max(x1_min, x2_min)
inter_y_min = max(y1_min, y2_min)
inter_x_max = min(x1_max, x2_max)
inter_y_max = min(y1_max, y2_max)
inter_area = max(0, inter_x_max - inter_x_min) * max(0, inter_y_max - inter_y_min)
# Union
box1_area = (x1_max - x1_min) * (y1_max - y1_min)
box2_area = (x2_max - x2_min) * (y2_max - y2_min)
union_area = box1_area + box2_area - inter_area
iou = inter_area / (union_area + 1e-8)
return iou
# Test
box1 = [0, 0, 10, 10]
box2 = [5, 5, 15, 15]
iou = compute_iou(box1, box2)
print(f"IoU: {iou:.4f}")
assert 0 <= iou <= 1, "IoU should be in [0,1]"
assert np.isclose(iou, 0.25), "Should match expected value"
print("✓ IoU computation working")
if __name__ == "__main__":
print("Lab 1: IoU - PASSED")### Lab 2: Non-Maximum Suppression
import torch
import numpy as np
def nms(boxes, scores, iou_threshold=0.5):
"""Non-Maximum Suppression"""
# Sort by score descending
sorted_idx = torch.argsort(scores, descending=True)
keep = []
while len(sorted_idx) > 0:
current = sorted_idx[0]
keep.append(current)
if len(sorted_idx) == 1:
break
# Compute IoU with remaining boxes
current_box = boxes[current]
other_boxes = boxes[sorted_idx[1:]]
ious = torch.tensor([
compute_iou_torch(current_box, box) for box in other_boxes
])
# Keep only low IoU
sorted_idx = sorted_idx[1:][ious < iou_threshold]
return keep
def compute_iou_torch(box1, box2):
x1_min, y1_min, x1_max, y1_max = box1
x2_min, y2_min, x2_max, y2_max = box2
inter_x_min = max(x1_min, x2_min)
inter_y_min = max(y1_min, y2_min)
inter_x_max = min(x1_max, x2_max)
inter_y_max = min(y1_max, y2_max)
inter_area = max(0, inter_x_max - inter_x_min) * max(0, inter_y_max - inter_y_min)
box1_area = (x1_max - x1_min) * (y1_max - y1_min)
box2_area = (x2_max - x2_min) * (y2_max - y2_min)
union_area = box1_area + box2_area - inter_area
return inter_area / (union_area + 1e-8)
# Test
boxes = torch.tensor([[0., 0., 10., 10.], [5., 5., 15., 15.], [20., 20., 30., 30.]])
scores = torch.tensor([0.9, 0.8, 0.85])
keep_idx = nms(boxes, scores, iou_threshold=0.3)
print(f"NMS kept indices: {keep_idx}")
assert len(keep_idx) <= len(boxes), "Should reduce number of boxes"
print("✓ NMS working")
if __name__ == "__main__":
print("Lab 2: NMS - PASSED")### Lab 3: Anchor Box Generation
import torch
import numpy as np
def generate_anchors(image_size=416, feature_map_size=13, scales=[1.0], aspect_ratios=[1.0]):
"""Generate anchor boxes for image"""
stride = image_size // feature_map_size
anchors = []
for y in range(feature_map_size):
for x in range(feature_map_size):
cx = (x + 0.5) * stride
cy = (y + 0.5) * stride
for scale in scales:
for ar in aspect_ratios:
w = stride * scale * np.sqrt(ar)
h = stride * scale / np.sqrt(ar)
anchors.append([cx, cy, w, h])
return np.array(anchors)
# Test
anchors = generate_anchors(image_size=416, feature_map_size=13, scales=[0.5, 1.0], aspect_ratios=[1.0, 2.0])
print(f"Generated {len(anchors)} anchors")
assert len(anchors) == 13 * 13 * 2 * 2, "Should have correct count"
assert all(a[2] > 0 and a[3] > 0 for a in anchors), "Widths/heights should be positive"
print("✓ Anchor generation working")
if __name__ == "__main__":
print("Lab 3: Anchors - PASSED")### Lab 4: Bounding Box Regression Target
import torch
import numpy as np
def compute_bbox_target(anchor, gt_box):
"""Compute regression target from anchor to GT box"""
ax, ay, aw, ah = anchor
gx, gy, gw, gh = gt_box
# Regression targets (log-space for scale)
tx = (gx - ax) / aw
ty = (gy - ay) / ah
tw = np.log(gw / aw)
th = np.log(gh / ah)
return np.array([tx, ty, tw, th])
def inverse_bbox_target(anchor, target):
"""Decode: prediction to predicted box"""
ax, ay, aw, ah = anchor
tx, ty, tw, th = target
px = ax + aw * tx
py = ay + ah * ty
pw = aw * np.exp(tw)
ph = ah * np.exp(th)
return np.array([px, py, pw, ph])
# Test
anchor = np.array([50, 50, 30, 30])
gt_box = np.array([55, 52, 35, 28])
target = compute_bbox_target(anchor, gt_box)
pred_box = inverse_bbox_target(anchor, target)
print(f"Regression target: {target}")
print(f"Reconstructed box: {pred_box}")
assert np.allclose(pred_box, gt_box, atol=1.0), "Should reconstruct GT box"
print("✓ Bbox regression target working")
if __name__ == "__main__":
print("Lab 4: Bbox Target - PASSED")