Bipin Saha

Technical Writeup

টেকনিক্যাল রাইটআপ

From 2D Perception to BEV Fusion: An Implementation Roadmap

2D Perception থেকে BEV Fusion: একটি বাস্তবায়ন রোডম্যাপ

Most teams arrive at 3D perception with a working 2D detector and a pile of sensor logs. The jump to a camera–LiDAR bird's-eye-view stack is less a single model than a sequence of representational commitments, each with its own failure surface. This is the path I recommend, and the pitfalls that cost weeks at each rung.

বেশিরভাগ টিম 3D perception-এ আসে একটি চালু 2D detector আর একগাদা sensor log নিয়ে। camera–LiDAR bird's-eye-view stack-এ লাফটা আসলে একটিমাত্র মডেল নয়, বরং পরপর কতগুলো representational সিদ্ধান্ত, প্রতিটির নিজস্ব failure surface সহ। এই লেখায় আমার সুপারিশ-করা পথ, এবং প্রতিটি ধাপে যেসব ভুল সপ্তাহ খেয়ে ফেলে।

Published 10 Nov 2025 Updated 31 Aug 2026 ~22 min read
প্রকাশ ১০ নভে ২০২৫ হালনাগাদ ৩১ আগস্ট ২০২৬ ~২২ মিনিট পাঠ
  • BEV perception
  • Lift-Splat-Shoot
  • Camera–LiDAR fusion
  • nuScenes
  • Deployment
  • BEV perception
  • Lift-Splat-Shoot
  • Camera–LiDAR fusion
  • nuScenes
  • Deployment

1The ladder, and why order matters

Bird's-eye view (BEV) has become the default intermediate representation for driving perception because it is the frame in which the downstream consumers — prediction, mapping, planning — actually operate. A metric top-down grid is sensor-agnostic, trivially fuses multiple cameras and LiDAR, composes across time by ego-motion, and turns "where is that car going" into a translation on a raster. The research arc from Lift, Splat, Shoot [1] through BEVFusion [15] is, in hindsight, a steady migration of every perception task into this one space.

The mistake I see teams make is to target the final fusion model directly. BEV fusion has a large number of moving parts — two backbones, a view transform, a BEV encoder, a fusion module, a 3D head, a multi-frame buffer, calibration ingestion — and when the first end-to-end training run lands at a disappointing score, there is no way to localize the fault. Build the ladder instead. Each rung is independently checkpointable, has a published baseline you can match, and de-risks exactly one representational decision.

The ladder. Each stage is a shippable checkpoint with a literature baseline to match before proceeding.
StageRepresentationCanonical methodsDe-risks
02D boxes + depth priorYour detector + IPM / mono-depthCalibration, data plumbing
1Monocular / multi-view 3DFCOS3D, PGD, DETR3D [10][6]3D head, loss, coordinate frames
2Camera BEV (single frame)LSS, BEVDet, BEVDepth, BEVFormer [1][3][4]View transform, BEV grid choices
3Camera BEV + temporalBEVDet4D, SOLOFusion, StreamPETR [7][8]Ego-motion warp, velocity
4LiDAR BEVPointPillars, CenterPoint, VoxelNeXt [11][13][14]Sparse conv, voxelization, CBGS
5Camera–LiDAR BEV fusionBEVFusion ×2, TransFusion, CMT [15][16][17][18]Alignment, modality balance
6Multi-task / end-to-end BEVUniAD, VAD [22]Task interference, planning metrics

You do not have to climb every rung to production — many deployed stacks stop at Stage 4 (LiDAR-primary) with camera as a secondary head — but you should build them in order so that each new failure has exactly one plausible cause.

সিঁড়ি, এবং কেন ক্রম গুরুত্বপূর্ণ

Bird's-eye view (BEV) এখন driving perception-এর ডিফল্ট intermediate representation, কারণ এটাই সেই frame যেখানে downstream consumer-রা — prediction, mapping, planning — আসলে কাজ করে। একটি metric top-down grid sensor-নিরপেক্ষ, একাধিক camera ও LiDAR-কে অনায়াসে fuse করে, ego-motion দিয়ে সময়জুড়ে জোড়ে, এবং "ওই গাড়িটা কোথায় যাচ্ছে" প্রশ্নটিকে একটি raster-এর উপর translation-এ পরিণত করে। Lift, Splat, Shoot [1] থেকে BEVFusion [15] পর্যন্ত গবেষণার ধারা, পিছন ফিরে দেখলে, প্রতিটি perception task-কে ধীরে ধীরে এই একটি space-এ সরিয়ে আনার গল্প।

টিমগুলোকে যে ভুলটা করতে দেখি তা হলো সরাসরি চূড়ান্ত fusion মডেল লক্ষ্য করা। BEV fusion-এ অনেকগুলো চলমান অংশ — দুটি backbone, একটি view transform, একটি BEV encoder, একটি fusion module, একটি 3D head, একটি multi-frame buffer, calibration ingestion — এবং প্রথম end-to-end training run যখন হতাশাজনক score-এ পৌঁছায়, তখন ত্রুটি কোথায় তা আলাদা করে বের করার উপায় থাকে না। বরং সিঁড়িটা গড়ুন। প্রতিটি ধাপ আলাদাভাবে checkpoint করা যায়, মেলানোর মতো একটি প্রকাশিত baseline আছে, এবং ঠিক একটি representational সিদ্ধান্তের ঝুঁকি কমায়।

