Spaces:
Sleeping
Sleeping
File size: 4,652 Bytes
d78fec2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # ============================================================
# bev_encoder.py
# ============================================================
#
# ETHUKU CREATE PANNINOM?
# ββββββββββββββββββββββ
# LSS kuduthathu "raw" BEV - just camera features-ai kotti vachathu.
# Antha map-la neighbour cells-ku thodarbu (context) illa.
# Ithu antha map-ai innum smart-a maathum: "intha 4m neelamana blob =
# oru car", "intha vari = road".
#
# MUNADI FILE ODA CONNECTION:
# ββββββββββββββββββββββββββ
# Input : view_transformer.py output [B,64,200,200]
# Output: center_head.py ku [B,128,200,200]
#
# INNER OPERATIONS:
# ββββββββββββββββ
# ResNet-style downsample (200->100->50) -> aprom upsample thirumba 200.
# Yaen keezha-mela? Downsample panna oru pixel periya area paakkum
# (receptive field). Athu illaina 12m lorry-va oru pixel-la puriya mudiyathu.
# FPN-style: chinna map-ai periya map-oda koottrom (details + context rendum).
#
# INPUT / OUTPUT:
# ββββββββββββββ
# Input : [B, 64, 200, 200]
# Output: [B, 128, 200, 200]
#
# EPADI USE AAGUM:
# βββββββββββββββ
# Detection head-ku rich features kudukka.
#
# ============================================================
import torch
import torch.nn as nn
import torch.nn.functional as F
from data.scripts.constants import BACKBONE_OUT_CHANNELS, BEV_OUT_CHANNELS
class BasicBlock(nn.Module):
"""ResNet basic block: conv-bn-relu x2 + skip connection."""
def __init__(self, in_ch: int, out_ch: int, stride: int = 1):
super().__init__()
self.conv1 = nn.Conv2d(in_ch, out_ch, 3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_ch)
self.conv2 = nn.Conv2d(out_ch, out_ch, 3, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_ch)
# Skip connection: input-ai output-oda neradiya koottrom.
# Yaen? Deep network-la gradient vanish aagum. Skip = "highway"
# gradient-ku, so training stable.
# Shape match aagalaina 1x1 conv poattu adjust pannurom.
self.shortcut = nn.Identity()
if stride != 1 or in_ch != out_ch:
self.shortcut = nn.Sequential(
nn.Conv2d(in_ch, out_ch, 1, stride=stride, bias=False),
nn.BatchNorm2d(out_ch),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
out = F.relu(self.bn1(self.conv1(x)), inplace=True)
out = self.bn2(self.conv2(out))
return F.relu(out + self.shortcut(x), inplace=True)
class BEVEncoder(nn.Module):
"""ResNet-18 style encoder + FPN-style decoder on the BEV map."""
def __init__(self, in_channels: int = BACKBONE_OUT_CHANNELS,
out_channels: int = BEV_OUT_CHANNELS):
super().__init__()
# --- Encoder (keezha poguthu) ---
self.layer1 = BasicBlock(in_channels, 64, stride=1) # [B,64,200,200]
self.layer2 = BasicBlock(64, 128, stride=2) # [B,128,100,100]
self.layer3 = BasicBlock(128, 256, stride=2) # [B,256,50,50]
# --- Decoder (mela varuthu) ---
# lateral = 1x1 conv, channel count-ai samam pannurathu
self.lat3 = nn.Conv2d(256, out_channels, 1)
self.lat2 = nn.Conv2d(128, out_channels, 1)
self.lat1 = nn.Conv2d(64, out_channels, 1)
# smooth = upsample panna vandha "blocky" artifacts-ai sari pannum
self.smooth = nn.Sequential(
nn.Conv2d(out_channels, out_channels, 3, padding=1, bias=False),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x: [B, 64, 200, 200] raw BEV from LSS
Returns:
[B, 128, 200, 200] encoded BEV features
"""
c1 = self.layer1(x) # [B, 64, 200, 200] fine details
c2 = self.layer2(c1) # [B,128, 100, 100] medium context
c3 = self.layer3(c2) # [B,256, 50, 50] large context
# Top-down: periya context-ai chinna details-oda koottrom
p3 = self.lat3(c3) # 50x50
p2 = self.lat2(c2) + F.interpolate(p3, scale_factor=2, mode="bilinear",
align_corners=False) # 100x100
p1 = self.lat1(c1) + F.interpolate(p2, scale_factor=2, mode="bilinear",
align_corners=False) # 200x200
return self.smooth(p1) # [B, 128, 200, 200]
|