← Назад к вопросам

Что такое multi-scale детекция?

3.0 Senior🔥 101 комментариев
#Глубокое обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Multi-scale детекция объектов

Основная идея

Multi-scale детекция — это подход в компьютерном зрении, когда модель детектирует объекты разного размера на разных уровнях абстракции (разных масштабах). Проблема в том, что объекты в изображениях могут быть разного размера: маленькие людиши вдали и большие люди вблизи.

Почему нужна multi-scale детекция?

Проблема: простый CNN с одним выходом плохо работает с объектами разного размера.

Обычный детектор смотрит на изображение один раз:
- Маленькие объекты теряются (не достаточно деталей)
- Большие объекты могут быть фрагментированы (каждая часть предсказывается отдельно)

Способ 1: Пирамида изображений (Image Pyramid)

Построить несколько копий изображения разных масштабов:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('photo.jpg')

# Пирамида Гаусса
pyramid = [img]
for i in range(3):
    pyramid.append(cv2.pyrDown(pyramid[-1]))

# Визуализация
fig, axes = plt.subplots(1, 4)
for i, p in enumerate(pyramid):
    axes[i].imshow(p)
    axes[i].set_title(f'Scale {i}: {p.shape}')
plt.show()

# Запустить детектор на каждом масштабе
detections = []
for scale_level, scaled_img in enumerate(pyramid):
    dets = detector(scaled_img)
    # Масштабировать координаты обратно к оригиналу
    scale_factor = 2 ** scale_level
    dets['boxes'] *= scale_factor
    detections.append(dets)

Плюсы:

  • Простой и понятный
  • Хорошо работает с маленькими объектами

Минусы:

  • Медленно (нужно обрабатывать несколько изображений)
  • Потребление памяти
  • Много дублирующихся вычислений

Способ 2: Пирамида признаков (Feature Pyramid Network, FPN)

Модерный подход — использовать несколько уровней детальности из одного прохода CNN:

import torch
import torch.nn as nn
from torchvision.models.detection.backbone_utils import BackboneWithFPN
from torchvision.ops import FeaturePyramidNetwork

# Стандартный backbone (ResNet)
backbone = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True)

# Извлечь признаки на разных уровнях
class ResNet50WithFPN(nn.Module):
    def __init__(self):
        super().__init__()
        # Conv1 → Conv5 слои ResNet
        self.conv1 = backbone.conv1
        self.bn1 = backbone.bn1
        self.relu = backbone.relu
        self.maxpool = backbone.maxpool
        self.layer1 = backbone.layer1  # stride=1, channels=256
        self.layer2 = backbone.layer2  # stride=2, channels=512
        self.layer3 = backbone.layer3  # stride=4, channels=1024
        self.layer4 = backbone.layer4  # stride=8, channels=2048
        
        # Feature Pyramid Network
        self.fpn = FeaturePyramidNetwork(
            in_channels_list=[256, 512, 1024, 2048],
            out_channels=256
        )
    
    def forward(self, x):
        # Backbone
        x = self.relu(self.bn1(self.conv1(x)))
        x = self.maxpool(x)
        
        c1 = self.layer1(x)   # 1/4 разрешение
        c2 = self.layer2(c1)  # 1/8 разрешение
        c3 = self.layer3(c2)  # 1/16 разрешение
        c4 = self.layer4(c3)  # 1/32 разрешение
        
        # FPN объединяет все уровни
        fpn_features = self.fpn({'0': c1, '1': c2, '2': c3, '3': c4})
        
        return fpn_features  # Dict с несколькими масштабами

model = ResNet50WithFPN()
x = torch.randn(1, 3, 800, 600)  # batch, channels, height, width
fpn_outputs = model(x)

print("FPN выходы на разных масштабах:")
for key, feat in fpn_outputs.items():
    print(f"Level {key}: shape {feat.shape}")

Как это работает в Faster R-CNN