সিঁড়ি। প্রতিটি stage একটি ship-যোগ্য checkpoint, এগোনোর আগে মেলানোর মতো একটি literature baseline সহ।
StageRepresentationCanonical পদ্ধতিযে ঝুঁকি কমায়
2D box + depth priorআপনার detector + IPM / mono-depthCalibration, data plumbing
Monocular / multi-view 3DFCOS3D, PGD, DETR3D [10][6]3D head, loss, coordinate frame
Camera BEV (single frame)LSS, BEVDet, BEVDepth, BEVFormer [1][3][4]View transform, BEV grid পছন্দ
Camera BEV + temporalBEVDet4D, SOLOFusion, StreamPETR [7][8]Ego-motion warp, velocity
LiDAR BEVPointPillars, CenterPoint, VoxelNeXt [11][13][14]Sparse conv, voxelization, CBGS
Camera–LiDAR BEV fusionBEVFusion ×2, TransFusion, CMT [15][16][17][18]Alignment, modality balance
Multi-task / end-to-end BEVUniAD, VAD [22]Task interference, planning metric

Production-এ যেতে প্রতিটি ধাপ বেয়ে ওঠা লাগবে না — অনেক deployed stack Stage 4-এ (LiDAR-primary) থেমে যায়, camera থাকে একটি secondary head হিসেবে — কিন্তু এগুলো ক্রমানুসারে গড়া উচিত যাতে প্রতিটি নতুন failure-এর ঠিক একটি সম্ভাব্য কারণ থাকে।

2Camera 3D: the push / pull split

Once you have a monocular 3D head working (Stage 1: predict a 3D box per 2D detection, supervise with a disentangled L1 on translation / size / yaw plus a depth term), the first real fork is how camera features reach the BEV grid. Two families:

  • Push (forward projection). Predict a per-pixel depth distribution, lift each pixel into a 3D frustum, and scatter ("splat") those features into BEV voxels. LSS [1], BEVDet [2], and BEVDepth [3] are this lineage. The transform is explicit and geometry-faithful, but its quality is capped by the depth prediction.
  • Pull (backward projection). Seed BEV queries at fixed grid locations, project each query into every camera, and gather image features by attention. BEVFormer [4] uses deformable spatial cross-attention; the PETR family [5] and DETR3D [6] fold 3D position into the key/value encoding so the "grid" is implicit in the queries. No explicit depth is required, but every query pays attention over all views.

Practical guidance: if you will fuse with LiDAR, start with push. The splatted camera BEV feature map lands in the same tensor layout as a LiDAR BEV feature map, so Stage 5 fusion is a concatenation-plus-conv rather than a redesign — this is precisely the design that made BEVFusion "simple" [15][16]. If you are camera-only and latency-bound, the query-based pull methods with object-centric temporal propagation (StreamPETR [8]) are currently the stronger camera-only performers, with reported nuScenes NDS in the low-60s using large backbones, versus the low-to-mid-50s for early BEVFormer configurations [4]. Treat those numbers as backbone-and-schedule dependent, not architectural constants.

Camera 3D: push / pull বিভাজন

একবার একটি monocular 3D head চালু হয়ে গেলে (Stage ১: প্রতি 2D detection-এ একটি 3D box predict করুন, translation / size / yaw-এর উপর disentangled L1 এবং একটি depth term দিয়ে supervise করুন), প্রথম আসল বিভাজন হলো camera feature কীভাবে BEV grid-এ পৌঁছায়। দুটি পরিবার:

  • Push (forward projection)। per-pixel depth distribution predict করুন, প্রতিটি pixel-কে একটি 3D frustum-এ lift করুন, এবং সেই feature-গুলো BEV voxel-এ scatter ("splat") করুন। LSS [1], BEVDet [2], ও BEVDepth [3] এই ধারার। transform-টি explicit ও geometry-বিশ্বস্ত, কিন্তু এর মান depth prediction দিয়ে সীমাবদ্ধ।
  • Pull (backward projection)। নির্দিষ্ট grid অবস্থানে BEV query বসান, প্রতিটি query-কে প্রতিটি camera-তে project করুন, এবং attention দিয়ে image feature সংগ্রহ করুন। BEVFormer [4] deformable spatial cross-attention ব্যবহার করে; PETR পরিবার [5] ও DETR3D [6] 3D position-কে key/value encoding-এ ভাঁজ করে দেয়, ফলে "grid" query-র মধ্যেই অন্তর্নিহিত। explicit depth লাগে না, কিন্তু প্রতিটি query সব view-এর উপর attention দেয়।

ব্যবহারিক পরামর্শ: LiDAR-এর সঙ্গে fuse করবেন বলে ঠিক থাকলে push দিয়ে শুরু করুন। splat-করা camera BEV feature map ঠিক একই tensor layout-এ আসে যেমন LiDAR BEV feature map, তাই Stage ৫ fusion একটা redesign নয়, বরং concatenation-plus-conv — ঠিক এই ডিজ়াইনই BEVFusion-কে "simple" করে তুলেছিল [15][16]। camera-only এবং latency-বাধ্য হলে, object-centric temporal propagation সহ query-ভিত্তিক pull পদ্ধতি (StreamPETR [8]) এখন শক্তিশালী camera-only performer, বড় backbone-এ রিপোর্ট-করা nuScenes NDS low-60s-এ, যেখানে প্রথম দিকের BEVFormer configuration low-to-mid-50s-এ [4]। এই সংখ্যাগুলোকে backbone-ও-schedule নির্ভর ধরুন, architectural ধ্রুবক নয়।

3The view transform is the crux — and the bottleneck

The push transform deserves its own section because it is where most of the compute, most of the memory, and a surprising fraction of the bugs live. Concretely: an image backbone produces a feature map F ∈ ℝH×W×C. For each pixel p the model also predicts a categorical depth distribution α(p) ∈ ℝ|D| over a set of discrete depth bins D (e.g. 1–60 m in 0.5 m steps). The lifted frustum feature at pixel p and depth bin d is the outer product

G(p, d) = αd(p) · F(p)  ∈  ℝC, (1)

