Scan a foot with an ordinary phone camera and generate a 3D-printable, flexible-TPU orthotic insole that sits between the foot and the shoe.
Two flavors, one shared geometry core (proven bit-for-bit identical):
- Desktop (this folder, Python) — accuracy king: photogrammetry (COLMAP) for the most accurate surface when a PC is available.
- Mobile (
mobile/, an installable PWA) — reach king: fully offline, on-device, no app store, no server — just a web link. Same insole math as desktop. Built for low-resource settings where a clinician or a laptop is hard to reach.
Parity is enforced by a test: python tools/parity_reference.py and
node mobile/test/parity.mjs produce the same mesh (same faces, same volume).
phone photos ──► COLMAP mesh ──► scale & orient ──► clean ──► orthotic ──► insole.stl
(30–60 shots) (reconstruct) (real mm, sole down) (total-contact) (print in TPU)
- Total-contact insole — spreads load over the whole plantar surface.
- Arch fill, heel cup (side cradle), heel lift (therapeutic raise).
- Relief wells — tap-to-place offload pockets for prominences / ulcers.
- Pressure-point smoothing — no sharp ridges on a foot that can't feel them.
- Real-time 3D preview + top-down pressure map (mobile).
- Clinical presets, left/right foot, shoe-size readout, STL + spec-sheet export.
- Flexible-TPU-ready output with a print profile.
python -m http.server 8740 --directory mobile # then open http://localhost:8740
# Tap a preset → drag the 3D view → switch to the map and tap to add a relief
# well → Download insole.stl.Run the whole test suite with python tools/run_tests.py.
The orthotic is a total-contact insole: its bottom is a flat plate on the shoe footbed and its top conforms to the underside of the foot, so weight is spread over the whole sole instead of a few bony points. It adds an arch fill, a heel cup, optional relief wells to offload a prominence/ulcer, and smooths the top so there are no sharp pressure ridges.
This tool was built with Charcot foot (Charcot neuro-osteoarthropathy) in mind, but that case is exactly where you must be most careful:
- People with Charcot foot almost always have neuropathy — they cannot feel a bad pressure point. A poorly-offloaded insole can cause a pressure ulcer that the wearer never feels until it is infected, and that can end in amputation.
- A do-it-yourself scan does not know where the bones, ulcers, or at-risk prominences are. The geometry here is only as good as the information you give it (notably the relief-well locations).
- During an active/acute Charcot episode, offloading is usually total non-weight-bearing or a clinical CROW boot / TCC — not a printed insole.
Use this as a digitiser and prototyping tool, and have any orthotic intended for a neuropathic or Charcot foot reviewed and fitted by a podiatrist or orthotist before it is worn. Relief-well placement should come from a clinician or a plantar-pressure map, not a guess. This software is not a medical device and makes no clinical claims.
python -m pip install -r requirements.txt
# For the photo->mesh step only:
winget install COLMAP.COLMAP # or https://github.com/colmap/colmap/releasesPure-Python mesh stack — no open3d/pymeshlab, works on Python 3.14.
python -m footscan.cli demo --out out --relief 70,95,20,7
python tools/preview.py out/insole.stl out/preview.pngBuilds a synthetic foot, generates out/insole.stl, and renders a thickness map
- cross-sections so you can see the arch support, heel cup, and relief pocket.
No depth sensor, no COLMAP — works on a $40 phone. Recovers the foot's true outline and size in millimetres; the arch/heel contour is a parametric model fitted to that outline (an honest baseline — for a deformed Charcot foot prefer the depth or photogrammetry path, which measure the real contour).
python -m footscan.cli make-card --out out/scale_card.png # print at 100% scale
# Place the bare foot inside the border, photograph from straight above, then:
python -m footscan.cli photo --image foot.jpg --side right --out outFour ArUco corner markers let it rectify camera tilt and lock real mm scale.
Verified end-to-end by tools/test_photo_capture.py (recovers a known foot's
size from a perspective-warped photo to within ~1%).
1. Photograph the foot. Best results:
- Sit with the foot resting (or lightly bearing weight) on a flat, matte, patterned surface (a towel works; blank/shiny floors confuse photogrammetry).
- Take 30–60 photos in a slow arc around the foot — low, medium, and high angles — keeping ~70% overlap between consecutive shots. Get the sides, the back of the heel, and over the toes. Hold still; good light; no flash.
- Keep the foot still the whole time (a stack of books to rest it on helps).
2. Reconstruct a mesh:
python -m footscan.cli reconstruct --photos .\photos --workspace .\ws --out out\foot_raw.ply3. Generate the insole (scale comes from your measured foot length — measure heel-to-longest-toe with a ruler):
python -m footscan.cli insole --mesh out\foot_raw.ply --foot-length-mm 262 --out out4. Place a relief well (optional, for offloading). First find local coords, then add one or more:
python -m footscan.cli grid --mesh out\foot_raw.ply --foot-length-mm 262
python -m footscan.cli insole --mesh out\foot_raw.ply --foot-length-mm 262 `
--relief 70,95,20,7 --relief 30,60,16,5 --out out--relief x,y,radius,depth (mm), origin at the footprint's min corner, +y = heel→toe.
5. Print out/insole.stl in TPU — see print_profiles/tpu_insole.md.
| Flag | Default | Effect |
|---|---|---|
--foot-length-mm |
— | real measurement that sets scale (required for scans) |
--base-thickness |
4.0 | cushion under the contact points (mm) |
--heel-cup |
12.0 | heel side rim that cradles the heel (mm) |
--heel-lift |
0.0 | therapeutic heel raise — lifts the calcaneus, tapering forward (mm) |
--heel-lift-runout |
80.0 | distance over which the heel lift tapers to 0 (mm) |
--max-arch-fill |
22.0 | clamp on arch support height (mm) |
--smooth |
4.0 | gaussian smoothing of the top (mm); higher = gentler |
--relief x,y,r,d |
— | offload pocket; repeatable |
--no-clean |
off | skip mesh cleaning if the input is already clean |
- Heel cup (
--heel-cup) is a side rim that hugs the heel laterally. - Heel lift (
--heel-lift) actually raises the heel — it adds height under the calcaneus and tapers forward over--heel-lift-runout. Use it for Achilles / equinus tightness or a leg-length discrepancy (both common in diabetic feet).
The lift is measured-independent (a prescribed amount you dial in) and is deliberately uncapped, so an extreme raise is possible. Caveats for big lifts:
- A tall lift turns the insole into a wedge that may not fit a normal shoe — it often belongs in accommodative/extra-depth footwear or a CROW boot.
- A heel raise meaningfully changes gait and forefoot loading; on a neuropathic / Charcot foot the amount should be clinician-set, and a leg-length lift should account for both feet (only one side is usually raised).
- For print stability, very tall lifts want a longer
--heel-lift-runout(gentler ramp) and more infill — see the print profile.
footscan/
reconstruct.py photos -> mesh via COLMAP (subprocess wrapper)
scale_align.py orient sole-down + scale to real mm from foot length
clean_mesh.py largest component, fill holes, Taubin smooth
meshbuild.py heightmap -> watertight solid (shared primitive)
orthotic.py *** total-contact insole generator (arch/heel/relief) ***
demo_foot.py synthetic foot so the pipeline runs with no scan
cli.py command-line entry point
tools/preview.py thickness-map + cross-section renders for sanity checks
print_profiles/ TPU slicer guidance
orthotic.py casts rays upward to sample the foot's underside as a height
field U(x,y). Then:
- top(x,y) = base_thickness + arch_fill + heel_cup − relief_wells, where
arch_fillis how far the foot lifts above its lowest contact point (so the insole grows to meet and support the arch), - bottom(x,y) = 0 (flat plate on the shoe footbed),
- the top is gaussian-smoothed (no sharp pressure ridges — vital on a foot that
can't feel them), then
meshbuild.heightmap_to_solidstitches a watertight solid (top + bottom + silhouette walls).
- ArUco scale-board auto-scaling (cv2 helper stubbed in
requirements.txt). - Import a plantar pressure map (force-plate / pressure-mat image) to place relief wells automatically instead of by hand.
- Dual-durometer export (soft top zone over a firmer base) for printers/slicers that support modifier meshes.
- Toe-spring / met-bar parameters; left/right mirroring from a single scan.