1. Входное изображение 800x600
2. ResNet backbone → признаки
3. FPN → несколько уровней признаков:
   - P2: 200x150 (маленькие объекты)
   - P3: 100x75  (средние объекты)
   - P4: 50x37   (большие объекты)
   - P5: 25x18   (очень большие объекты)
4. RPN на каждом уровне с разными anchor размерами
5. Классификация и регрессия

Anchor размеры для разных масштабов

# В Faster R-CNN используются разные anchor размеры для разных уровней
anchor_scales = {
    'P2': [32],      # Маленькие якоря (объекты маленькие)
    'P3': [64],      # Средние якоря
    'P4': [128],     # Большие якоря
    'P5': [256],     # Очень большие якоря
}

anchor_ratios = [0.5, 1, 2]  # aspect ratios на всех уровнях

# Каждая позиция может иметь несколько якорей разных размеров
# На P2 (200x150): 200*150*3 = 90,000 якорей
# На P5 (25x18):   25*18*3 = 1,350 якорей
# Всего: много якорей на разных масштабах

Пример: YOLO v3 (один из первых использовал multi-scale)

# YOLO v3 предсказывает на трёх масштабах одновременно

# Масштаб 1: 13x13 (большие объекты)
# Масштаб 2: 26x26 (средние объекты)
# Масштаб 3: 52x52 (маленькие объекты)

from torchvision.models.detection import yolov3
import torch

model = yolov3(pretrained=True)
x = torch.randn(1, 3, 416, 416)

# YOLOv3 выдаёт 3 выхода (один на масштаб)
# output1: (1, 255, 13, 13)  → большие объекты
# output2: (1, 255, 26, 26)  → средние объекты
# output3: (1, 255, 52, 52)  → маленькие объекты
# (255 = 3 якоря * (4 координаты + 1 уверенность + 80 классов))

Сравнение разных архитектур

АрхитектураMulti-scale подходСкоростьМаленькие объекты
YOLO v1Image pyramidМедленноПлохо
YOLO v2Multi-scale trainingСреднеХорошо
YOLO v33 масштаба выходовБыстроОтлично
Faster R-CNNFPNСреднеХорошо
EfficientDetBiFPN (улучшенная FPN)БыстроОтлично
RetinaNetFPN + Focal LossСреднеХорошо

BiFPN (Bi-directional Feature Pyramid Network)

Улучшение FPN с двусторонней связью:

# Обычная FPN: только top-down
# C5 → P5
# ↑
# C4 → P4 (использует P5)
# ↑
# C3 → P3 (использует P4)
# ↑
# C2 → P2 (использует P3)

# BiFPN: both направления
#   P5 ← P6 ← P7 (down)
#   ↓
#   P4 ← (из P5 и C4) (up-down)
#   ↓
#   P3 ← (из P4 и C3) (up-down)
#   ↓
#   P2 ← (из P3 и C2) (up-down)

Практический пример: детекция в реальной жизни

import cv2
import torch
from torchvision.models.detection import fasterrcnn_resnet50_fpn

model = fasterrcnn_resnet50_fpn(pretrained=True)
model.eval()

img = cv2.imread('photo.jpg')
h, w = img.shape[:2]

# Преобразовать в tensor
img_tensor = torch.from_numpy(img).permute(2, 0, 1).float() / 255

# Детекция (использует FPN для разных масштабов)
with torch.no_grad():
    predictions = model([img_tensor])

boxes = predictions[0]['boxes']
scores = predictions[0]['scores']
labels = predictions[0]['labels']

# Визуализировать
for box, score, label in zip(boxes, scores, labels):
    if score > 0.5:
        x1, y1, x2, y2 = box
        cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
        cv2.putText(img, f'{label}: {score:.2f}', (int(x1), int(y1)-10), 
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

cv2.imshow('Detections', img)
cv2.waitKey(0)

Заключение

Multi-scale детекция — это критически важный компонент современных детекторов объектов. Методы эволюционировали от простых image pyramids к элегантным FPN и BiFPN, которые одновременно работают эффективно и точно. Без multi-scale подхода трудно детектировать объекты разного размера в одном изображении.

Что такое multi-scale детекция? | PrepBro