so the full frustum tensor is N×|D|×H×W×C for N cameras. Each frustum cell has a known 3D position from the camera intrinsics K and the camera→ego extrinsics [R | t]; you bin those positions into the BEV grid and sum-pool the features that fall in each cell. That pooling step, done naively, materializes the giant 5D tensor and is the throughput killer. BEVPool / BEVPoolv2 [9] replaces it with a precomputed, sorted index and a custom cumulative-sum kernel, cutting the view transform from tens of milliseconds to about one, and removing the need to store G explicitly. Use it from the start; do not hand-roll voxel pooling in Python.

Depth supervision

BEVDepth's core finding [3] is that the implicitly-learned depth in vanilla LSS is poor — the network minimizes detection loss without ever getting geometry right — and that projecting LiDAR points into the image to supervise α(p) directly is worth several NDS points. If you have LiDAR at training time (you do, if you are heading for fusion), add this auxiliary loss even for the camera-only rung. Watch for the classic bug: image augmentations (resize, crop, flip) must be applied to the LiDAR-derived depth map and reflected in the intrinsics, or the supervision is spatially wrong.

BEV grid choices you are committing to

Range, resolution, and z-handling are hard to change later because the head, the losses, and the fusion module all bake in the grid. On nuScenes, a [-51.2, 51.2] m grid at 0.8 m (128×128) or 0.4 m (256×256) resolution is standard; 0.4 m roughly doubles BEV-encoder cost for a modest recall gain on small objects. Most stacks collapse height into channels (a 2D BEV map) rather than keeping a full 3D voxel grid; keep 3D only if you also want occupancy. Decide once, write it in a config, and never let it drift between the camera and LiDAR branches — a grid mismatch there produces a model that trains to a mediocre plateau with no error.

View transform-ই মূল বিষয় — এবং bottleneck

push transform-এর জন্য আলাদা section প্রাপ্য, কারণ এখানেই বেশিরভাগ compute, বেশিরভাগ memory, এবং অবাক করা পরিমাণ bug থাকে। সুনির্দিষ্টভাবে: একটি image backbone একটি feature map F ∈ ℝH×W×C তৈরি করে। প্রতিটি pixel p-এর জন্য মডেল একগুচ্ছ discrete depth bin D-এর (যেমন ১–৬০ মি, ০.৫ মি ধাপে) উপর একটি categorical depth distribution α(p) ∈ ℝ|D|-ও predict করে। pixel p ও depth bin d-তে lift-করা frustum feature হলো outer product

G(p, d) = αd(p) · F(p)  ∈  ℝC, (1)

ফলে N camera-র জন্য পূর্ণ frustum tensor হয় N×|D|×H×W×C। প্রতিটি frustum cell-এর একটি জানা 3D position আছে camera intrinsics K ও camera→ego extrinsics [R | t] থেকে; ওই position-গুলোকে BEV grid-এ bin করে প্রতিটি cell-এ পড়া feature sum-pool করুন। সেই pooling ধাপ naively করলে বিশাল 5D tensor বানিয়ে ফেলে এবং throughput-এর ঘাতক। BEVPool / BEVPoolv2 [9] এটিকে একটি precomputed, sorted index ও একটি custom cumulative-sum kernel দিয়ে বদলে দেয়, view transform-কে কয়েক দশ মিলিসেকেন্ড থেকে প্রায় এক-এ নামিয়ে আনে, এবং G-কে explicitly রাখার দরকার মিটিয়ে দেয়। শুরু থেকেই এটি ব্যবহার করুন; Python-এ হাতে voxel pooling লিখবেন না।

Depth supervision

BEVDepth-এর মূল আবিষ্কার [3] হলো vanilla LSS-এ implicitly-শেখা depth দুর্বল — network geometry ঠিক না করেই detection loss কমায় — এবং α(p)-কে সরাসরি supervise করতে image-এ LiDAR point project করা কয়েক NDS point-এর সমান মূল্যবান। training-এর সময় LiDAR থাকলে (fusion-এর দিকে গেলে থাকবেই), camera-only ধাপেও এই auxiliary loss যোগ করুন। ক্লাসিক bug-টা খেয়াল রাখুন: image augmentation (resize, crop, flip) LiDAR-derived depth map-এও প্রয়োগ করতে হবে এবং intrinsics-এ প্রতিফলিত হতে হবে, নয়তো supervision স্থানিকভাবে ভুল।

যেসব BEV grid পছন্দে আপনি আবদ্ধ হচ্ছেন

Range, resolution, ও z-handling পরে বদলানো কঠিন, কারণ head, loss, ও fusion module সবই grid-কে ভেতরে গেঁথে নেয়। nuScenes-এ [-51.2, 51.2] মি grid, 0.8 মি (128×128) বা 0.4 মি (256×256) resolution-এ, স্ট্যান্ডার্ড; 0.4 মি ছোট object-এ সামান্য recall লাভের জন্য BEV-encoder খরচ মোটামুটি দ্বিগুণ করে। বেশিরভাগ stack পূর্ণ 3D voxel grid না রেখে height-কে channel-এ মিশিয়ে দেয় (একটি 2D BEV map); occupancy-ও চাইলে তবেই 3D রাখুন। একবার ঠিক করুন, একটি config-এ লিখুন, এবং camera ও LiDAR branch-এর মধ্যে কখনো drift করতে দেবেন না — সেখানে grid mismatch এমন একটি মডেল দেয় যা কোনো error ছাড়াই একটি মাঝারি plateau-তে train করে।

4The LiDAR BEV backbone

This rung is the most standardized and the least likely to surprise you. The pipeline is: voxelize the point cloud (or pillarize it), run a sparse 3D convolutional backbone (SECOND-style [12]), flatten the last stage to BEV, run a 2D BEV encoder, and attach a center-based head (CenterPoint [13]). PointPillars [11] trades a little accuracy for a pure-2D-conv backbone that exports cleanly. VoxelNeXt [14] drops the dense BEV stage entirely for a fully sparse head, which matters for long-range grids.

