rampnet-model / rampnet_model.py
jonfroehlich's picture
Re-export with transformers-compatible RampNetModel wrapper + corrected card (fixes #19); weights unchanged from v1.0-paper
606a119 verified
Raw
History Blame Contribute Delete
1.69 kB
import timm
import torch.nn as nn
BACKBONE_NAME = 'convnextv2_base.fcmae_ft_in22k_in1k_384'
# Panorama model (stage_two): equirectangular 2048x4096 input -> 512x1024 heatmap.
PANO_INPUT_SIZE = (2048, 4096)
PANO_HEATMAP_SIZE = (512, 1024)
# Crop model (stage_one): perspective 1024x352 input -> 256x88 heatmap.
CROP_INPUT_SIZE = (1024, 352)
CROP_HEATMAP_SIZE = (256, 88)
IMAGENET_MEAN = [0.485, 0.456, 0.406]
IMAGENET_STD = [0.229, 0.224, 0.225]
class KeypointModel(nn.Module):
"""The one canonical RampNet keypoint-heatmap model.
The state_dict key layout (feature_extractor as Sequential over
backbone.children()[:-2], i.e. dropping norm_pre and head) is the layout
every released checkpoint was trained and saved with — including the
HuggingFace weights. Do not restructure the modules (e.g. features_only=True
or named submodules): that changes the keys and breaks strict loading of
all existing checkpoints.
"""
def __init__(self, heatmap_size=PANO_HEATMAP_SIZE, pretrained_backbone=False):
super().__init__()
backbone = timm.create_model(BACKBONE_NAME, pretrained=pretrained_backbone)
self.feature_extractor = nn.Sequential(*list(backbone.children())[:-2])
in_channels = backbone.num_features
self.head = nn.Sequential(
nn.Conv2d(in_channels, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Upsample(size=heatmap_size, mode='bilinear', align_corners=False),
nn.Conv2d(256, 1, kernel_size=1)
)
def forward(self, image):
features = self.feature_extractor(image)
heatmap = self.head(features)
return heatmap