Inspiration
A radiologist reading a CT angiogram has to find every artery leaving the aorta by hand, slice by slice, and the ones that matter most, a 2 mm renal accessory, a lumbar branch near a graft landing zone, are one or two voxels across. Miss one before an endovascular repair and you occlude a kidney. The obvious answer is a deep network, but the brief said CPU-only, 4 cores, no GPU, no internet, 60 seconds a case. That constraint is the interesting part: it forces you to actually understand the geometry of a branch instead of asking a model to memorise what one looks like.
What it does
Given a CT volume and a binary abdominal-aorta mask, Branchseed finds every eligible artery leaving that aorta and returns, for each one: the ostium in physical LPS millimetres, a seed point 5 mm down the daughter, the lumen radius, and a unit direction vector. Then it hands the result to a human...a browser viewer with linked axial/coronal/sagittal planes and a 3D volume render, where clicking a branch drives the crosshair to its origin in all three planes, and holding H strips the overlay off so you can check the raw CT underneath.
No trained model, no GPU, no network at runtime, no per-case tuning. 0.5–5.3 seconds per case on one core against a 60-second budget.
How we built it
Eight stages, all classical CV:
- Crop to the aorta plus a 30 mm margin — 98% of the volume is irrelevant.
- Per-case intensity model. Lumen HU spans 252–580 across the dataset, so every threshold is derived from the mask's own interior rather than hardcoded. We use the 85th percentile, not the median: an aneurysm with mural thrombus drags the median into soft tissue.
- Geometry and end caps. The mask's own first and last slices are dead zones — a cropped end face looks exactly like a giant ostium.
- Candidates. Threshold a 6 mm collar just outside the mask, keep components touching the wall. A data-driven rind exclusion removes the partial-volume shell hugging the aortic wall.
- Split fused ostia. Two origins 5 mm apart merge into one component at 1.5 mm voxels, because the haloes touch before the lumens do. We raise the threshold inside each component until distinct bright cores appear, then split.
- Geodesic growth with
MCP_Geometric, spacing-aware, capped at 22 mm — which doubles as a firebreak against leaks into kidney parenchyma. - The tri-planar signature. At the seed, measure the 2D connected component's equivalent diameter in each of the three orthogonal planes. Two large + one small = a tube. Three small = a blob. Three large = an organ leak. It's a discrete, cheap stand-in for Hessian eigenvalue analysis.
- Ostium placement by wall foot-point centroid: every background voxel already knows its nearest aorta voxel from the distance transform's index map, so the branch's proximal collar maps directly onto the patch of wall it emerges from.
Scoring uses Hungarian bipartite matching, same as the brief's one-to-one rule.
Challenges we ran into
Our first idea was exactly backwards. We designed the tri-planar test as a consensus rule: accept a candidate only if all three views agree it's a vessel. We built a phantom to check, and it kept 38% of calcified plaque while rejecting 90% of real branches. Of course it did — a tube looks completely different in its three orthogonal planes, and demanding agreement selects for spheres. The rule had to be the pattern, not the agreement.
A metric we trusted was measuring nothing. We were using elongation (reach ÷ min caliber) as our best shape discriminator until we looked at the distribution: 80% of detections saturate the 22 mm growth cap, so elongation was just 22/d_min with 1.9% error. It was a caliber test wearing a disguise. Replaced with a volume-based leak ratio.
A bright rind that ate an entire aorta. One fixed parameter tuned on the eval set was smaller than one voxel on the 0.78 mm training scans. The partial-volume shell survived, fused the whole aortic wall into a single connected component, and produced one candidate with a 70 mm "ostium" that swallowed every real branch — three subjects returned zero detections. No metric caught it; a teammate caught it by eye. Now the rind is measured per case from that shell's actual brightness.
Silent recall loss. Four reference branches were being detected and then discarded with no filter ever reporting it, because two ostia within 5 mm shared one collar component. Finding that required instrumenting every rejection and matching it back against the reference — the fix took recall from 0.789 to 0.895.
Plus: subjects 16–25 shipped as gzip files named .nii, subject 24 had non-orthonormal direction cosines, and numpy indexes (z,y,x) while SimpleITK indexes (x,y,z).
Accomplishments that we're proud of
- F1 0.739, 17 of 19 reference daughters recovered, median ostium error 1.23 mm, composite 0.6151 on the published rubric.
- 1.23 mm median localisation on 1.5 mm voxels — sub-voxel, from a distance-transform foot-point construction rather than a regression head.
- Every parameter is either derived per case or held fixed across all 25 subjects and 5 eval cases. No leaderboard tuning.
- We built a synthetic phantom with 15 known daughters before touching real data, which is the only reason we caught the consensus bug instead of shipping it.
- We can tell you why our count differs from the reference: the draft annotations cover 10–45% of each supplied aorta, every unmatched detection is ≥12.6 mm from the nearest reference ostium, and all 19 reference branches are stamped
expert_review_pending. Not one unmatched detection is a mislocated true branch.
What we learned
Test on something where you know the answer. Our phantom killed two confident, wrong ideas in an afternoon.
When a metric looks too good, plot its distribution before you trust it. Both times we were fooled, the evidence was one histogram away.
Voxel size is not a nuisance parameter. Nearly every regression we hit came from a threshold calibrated at 0.78 mm meeting a 1.5 mm grid, where a 2 mm vessel is 1.3 voxels across and discrete shape statistics collapse toward 1.
And: a score is not a result until you understand its error bars. Chasing an exact count match against a reference explicitly marked "not certified exhaustive" would have made the detector worse at the actual clinical task.
What's next for pizzaDemolishers
Ask the organisers the question that decides everything: does the scored reference cover the whole supplied aortic segment, or only the reviewed window? That single answer determines whether to push precision or recall, and it's worth more than any parameter we could still tune.
Beyond that: a proper centreline (the geodesic path cuts corners near the wall, which is most of our remaining direction error), vessel naming against an anatomical atlas so the viewer says "left renal" instead of "branch_003", and a one-click reader loop — a clinician confirms or rejects each origin in the viewer, and those marks become the reference the next version is measured against.
Log in or sign up for Devpost to join the conversation.