Three things to get right here:

  • Sweep aggregation. nuScenes convention is to accumulate ~10 past LiDAR sweeps into the current keyframe, each transformed by relative ego pose and tagged with a time-delta channel. Get the pose chain wrong — wrong reference frame, or forgetting that sweeps and samples have different timestamps — and moving objects smear into comet tails that the network learns to ignore.
  • Class-balanced sampling (CBGS). nuScenes is dominated by cars; without CBGS [20] the rare classes (bicycle, construction vehicle) barely train. CBGS resamples the dataset to flatten the class histogram. It roughly doubles epoch length and can mildly hurt car AP, so report both with and without it.
  • GT-paste augmentation. Copy ground-truth object point clusters from other frames into the current one. Essential for LiDAR, but see the fusion section — it becomes a liability the moment cameras enter.

A CenterPoint-style LiDAR-only model on nuScenes [21] should reach roughly the mid-60s NDS on val. If yours is well below that, the bug is upstream of anything clever — check voxel ranges, sweep poses, and that the eval is using the same class map as training.

LiDAR BEV backbone

এই ধাপ সবচেয়ে standardized এবং আপনাকে অবাক করার সম্ভাবনা সবচেয়ে কম। pipeline হলো: point cloud voxelize করুন (বা pillarize করুন), একটি sparse 3D convolutional backbone চালান (SECOND-ধাঁচের [12]), শেষ stage-কে BEV-তে flatten করুন, একটি 2D BEV encoder চালান, এবং একটি center-based head লাগান (CenterPoint [13])। PointPillars [11] সামান্য accuracy ছেড়ে দিয়ে একটি pure-2D-conv backbone দেয় যা পরিষ্কারভাবে export হয়। VoxelNeXt [14] dense BEV stage পুরোপুরি বাদ দিয়ে একটি fully sparse head নেয়, যা long-range grid-এ গুরুত্বপূর্ণ।

এখানে তিনটি জিনিস ঠিক করতে হবে:

  • Sweep aggregation। nuScenes প্রথা হলো বর্তমান keyframe-এ ~১০টি অতীত LiDAR sweep জমা করা, প্রতিটি relative ego pose দিয়ে transform করা এবং একটি time-delta channel দিয়ে ট্যাগ করা। pose chain ভুল করুন — ভুল reference frame, বা sweep ও sample-এর timestamp আলাদা তা ভুলে যাওয়া — আর চলমান object ধূমকেতুর লেজের মতো ছড়িয়ে যায়, যা network উপেক্ষা করতে শেখে।
  • Class-balanced sampling (CBGS)। nuScenes-এ গাড়ির আধিপত্য; CBGS [20] ছাড়া বিরল class (bicycle, construction vehicle) কার্যত train-ই হয় না। CBGS dataset-কে resample করে class histogram সমান করে। এটি epoch দৈর্ঘ্য মোটামুটি দ্বিগুণ করে এবং car AP সামান্য কমাতে পারে, তাই সহ ও ছাড়া — দুটোই রিপোর্ট করুন।
  • GT-paste augmentation। অন্য frame থেকে ground-truth object point cluster বর্তমান frame-এ কপি করুন। LiDAR-এর জন্য অপরিহার্য, কিন্তু fusion section দেখুন — camera ঢোকার সঙ্গে সঙ্গেই এটি দায় হয়ে দাঁড়ায়।

nuScenes-এ [21] একটি CenterPoint-ধাঁচের LiDAR-only মডেলের val-এ মোটামুটি mid-60s NDS পাওয়া উচিত। আপনারটা এর অনেক নিচে হলে bug-টা যেকোনো চালাকির আগেই — voxel range, sweep pose, এবং eval training-এর মতো একই class map ব্যবহার করছে কিনা তা দেখুন।

5Fusion in BEV

With a camera BEV feature map and a LiDAR BEV feature map on the same grid, the simplest fusion — concatenate along channels, run a few conv layers, attach one shared head — already works and is essentially the MIT BEVFusion recipe [15]. Reported fusion numbers on nuScenes cluster in the low-70s NDS on the test benchmark, versus the mid-60s for the LiDAR-only baseline; the camera contribution is largest on orientation, on small or distant objects, and on classes LiDAR under-resolves. The parallel NeurIPS 2022 BEVFusion [16] emphasizes robustness: because the two streams are independent until the BEV join, the model degrades gracefully when one sensor drops out.

Beyond simple concatenation:

  • Query-level fusion. TransFusion [17] runs a LiDAR-based transformer decoder to propose boxes, then a second decoder layer that softly attends from each object query to image features. The soft association is deliberately robust to calibration error — there is no hard point-to-pixel projection that a few centimeters of extrinsic drift can break.
  • Unified tokens. CMT [18] encodes 3D position into both image and point tokens and lets object queries attend over the concatenated set, with no explicit view transform at all. Reported test NDS in the low-to-mid-70s.
  • Bidirectional interaction. DeepInteraction [19] keeps both a BEV and an image representation to the end and exchanges information between them in both directions, on the argument that flattening to BEV discards image detail that a per-view branch retains.
The multimodal GT-paste trap

LiDAR GT-paste inserts point clusters with no corresponding image pixels. Train a fusion model with naive GT-paste and the camera branch learns that "points with no image evidence are still objects" — it discounts the image. Fixes: paste consistently into both modalities (render or copy the matching image patch), or disable GT-paste for pasted instances in the camera branch, or use it only in a LiDAR pre-training phase and turn it off during joint fine-tuning. Several fusion papers quietly depend on getting this right.

BEV-তে fusion

