Rethinking BiSeNet For Real-time Semantic Segmentation
Paper • 2104.13188 • Published
This is a redistribution (a "mirror"), not a new model. The weights are the official STDC2-Seg75 Cityscapes checkpoint from MichaelFan01/STDC-Seg, re-hosted here for convenient, stable, programmatic access via
huggingface_hub. All credit to the original authors.
| Architecture | Short-Term Dense Concatenate Network (CVPR 2021) |
| Variant | STDC2-Seg75 (STDCNet1446 backbone) |
| Pretraining | Cityscapes semantic segmentation, 19 classes (full fine-tuned checkpoint) |
| Reported metric | 77.04 mIoU (single-scale) on Cityscapes val |
| Upstream repository | https://github.com/MichaelFan01/STDC-Seg |
| Upstream weights | https://drive.google.com/drive/folders/1wROFwRt8qWHD4jSo8Zu1gp1d6oYJ3ns1 |
| Upstream license | MIT; mirrored as LICENSE in this repo |
Nothing in the weights. The upstream file is already a bare fp32 state_dict with no optimizer state. Only what is needed to load the model is kept:
| Component | Upstream | This mirror |
|---|---|---|
state_dict (model weights, fp32) |
yes | yes, unchanged |
The tensors are byte-identical to the upstream file. checksums.txt in this repo carries the
SHA-256 of the mirrored file.
The STDC-Seg architecture (BiSeNet in models/model_stages.py) is not packaged, so
clone the upstream repo and run from its root.
git clone https://github.com/MichaelFan01/STDC-Seg
cd STDC-Seg
pip install torch torchvision pillow numpy huggingface_hub
import numpy as np
import torch
import torch.nn.functional as F
from PIL import Image
from huggingface_hub import hf_hub_download
from models.model_stages import BiSeNet
weights = hf_hub_download("dronefreak/stdc2-seg-cityscapes", "stdc2-seg_cityscapes.pth")
net = BiSeNet(
backbone="STDCNet1446", n_classes=19,
use_boundary_2=False, use_boundary_4=False,
use_boundary_8=True, use_boundary_16=False, use_conv_last=False,
)
net.load_state_dict(torch.load(weights, map_location="cpu"), strict=False) # skips the training-only boundary heads
net.eval()
# inference on a single image, following the repo's Seg75 eval (resize to scale, then back)
MEAN = torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1)
STD = torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1)
img = Image.open("street.jpg").convert("RGB")
x = torch.from_numpy(np.asarray(img, np.float32) / 255.0).permute(2, 0, 1)[None]
x = (x - MEAN) / STD
H, W = x.shape[-2:]
x = F.interpolate(x, (int(H * 0.75), int(W * 0.75)),
mode="bilinear", align_corners=True)
with torch.no_grad():
logits = net(x)[0]
logits = F.interpolate(logits, (H, W), mode="bilinear", align_corners=True)
seg = logits.argmax(1)[0].byte().numpy() # (H, W) trainId map, 0..18
PALETTE = np.array([
(128, 64, 128), (244, 35, 232), (70, 70, 70), (102, 102, 156), (190, 153, 153),
(153, 153, 153), (250, 170, 30), (220, 220, 0), (107, 142, 35), (152, 251, 152),
(70, 130, 180), (220, 20, 60), (255, 0, 0), (0, 0, 142), (0, 0, 70),
(0, 60, 100), (0, 80, 100), (0, 0, 230), (119, 11, 32),
], dtype=np.uint8)
Image.fromarray(PALETTE[seg]).save("street_pred.png")
net(x) returns (main, aux16, aux32); take [0].
% Rethinking BiSeNet for Real-Time Semantic Segmentation, CVPR 2021 (arXiv:2104.13188)
@inproceedings{fan2021rethinking,
title = {Rethinking {BiSeNet} for Real-Time Semantic Segmentation},
author = {Fan, Mingyuan and Lai, Shenqi and Huang, Junshi and Wei, Xiaoming and Chai, Zhenhua and Luo, Junfeng and Wei, Xiaolin},
booktitle = {Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
year = {2021}
}