একই grid-এ একটি camera BEV feature map ও একটি LiDAR BEV feature map থাকলে, সরলতম fusion — channel-জুড়ে concatenate, কয়েকটি conv layer, একটি shared head — এমনিতেই কাজ করে এবং মূলত MIT BEVFusion recipe [15]। nuScenes-এ রিপোর্ট-করা fusion সংখ্যা test benchmark-এ low-70s NDS-এ জড়ো, যেখানে LiDAR-only baseline mid-60s-এ; camera-র অবদান সবচেয়ে বেশি orientation-এ, ছোট বা দূরের object-এ, এবং যেসব class LiDAR ভালোভাবে resolve করে না তাতে। সমান্তরাল NeurIPS 2022 BEVFusion [16] robustness-এ জোর দেয়: যেহেতু BEV-তে মেলার আগ পর্যন্ত দুটি stream স্বাধীন, একটি sensor বাদ পড়লে মডেল gracefully দুর্বল হয়।

সরল concatenation-এর বাইরে:

  • Query-level fusion। TransFusion [17] box প্রস্তাব করতে একটি LiDAR-ভিত্তিক transformer decoder চালায়, তারপর একটি দ্বিতীয় decoder layer যা প্রতিটি object query থেকে image feature-এ softly attend করে। soft association ইচ্ছাকৃতভাবে calibration ত্রুটির প্রতি robust — কয়েক সেন্টিমিটার extrinsic drift ভাঙতে পারে এমন কোনো hard point-to-pixel projection নেই।
  • Unified token। CMT [18] image ও point দুই ধরনের token-এই 3D position encode করে এবং object query-কে concatenated set-এর উপর attend করতে দেয়, কোনো explicit view transform ছাড়াই। রিপোর্ট-করা test NDS low-to-mid-70s-এ।
  • Bidirectional interaction। DeepInteraction [19] শেষ পর্যন্ত BEV ও image দুটি representation-ই রাখে এবং দুই দিকেই তাদের মধ্যে তথ্য বিনিময় করে, এই যুক্তিতে যে BEV-তে flatten করলে এমন image detail হারায় যা একটি per-view branch ধরে রাখে।
Multimodal GT-paste ফাঁদ

LiDAR GT-paste এমন point cluster ঢোকায় যার সঙ্গে মেলানো image pixel নেই। naive GT-paste দিয়ে fusion মডেল train করুন, camera branch শেখে যে "image প্রমাণহীন point-ও object" — এটি image-কে কম গুরুত্ব দেয়। সমাধান: দুই modality-তেই সঙ্গতভাবে paste করুন (মেলানো image patch render বা copy করুন), অথবা camera branch-এ paste-করা instance-এর জন্য GT-paste নিষ্ক্রিয় করুন, অথবা কেবল একটি LiDAR pre-training পর্বে ব্যবহার করে joint fine-tuning-এ বন্ধ করে দিন। বেশ কয়েকটি fusion paper নীরবে এটা ঠিক করার উপর নির্ভর করে।

6A reference architecture blueprint

A concrete, known-good configuration to target for a nuScenes camera–LiDAR fusion baseline. Swap components once the baseline reproduces.
BlockChoiceNotes
Image backboneResNet-50 / Swin-TInput 256×704; FPN neck; init from a 2D-detection checkpoint
View transformLSS + BEVPoolv2Depth bins 1–60 m ×0.5 m; LiDAR depth supervision on
LiDAR backboneVoxelNet / SECOND sparse convVoxel 0.075 m; ~10 sweeps; range ±54 m
BEV grid±51.2 m @ 0.4 m (256²)Identical for both branches
FusionConcat + 3× conv blockUpgrade to query fusion after baseline matches
BEV encoder2× ResNet BEV blocksShared post-fusion
HeadCenterPoint (center + regression + IoU)Or transformer decoder head
TemporalDeferred to Stage 3Add BEV warp + concat of previous BEV

একটি রেফারেন্স architecture ব্লুপ্রিন্ট

একটি nuScenes camera–LiDAR fusion baseline-এর জন্য লক্ষ্য করার মতো একটি সুনির্দিষ্ট, পরিচিত-ভালো configuration। baseline reproduce হলে তবেই component বদলান।
Blockপছন্দনোট
Image backboneResNet-50 / Swin-TInput 256×704; FPN neck; একটি 2D-detection checkpoint থেকে init
View transformLSS + BEVPoolv2Depth bin 1–60 মি ×0.5 মি; LiDAR depth supervision চালু
LiDAR backboneVoxelNet / SECOND sparse convVoxel 0.075 মি; ~10 sweep; range ±54 মি
BEV grid±51.2 মি @ 0.4 মি (256²)দুই branch-এ অভিন্ন
FusionConcat + 3× conv blockbaseline মিললে query fusion-এ upgrade
BEV encoder2× ResNet BEV blockfusion-পরবর্তী shared
HeadCenterPoint (center + regression + IoU)অথবা transformer decoder head
TemporalStage 3-এ স্থগিতBEV warp + আগের BEV-র concat যোগ করুন

7Data pipeline and coordinate frames

More BEV bugs are coordinate-frame bugs than architecture bugs. Enumerate the frames explicitly and pick one canonical target:

  • Sensor frames — one per camera, one per LiDAR, each with calibrated intrinsics and a sensor→ego transform.
  • Ego frame at the sample timestamp — the usual canonical frame for the BEV grid.
  • Global frame — needed to compose sweeps and past frames via ego pose.

The nuScenes devkit distinguishes samples (annotated keyframes at 2 Hz) from sweeps (unannotated intermediate sensor data). Every sweep-to-keyframe transform is the chain Tego←sensor then Tglobal←ego(sweep) then Tego(key)←global. Write one tested utility for this chain and route every transform through it. Cross-check by projecting an accumulated point cloud back into a camera and overlaying it on the image — static structure should be pixel-tight; if it lags on moving cars only, your time handling is off; if everything is offset, your extrinsics or reference frame is off.

Also: whatever image augmentation you apply (random resize, crop, flip, rotate) must be recorded as a 3×3 transform and composed into K so the view transform stays consistent. This single omission silently caps camera-branch quality and is the most common "my BEVDet is 4 NDS low" cause.

Data pipeline ও coordinate frame

architecture bug-এর চেয়ে coordinate-frame bug-ই BEV-তে বেশি। frame-গুলো স্পষ্টভাবে তালিকাভুক্ত করুন এবং একটি canonical target বেছে নিন:

  • Sensor frame — প্রতি camera-য় একটি, প্রতি LiDAR-এ একটি, প্রতিটির calibrated intrinsics ও একটি sensor→ego transform সহ।
  • Ego frame sample timestamp-এ — BEV grid-এর জন্য সাধারণ canonical frame।
  • Global frame — ego pose দিয়ে sweep ও অতীত frame জোড়ার জন্য দরকার।

nuScenes devkit samples (২ Hz-এ annotated keyframe) আর sweeps (unannotated মধ্যবর্তী sensor data) আলাদা করে। প্রতিটি sweep-to-keyframe transform হলো চেইন Tego←sensor তারপর Tglobal←ego(sweep) তারপর Tego(key)←global। এই চেইনের জন্য একটি পরীক্ষিত utility লিখুন এবং প্রতিটি transform সেটির মধ্য দিয়ে চালান। একটি জমা-করা point cloud আবার একটি camera-তে project করে image-এর উপর overlay করে ক্রস-চেক করুন — static structure pixel-টাইট হওয়া উচিত; কেবল চলমান গাড়িতে পিছিয়ে থাকলে আপনার time handling ভুল; সব কিছু offset হলে আপনার extrinsics বা reference frame ভুল।

এছাড়া: যে image augmentation-ই প্রয়োগ করুন (random resize, crop, flip, rotate) তা একটি 3×3 transform হিসেবে রেকর্ড করে K-এর সঙ্গে compose করতে হবে যাতে view transform সঙ্গতিপূর্ণ থাকে। এই একটিমাত্র বাদ পড়া নীরবে camera-branch-এর মান সীমিত করে এবং "আমার BEVDet ৪ NDS কম" — এর সবচেয়ে সাধারণ কারণ।

8Training recipe

  • Staged, not joint from scratch. Pre-train the LiDAR branch to convergence. Add and train the camera branch + view transform with the LiDAR branch frozen or low-LR. Then unfreeze for a short joint fine-tune. Training everything jointly from random init usually underperforms and always debugs worse.
  • Augmentation, per branch. BEV-space augmentation (global rotate / scale / translate / flip) applied consistently to points, boxes, and the camera-to-BEV geometry; image-space augmentation composed into intrinsics as above; GT-paste with the multimodal caveat from §5.
  • Schedule. ~20 epochs with CBGS is a common nuScenes setting; AdamW, one-cycle LR ~2e-4, weight decay 0.01, grad clip. EMA of weights is worth ~0.5–1 NDS and is nearly free.
  • Losses. Gaussian focal loss on the center heatmap, L1 on box regression, optional IoU-aware term, plus the depth cross-entropy. Keep loss weights in the config; a mis-scaled depth loss quietly dominates or vanishes.
  • Precision and memory. FP16 everywhere except voxelization and the pooling kernel; gradient checkpointing on the image backbone; the frustum tensor is the memory spike if BEVPool is not doing its job.

Training recipe

  • Staged, scratch থেকে joint নয়। LiDAR branch-কে convergence পর্যন্ত pre-train করুন। LiDAR branch frozen বা low-LR রেখে camera branch + view transform যোগ করে train করুন। তারপর একটি সংক্ষিপ্ত joint fine-tune-এর জন্য unfreeze করুন। random init থেকে সব কিছু একসঙ্গে train করলে সাধারণত খারাপ ফল দেয় এবং সবসময় debug করা কঠিন।
  • Augmentation, branch-ভিত্তিক। BEV-space augmentation (global rotate / scale / translate / flip) point, box, এবং camera-to-BEV geometry-তে সঙ্গতভাবে প্রয়োগ; image-space augmentation উপরের মতো intrinsics-এ compose করা; §৫-এর multimodal সতর্কতা সহ GT-paste।
  • Schedule. CBGS সহ ~২০ epoch একটি সাধারণ nuScenes setting; AdamW, one-cycle LR ~2e-4, weight decay 0.01, grad clip। weight-এর EMA ~০.৫–১ NDS-এর সমান মূল্যবান এবং প্রায় বিনামূল্যে।
  • Loss. center heatmap-এ Gaussian focal loss, box regression-এ L1, ঐচ্ছিক IoU-aware term, সঙ্গে depth cross-entropy। loss weight config-এ রাখুন; ভুল-scale করা depth loss নীরবে হয় প্রাধান্য নেয় নয় মিলিয়ে যায়।
  • Precision ও memory. voxelization ও pooling kernel বাদে সর্বত্র FP16; image backbone-এ gradient checkpointing; BEVPool ঠিকমতো কাজ না করলে frustum tensor-ই memory spike।

9Deployment and the latency budget

The two components that do not export cleanly to TensorRT/ONNX are sparse convolution (custom ops, layout-sensitive, version-fragile) and voxel pooling (the BEVPool scatter/cumsum). Both have plugin implementations, but plan for a week of integration and numerical-parity checking against the PyTorch reference. Budget the pipeline roughly as: image backbone 30–45%, view transform 5–10% (with BEVPoolv2; 40%+ without), LiDAR backbone 15–25%, BEV encoder + fusion 15%, head + NMS 5–10%. If you are over budget, the image backbone and input resolution are the first knobs; halving BEV resolution is the second; the view transform is not the place to cut once BEVPoolv2 is in.

Deployment ও latency budget

যে দুটি component TensorRT/ONNX-এ পরিষ্কারভাবে export হয় না সেগুলো হলো sparse convolution (custom op, layout-সংবেদনশীল, version-ভঙ্গুর) এবং voxel pooling (BEVPool scatter/cumsum)। দুটোরই plugin implementation আছে, কিন্তু PyTorch reference-এর সঙ্গে integration ও numerical-parity যাচাইয়ের জন্য এক সপ্তাহ ধরে রাখুন। pipeline মোটামুটি এভাবে ভাগ করুন: image backbone ৩০–৪৫%, view transform ৫–১০% (BEVPoolv2 সহ; ছাড়া ৪০%+), LiDAR backbone ১৫–২৫%, BEV encoder + fusion ১৫%, head + NMS ৫–১০%। budget ছাড়িয়ে গেলে image backbone ও input resolution প্রথম knob; BEV resolution অর্ধেক করা দ্বিতীয়; BEVPoolv2 বসে গেলে view transform কাটার জায়গা নয়

10Milestones and sanity checks

Rough nuScenes val NDS you should see at each rung with a ResNet-50-class image backbone and standard schedule. Numbers are orientation, not targets — exact values depend heavily on backbone, resolution, sweeps, and TTA. See the benchmarking writeup for why.
RungModelval NDS (approx.)If far below, check
1Monocular / multi-view 3D0.37–0.42Box loss disentanglement, yaw convention
2Camera BEV, single frame0.40–0.45Intrinsics after aug, depth supervision
3Camera BEV + temporal0.47–0.55BEV warp direction, velocity sign
4LiDAR-only (CenterPoint-class)0.64–0.67Sweep poses, voxel range, CBGS class map
5Camera–LiDAR fusion (concat)0.69–0.72Grid match, multimodal GT-paste

Sanity checks that catch most silent failures: (a) overfit a single scene to near-zero loss before any full run; (b) confirm the eval class map equals the train class map; (c) visualize predictions in BEV and reprojected into the image; (d) drop each modality at inference and confirm the score changes in the expected direction and magnitude — if removing the camera barely moves the score, the camera branch is dead weight and something in §3 or §5 is wrong.

১০মাইলফলক ও sanity check

একটি ResNet-50-শ্রেণির image backbone ও স্ট্যান্ডার্ড schedule দিয়ে প্রতিটি ধাপে যে আনুমানিক nuScenes val NDS দেখা উচিত। সংখ্যাগুলো দিকনির্দেশ, target নয় — সঠিক মান অনেকটাই backbone, resolution, sweep, ও TTA-র উপর নির্ভর করে। কেন — benchmarking রাইটআপ দেখুন।
ধাপমডেলval NDS (আনু.)অনেক নিচে হলে দেখুন
Monocular / multi-view 3D0.37–0.42Box loss disentanglement, yaw convention
Camera BEV, single frame0.40–0.45aug-পরবর্তী intrinsics, depth supervision
Camera BEV + temporal0.47–0.55BEV warp দিক, velocity চিহ্ন
LiDAR-only (CenterPoint-শ্রেণি)0.64–0.67Sweep pose, voxel range, CBGS class map
Camera–LiDAR fusion (concat)0.69–0.72Grid match, multimodal GT-paste

বেশিরভাগ নীরব failure ধরার sanity check: (ক) যেকোনো পূর্ণ run-এর আগে একটি single scene-কে near-zero loss পর্যন্ত overfit করুন; (খ) eval class map train class map-এর সমান কিনা নিশ্চিত করুন; (গ) prediction BEV-তে এবং image-এ reproject করে visualize করুন; (ঘ) inference-এ প্রতিটি modality বাদ দিন এবং score প্রত্যাশিত দিক ও মাত্রায় বদলায় কিনা নিশ্চিত করুন — camera সরালে score প্রায় না নড়লে camera branch অকেজো ভার এবং §৩ বা §৫-এ কিছু ভুল।

11The recurring bugs, in one list

  • Image augmentation not composed into the camera intrinsics → camera branch permanently ~3–5 NDS low.
  • BEV grid range/resolution mismatched between camera and LiDAR branches → trains to a plateau, no error.
  • Sweep-to-keyframe pose chain wrong → moving objects smear; velocity estimates biased.
  • Yaw convention mismatch (x-forward vs y-forward, CW vs CCW) between head, loss, and eval → orientation error near 90° on half the classes.
  • Naive multimodal GT-paste → camera branch under-weighted; fusion barely beats LiDAR-only.
  • CBGS applied in training but eval done on the resampled set → inflated, non-comparable score.
  • Depth-supervision target not augmented alongside the image → depth head learns a warped mapping.
  • Val leakage via scene overlap when making a custom split → everything looks great until the test server.

১১বারবার আসা bug, এক তালিকায়

  • Image augmentation camera intrinsics-এ compose না করা → camera branch স্থায়ীভাবে ~৩–৫ NDS কম।
  • camera ও LiDAR branch-এর মধ্যে BEV grid range/resolution অমিল → plateau-তে train করে, কোনো error নেই।
  • Sweep-to-keyframe pose chain ভুল → চলমান object ছড়ায়; velocity estimate biased।
  • head, loss, ও eval-এর মধ্যে yaw convention অমিল (x-forward বনাম y-forward, CW বনাম CCW) → অর্ধেক class-এ ~90° orientation error।
  • Naive multimodal GT-paste → camera branch under-weighted; fusion কোনোমতে LiDAR-only-কে হারায়।
  • CBGS training-এ প্রয়োগ কিন্তু eval resampled set-এ → স্ফীত, অতুলনীয় score।
  • Depth-supervision target image-এর সঙ্গে augment না করা → depth head একটি বিকৃত mapping শেখে।
  • custom split বানানোর সময় scene overlap-এর মাধ্যমে val leakage → test server-এ যাওয়ার আগ পর্যন্ত সব দারুণ দেখায়।

Key takeaways

  • Build the ladder in order. Each rung is a checkpoint with a literature baseline; skipping straight to fusion removes your ability to localize faults.
  • If fusion is the goal, use a push (Lift-Splat) camera transform so the camera BEV map matches the LiDAR BEV map and fusion is concatenation, not redesign.
  • The view transform is the compute and bug hotspot: use BEVPoolv2, supervise depth from LiDAR, and compose image augmentations into the intrinsics.
  • Coordinate frames and multimodal GT-paste cause more lost weeks than architecture. Write one tested transform utility; handle GT-paste explicitly.
  • Treat published NDS figures as backbone- and schedule-dependent ranges, not constants.

মূল কথা

  • সিঁড়িটা ক্রমানুসারে গড়ুন। প্রতিটি ধাপ একটি literature baseline সহ checkpoint; সরাসরি fusion-এ লাফালে ত্রুটি আলাদা করার ক্ষমতা হারান।
  • fusion-ই লক্ষ্য হলে একটি push (Lift-Splat) camera transform ব্যবহার করুন যাতে camera BEV map, LiDAR BEV map-এর সঙ্গে মেলে এবং fusion হয় concatenation, redesign নয়।
  • View transform-ই compute ও bug-এর কেন্দ্র: BEVPoolv2 ব্যবহার করুন, LiDAR থেকে depth supervise করুন, এবং image augmentation intrinsics-এ compose করুন।
  • architecture-এর চেয়ে coordinate frame ও multimodal GT-paste বেশি সপ্তাহ নষ্ট করে। একটি পরীক্ষিত transform utility লিখুন; GT-paste স্পষ্টভাবে সামলান।
  • প্রকাশিত NDS সংখ্যাকে backbone- ও schedule-নির্ভর পরিসর ধরুন, ধ্রুবক নয়।

Referencesতথ্যসূত্র

  1. Philion, J., Fidler, S. “Lift, Splat, Shoot: Encoding Images from Arbitrary Camera Rigs by Implicitly Unprojecting to 3D.” ECCV 2020. arXiv:2008.05711
  2. Huang, J. et al. “BEVDet: High-performance Multi-camera 3D Object Detection in Bird-Eye-View.” arXiv 2021. arXiv:2112.11790
  3. Li, Y. et al. “BEVDepth: Acquisition of Reliable Depth for Multi-view 3D Object Detection.” AAAI 2023. arXiv:2206.10092
  4. Li, Z. et al. “BEVFormer: Learning Bird's-Eye-View Representation from Multi-Camera Images via Spatiotemporal Transformers.” ECCV 2022. arXiv:2203.17270
  5. Liu, Y. et al. “PETR: Position Embedding Transformation for Multi-View 3D Object Detection.” ECCV 2022. “PETRv2,” ICCV 2023. arXiv:2203.05625
  6. Wang, Y. et al. “DETR3D: 3D Object Detection from Multi-view Images via 3D-to-2D Queries.” CoRL 2021. arXiv:2110.06922
  7. Park, J. et al. “Time Will Tell: New Outlooks and A Baseline for Temporal Multi-View 3D Object Detection (SOLOFusion).” ICLR 2023. arXiv:2210.02443
  8. Wang, S. et al. “Exploring Object-Centric Temporal Modeling for Efficient Multi-View 3D Object Detection (StreamPETR).” ICCV 2023. arXiv:2303.11926
  9. Huang, J., Huang, G. “BEVPoolv2: A Cutting-edge Implementation of BEVDet Toward Deployment.” arXiv 2022. arXiv:2211.17111
  10. Wang, T. et al. “FCOS3D: Fully Convolutional One-Stage Monocular 3D Object Detection.” ICCV 2021 Workshops. arXiv:2104.10956
  11. Lang, A. et al. “PointPillars: Fast Encoders for Object Detection from Point Clouds.” CVPR 2019. arXiv:1812.05784
  12. Yan, Y. et al. “SECOND: Sparsely Embedded Convolutional Detection.” Sensors 2018.
  13. Yin, T. et al. “Center-based 3D Object Detection and Tracking (CenterPoint).” CVPR 2021. arXiv:2006.11275
  14. Chen, Y. et al. “VoxelNeXt: Fully Sparse VoxelNet for 3D Object Detection and Tracking.” CVPR 2023. arXiv:2303.11301
  15. Liu, Z. et al. “BEVFusion: Multi-Task Multi-Sensor Fusion with Unified Bird's-Eye View Representation.” ICRA 2023. arXiv:2205.13542
  16. Liang, T. et al. “BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework.” NeurIPS 2022. arXiv:2205.13790
  17. Bai, X. et al. “TransFusion: Robust LiDAR-Camera Fusion for 3D Object Detection with Transformers.” CVPR 2022. arXiv:2203.11496
  18. Yan, J. et al. “Cross Modal Transformer: Towards Fast and Robust 3D Object Detection.” ICCV 2023. arXiv:2301.01283
  19. Yang, Z. et al. “DeepInteraction: 3D Object Detection via Modality Interaction.” NeurIPS 2022. arXiv:2208.11112
  20. Zhu, B. et al. “Class-balanced Grouping and Sampling for Point Cloud 3D Object Detection (CBGS).” arXiv 2019. arXiv:1908.09492
  21. Caesar, H. et al. “nuScenes: A Multimodal Dataset for Autonomous Driving.” CVPR 2020. arXiv:1903.11027
  22. Hu, Y. et al. “Planning-oriented Autonomous Driving (UniAD).” CVPR 2023. arXiv:2212.10156