DEV Community

Matthew Armstrong
Matthew Armstrong

Posted on Edited on

Scantastic

WORK IN PROGRESS: MANY FEATURES MAY BE BROKEN.
Version 0.11.0-wip. Source-available and free for non-commercial use
(PolyForm Noncommercial 1.0.0). No warranty.

Scantastic (until 0.7.0 called RealSense 3D Scanner) is a desktop app that turns an
Intel RealSense depth camera into a tabletop 3D scanner: live preview → scan while you turn the object → build a mesh → save
.stl / .obj / .ply. It can also record the raw camera streams and clean them
up in several passes before the mesh is built.

Works with the SR305 / SR300 (coded light) and D400-series cameras such as
the D415 inside the Prowise MOVE 3in1. The camera is detected automatically.
A Kinect v1 or v2 can be used too, as an experimental option that has not been
tried on real hardware yet (KINECT.md).
It is designed for modest hardware (a 7th-gen i3 with no GPU is the target);
everything has a CPU path.

Main window

What has actually been tested

Being straight about this, because it is a work in progress:

Area Status
Whole app on a real camera 0.2.0 has been run on real hardware (i5 U-series laptop, 8 GB). It scans and runs light, but the scans lack definition. 0.5.1 has been run on a D415 (sensor check and a face scan). The rest of 0.2.1 to 0.11.0 has not been run on a camera yet.
Stream clean-up pipeline (stream_pipeline.py) Unit-tested on synthetic scenes (8 tests, run in CI). Not yet tried on real footage.
Sensor check breakdown and surface-detail options (new in 0.2.1) Unit-tested on synthetic walls and scans (17 tests with the 3D-view ones; they need Open3D, so CI skips them). Not yet tried on a real camera.
3D view colours, backgrounds, remembered settings, cancelling a build (0.2.2, merged from an older fork) Exercised headless on synthetic scans, plus 4 unit tests. Not yet tried on a real camera.
Kinect v1 / v2 (new in 0.3.0, optional modules) Untested on real hardware and against real drivers. 25 unit tests with stand-in drivers and a headless run of the app with a stand-in Kinect.
Retro TV look (new in 0.3.0, optional module) Exercised headless on Linux, plus 5 unit tests. Not checked on Windows or macOS. --plain switches it off.
Cutting on the model (new in 0.4.0) 25 unit tests on made-up shapes, and a headless run of the app that draws, drags, applies and undoes cuts on a noisy made-up scan of a ball on a table. Not yet tried on a real scan, or by a real hand on a real mouse.
Double-click launchers (new in 0.4.1) The Linux launcher: 9 tests with a stand-in Python, and started for real under a headless display. The Windows launcher has not been run on Windows. The Mac launcher was run by the owner on an M5 Mac with 0.9.0: set-up ran, then Open3D 0.20 failed to load (Homebrew libusb). Fixed in 0.9.1, which is not yet tried on a Mac.
Live picture by itself, camera on/off, Rotate (new in 0.5.0) 13 tests, 6 of them running the whole window with a stand-in camera and a stand-in "what is plugged in" answer (plugging in, turning off and on, turning off while starting, unplugging, a camera that will not start, turning the picture). Not yet tried with a real camera being plugged in and out.
D400 settings (0.5.1, 0.5.2) 18 tests with a stand-in RealSense driver. 0.5.1 tried on a real D415: much better than 0.5.0, still soft. 0.5.2 not yet tried.
Handheld and turntable stitching, picture features, marker ring, scan target (new in 0.9.0) Measured on made-up scans with known answers: turntable 0 of 40 failed, typical worst frame 0.6 mm; handheld 0 of 20 held-out and 3 of 20 tuning scans failed (0.8.1 failed every one). 21 tests. Not yet tried on a real camera, a real turntable, a printed ring or a printed target. See the results.
Live tracking, scan styles, record-now-stitch-later, captures off the camera thread (new in 0.10.0) Made-up video-rate scans: live tracking 0 of 20 failed (tuning and held-out); record-now-stitch-later 2 of 20 held-out scans had one stray frame 6–8 mm out (of about 50 kept); the rest had a typical worst frame of 0.9 mm. 18 tests, including end-to-end window runs with a stand-in camera. Not yet tried on a real camera or a real 7th-gen i3. See the write-up.
Speed profiles, alignments side by side, graphics card (new in 0.11.0) Held-out made-up handheld scans: the same answer as 0.10.0 on all 20 (1 of 20 fails, as 0.10.0 does when run again; its earlier "0 of 20" was not from its final code). The graphics-card method, run on the processor: also 1 of 20, worst frames within 0.04 mm. Final polish about a quarter quicker; side by side only about 10% quicker on the 2-core test machine. 23 tests. No real graphics card, no PC with more than 2 cores, and Windows and macOS not tried. See the write-up.
SR305 unchanged by the D400 work (0.8.1) Compared with 0.5.0 on the same inputs: camera set-up, window settings and mesh match, the last within run-to-run noise. 3 tests keep it so.
Ready-made Intel driver, private Python 3.11, driver reuse (new in 0.8.0) A real first run from nothing, here, with only Python 3.12 on the path: Python 3.11 downloaded, Intel's driver installed and hash-checked, app started. The suite passes on that Python (Tk 9). Not yet tried with a camera plugged in, or on your laptop.
Advanced-mode switch, firmware note, review fixes (new in 0.7.1) 20 tests with stand-in drivers, cameras and meshes. The advanced-mode switch matches librealsense 2.54.2's source, but has not been tried on a real D415.
Magenta mask overlay, no-depth-only mask, fill small holes (new in 0.6.1) 10 tests on made-up walls, a stand-in camera and a synthetic mesh with holes. Not yet tried on a real camera.
Settings per camera, Reset, camera badge (new in 0.6.0) 8 tests, 4 running the whole window with stand-in cameras that are swapped. Not yet tried with two real cameras.
Optional ErrCode hook (new in 0.4.1) Tried with stand-ins only, not with the real plugin.
Laser power option (new in 0.2.1) Checked against a fake sensor only. What value 1 does on SR305 firmware is unconfirmed.
Recording infrared; opening .bag files; the optional AI mask; the GitHub workflows Untested with real data.

All screenshots here come from synthetic test data, not a real object. The Kinect one
uses a stand-in driver, not a real Kinect.
If something breaks on your camera, please open an issue.

Kinect (0.3.0, experimental)

The app showing a stand-in Kinect

Camera type at the top of the Camera panel switches between RealSense and Kinect.
Kinect support is untested on real hardware, its drivers have to be installed by hand, and
the sensor check, depth confidence and laser settings do not apply to it. The Kinect runs
in its own process, so a driver crash cannot close the app; it is restarted automatically
if it crashes, hangs or stops sending pictures.
Everything is in KINECT.md.

The look (0.3.0)

The window is dressed as a wood-panelled television: walnut cabinet, black bezel, a
rounded screen, and static on the screen while the camera is off. The static stops the
moment the first camera picture arrives, and a lamp under the screen shows whether the
camera is on standby or live.

Everything is drawn by the app; there are no picture files. The static is a few pictures
made once and swapped on a timer. In a headless test the whole app used about 4% of one
processor core while showing it.

Look (bottom of the right-hand panel) chooses Retro TV, Retro TV, still screen (no
movement) or Plain. It applies the next time the app starts. --plain on the command
line forces the plain look, and the app falls back to it by itself if the skin fails.

Plain look

Using it

  1. Plug the camera in. The live picture appears by itself (the app looks for a camera every few seconds while the live view is showing). Point it at the subject; the live distance guide shows the sweet spot.
  2. START SCAN (green). In Handheld mode, move the camera slowly round the object; in Turntable mode, keep the camera still and turn the object (below). STOP when done. Capture Frame takes single frames instead.
  3. BUILD MESH. Choose Smooth surface (fuses depth images, recommended) or Watertight (Poisson; fills unscanned gaps so it can be printed). While it builds, the same button turns into CANCEL.
  4. Save mesh… as STL/OBJ/PLY, in millimetres or metres.

Other controls: near/far range, depth confidence, laser power, average-when-still,
keep-only-the-subject, a CAD-style view cube, and cutting (next section) to remove
the table or split overlapping scans. While scanning, the STOP
button shows the elapsed time and the number of frames. Clear captured frames
asks first if it would throw away a mesh you have not saved.

Handheld or turntable (new in 0.9.0)

Pick the Scan mode in the Scan panel. Frames are cut out differently in each mode, so
changing it clears the frames captured so far (it asks first).

Mode You move Best for
Handheld the camera, slowly round the object big or fixed things, faces
Turntable the object, on a turntable or lazy Susan, a little between captures. The camera stays on a stand and must not move. small objects; the most reliable

Turntable mode in four steps:

  1. Put the camera on a stand, 30–50 cm from the turntable, looking down at it a little.
  2. Optional, but best: with nothing on the turntable, press Record empty turntable. Everything that is there now (table, wall, the turntable itself) is left out of the scan. Without it, the table and the turntable's top are found and removed instead.
  3. For a plain or round object (a mug, a smooth figure, anything with little pattern), press Save marker ring to print (PDF). Print it at 100% (the 50 mm bar must measure 50 mm), lay it flat on the turntable and put the object in the middle. The markers say exactly how far the turntable turned.
  4. START SCAN and turn the object slowly through a full turn, or Capture Frame every 10–20 degrees.

How it lines frames up: every frame is a turn about the same axis, so instead of six
unknowns per frame there is one. A step that doesn't fit the axis is re-checked. A full
turn is checked against the start, and the axis and every turn are then fine-tuned
together against all the frames that see the same side. The build report says what it
found, for example "Turntable: one axis fits the steps (0.4 mm typical); 24 frames over
345 degrees; full-turn check from 1 closure(s)". If the steps don't fit one axis (the
object slid, or the camera was knocked) it says so and aligns as a handheld scan instead.

Picture features (tick box, on by default): every step between frames is also worked
out from the colour picture, using ORB corners on a greyscale copy, lifted to 3D with the
depth. A shape match that the picture clearly contradicts is overruled. This is what stops
a round object being glued on at the wrong turn. Untick it to compare.

Slow PCs, live tracking, and what to expect (new in 0.10.0)

The Scan style box (Scan panel) chooses when the heavy work happens.

Scan style While you scan After STOP For
Stitch while scanning Every capture is lined up as it comes. Handheld, the camera is also followed on the live picture (up to 10 frames a second), and a red banner says TRACKING LOST - move back slowly if it loses its way. Build Mesh a reasonably quick PC
Record now, stitch afterwards Only the camera's frames are saved to disk (about 10 a second), which even a slow PC keeps up with. Stitching starts by itself and shows how long is left. Then Build Mesh. slower PCs, such as a 7th-gen Core i3

The first time it starts, the app times one tracking step on your PC (about a third of
a second). With 4 processor threads or fewer, or a slow step, it picks Record now,
stitch afterwards
. You can change it at any time when not scanning.

On a 7th-gen i3, be ready for slow. It won't freeze or crash, but it takes a while.

  • Stitching runs as a separate program with a memory limit. If it runs out of memory, only that program stops, and it starts again on every 2nd frame (twice at most). The recording stays safe on disk whatever happens. A recording cut short by a crash keeps all but its last few frames.
  • Expect minutes, not seconds. On a 2-core test machine, about as fast as a 7th-gen i3, a 40-second handheld recording (about 120 frames) took about half a minute to clean and track. Then lining up the 48 frames it kept took 2–4 minutes, and Build Mesh takes longer again. A turntable scan is much quicker to line up. These are measured on made-up scans, not timed on a real i3.
  • While stitching, the status bar shows the progress and the minutes left. You can leave it running.

Whichever style you choose, captures are now worked out away from the camera's own
thread. If the PC falls behind, a capture is skipped with a message rather than freezing
the live picture.

Speed profiles and the graphics card (new in 0.11.0)

The Speed and graphics card box (right-hand panel) is taken from STL2STEP. It sets how
hard Build Mesh and stitching work the computer.

Profile Alignments at once Priority Graphics card Auto picks it for
Potato 1 lowest: the PC stays usable no under 4 cores or 12 GB, such as a 7th-gen i3
Moderate half the cores below normal no most laptops
Extreme every core normal yes, where it passed its test 8+ cores and 16 GB

Speed and graphics card box

Be realistic about what it gains.

  • Lining the frames up is over 90% of Build Mesh, and that is Open3D's ICP alignment.
  • On a 7th-gen i3, Potato makes nothing faster. It keeps the computer usable while it works.
  • Alignments side by side give the same results. On the 2-core test machine they were only about 10% faster; a PC with more cores should gain more, but that hasn't been measured.
  • The final polish is now about a quarter quicker, with the same results.

Graphics cards:

  • Nvidia on Linux: the standard Open3D already contains Nvidia (CUDA) support, so nothing extra is installed. Press Test the card; the card is only used if a real alignment and depth fusion on it give the right answers. Otherwise the processor does the work, as before.
  • Nvidia on Windows: not used. Open3D's Windows graphics-card build is an experimental preview that isn't on the normal download site.
  • Apple M1–M5 Macs: not used. Open3D can't use Apple's graphics chip; Extreme uses all the processor cores instead.
  • AMD and Intel graphics: not used. Open3D supports Nvidia cards only.
  • No real graphics card has been tried. The card's code was run on the processor instead; see the write-up.

python3 scantastic.py --speed-check prints the same information and tests the card.

Scan target and compare (new in 0.9.0)

Save printable target (STL) writes a 70 x 70 mm test block, shown below. Each corner
has one feature:

  • steps 2, 4, 6 and 8 mm high;
  • a dome 30 mm across;
  • grooves 1, 2 and 3 mm wide;
  • a ramp.

An L-shaped notch on one side means it only fits one way round. Print it in a matt
colour, scan it on the turntable and build the mesh. Then Compare mesh with scan target
reports:

  • the typical error and the error that 9 points in 10 stay within, in mm;
  • how much of the top was covered;
  • each step height as scanned.

The same can be run outside the app:

python scan_target.py target.stl          # the STL
python scan_target.py --ring ring.pdf     # the marker ring
python scan_target.py --compare scan.stl  # compare a scan with the target
Enter fullscreen mode Exit fullscreen mode

Scan target

Turntable mode

The camera on and off, and turning the picture (new in 0.5.0)

Control What it does
Turn camera off / Turn camera on (Camera panel) Off stops the camera and keeps it off, also the next time the app starts, until you turn it on. The line under the button says what the camera is doing: live, waiting for one to be plugged in, or off.
Rotate (above the picture) Turns the live picture a quarter turn clockwise each press, for a camera mounted on its side or upside down. The 3D model's default view and the sensor check's pictures turn with it. The scan data itself is not changed. Remembered.

Unplug the camera and the app notices (at once on Linux, within about 8 seconds
elsewhere), says so, and starts the picture again when the camera is back. A camera that is
plugged in but will not start is reported once in the status line, with no dialog; press
Capture Frame to see the full reason. START SCAN and Capture Frame still start the camera
themselves, and turn it on if it was off.

A Kinect is looked for in the same way on Linux. On Windows and macOS there is no quick way
to look for one, so a Kinect starts when you press START SCAN or Capture Frame.

Settings for each camera, and which camera is running (new in 0.6.0)

Each kind of camera has its own settings. When a camera starts, the app puts that
camera's settings in the window, and anything you change is remembered for that camera
only. So a D415 and an SR305 can be swapped without retuning. Reset ... settings in
the Camera panel puts the starting values back for the camera in use. The line under it
lists what you have changed.

The coloured badge at the top of the Camera panel says which camera is running: blue for
an SR305 / SR300, orange for a D400, purple for a Kinect, grey for none. The model name is
also shown in that colour on the live picture and in the window title.

Starting values (best guesses; the reasons are in DESIGN_NOTES section 3):

Setting SR305 / SR300 D400 (D415) Kinect
Near / Far 0.20 / 1.00 m 0.25 / 1.00 m 0.5 / 3.0 m
Depth confidence Standard (no such setting) (no such setting)
Laser power Maximum Maximum (no such setting)
Quality 60 60 60
Surface detail Standard Fine (1.0 mm grid) Standard
Narrow band / 3+ frames off / off off / off off / off
Final smoothing passes 5 2 5
Fill holes smaller than off 8 mm off
Sensor-check mask: only no-depth patches off on off
Only keep the subject / Average when still on / on on / on on / on

Black spots in the same place on the screen (0.6.1)

A black spot that stays put whatever you scan is one of two things, and the live depth
picture now tells them apart:

  • Magenta: the sensor-check mask. You ran the sensor check and the app ignores those pixels on purpose. Untick Ignore damaged sensor areas to see what the camera gives there, or tick ...only patches with no depth to keep the merely noisy parts (run the sensor check again once, to save that smaller mask).
  • Black: the camera gives no depth there (a scratch, mark or smear on the window, or a dark or shiny patch). Clean the window with a blower and a dry, soft cloth (no liquids).

Either way, move the object (or yourself) between frames. A spot at a fixed place on
the screen falls on a different part of a turning object in the next frame, so the
other frames fill it in. And Fill holes smaller than ... mm (Quality panel) closes
what is left in the finished mesh with flat patches. It starts at 8 mm for a D400.

D400 advanced mode and firmware (0.7.1)

Advanced mode. A D400 has a setting stored in the camera called "advanced mode".
Intel's driver only offers the High Accuracy preset and 0.1 mm depth steps while it is on,
and the ripple correction needs it too. The first time a D400 with it off starts, the app
asks whether it may switch it on. The camera restarts once, a few seconds, and it stays
on. The tick box "Let the app switch on a D400's advanced mode" in the Camera panel
changes your answer. Intel RealSense Viewer can switch it off again.

D400 firmware. The app uses Intel's driver 2.54.2. It has to: 2.55 and later dropped the
SR305. That driver is fine for a D415, because the depth is worked out inside the
camera, but Intel recommends D400 firmware 5.15.0.2 or later with it. The status line
says when a camera's firmware is older. The D415 tested here reports 5.11.10, from 2019.
It works. Updating is optional, done with Intel's tools rather than this app:

  • Intel RealSense Viewer, under More, Update Firmware;
  • or rs-fw-update. Read the D400 firmware release notes first. Keep the camera plugged in and don't interrupt the update.

D400 cameras such as the D415 (0.5.1)

Before 0.5.1 a D400 shared the SR305's settings, and scans looked coated in a thick soft
skin. Now a D400 gets its own:

  • depth at 848x480 instead of 640x480 (sharper; still works from about 30 cm);
  • 0.1 mm depth steps instead of 1 mm;
  • Intel's ripple correction (A-factor 0.08), if the camera's advanced mode is on. If it is off, the log says so. Intel RealSense Viewer can switch it on once and it stays on;
  • a wider trim along object outlines, where stereo depth spills past the real edge;
  • (0.5.2) the colour laid onto the depth, so the depth is never resampled;
  • (0.5.2) 2 smoothing passes to start with instead of 5; (0.6.0) its own remembered settings.

The status line and the sensor check report say whether the ripple correction is on.

Scan at the close end of the guide, about 35 to 45 cm. If a white or shiny object still
looks blobby, try Laser Reduced. A sensor-check mask made before 0.5.1 is ignored on a
D400 (wrong resolution), so run the check again.

Cutting: point at where the cut goes (new in 0.4.0)

A cut set on the model

The cut is set on the model itself, in the 3D view. The part that will be cut off turns
red before anything is changed.

  1. Press Draw a cut (in the 3D view, or Draw the cut on the model in the Edit panel) and drag a line across the model. The cut follows the line and goes straight into the screen. Hold Shift for a level, upright or 15-degree line. Esc cancels.
  2. Adjust it if needed: drag the yellow dot to move the cut, drag the red arrow to turn it. The arrow points at the part that goes. Or press Redraw and draw the line again.
  3. Flip side if the wrong part is red. Apply cut when it looks right. Undo last edit brings back both the mesh and the cut, so you can nudge it and apply again.

Three shortcuts, in the Edit panel:

Button What it does
Find the table / flat base Finds the biggest flat area of the model and puts the cut just above it, so the table goes and the subject stays. It is a suggestion: check the red part first.
Top, Bottom, Left, Right, Near, Far Cuts off that side of the model as you see it now. Turn the view first (the view cube snaps to a face) and these give exactly level or upright cuts.
How much Slides the cut through the model, from nothing cut off to everything.

"Cap the cut" (on by default) closes the cut with a flat face, which makes a solid you can
print; untick it to simply trim the surface. A scan seen from one side only is filled in
straight back to a flat back, just behind the deepest point of the part you keep.

This replaces the earlier orientation list, position slider and tilt joystick. A line drawn
on the model removes whichever part is the thinner slice; if you meant the other, Flip side.

Looking at the result: colours and background (0.2.2)

Height colours in the 3D view

Above the 3D view, Colours chooses how the mesh is painted:

Colours Shows
Scan colours The colours the camera saw.
Plain Grey, shaded only. Best for judging the shape without the texture distracting.
Height (low - high) Blue at the bottom to red at the top, with the range in millimetres and the highest and lowest points marked.
Relief (back - front) The same map, front to back. Small bumps and dents stand out.
Coverage (rescan hints) How many frames saw each part, so you know where to scan again.

Background switches the 3D view between dark, grey, light, white, navy or a colour
you pick. Both choices are remembered in settings.json next to the script.

Sensor check: what kind of fault is it? (new in 0.2.1)

Sensor check result

Sensor check (point at a wall)… looks at a plain, matt wall for about two
seconds and finds the parts of the view that misbehave, so scans can ignore them.
Since 0.2.1 it also says what kind of fault it found, because the cures differ:

  • Flicker (noise): the reading jumps about from frame to frame. Left picture. It cannot be subtracted; those pixels can only be trusted less.
  • Steady offset: the reading is wrong by the same amount every frame. Right picture (red = reads too far, blue = too near). An offset can in principle be subtracted.
  • Missing depth: purple in both pictures.

It also reports how curved the camera sees the flat wall (calibration error, or a
wall that is not flat) and whether a suspicious ring is only smooth calibration
error. Every run saves two pictures, the two maps (.npz) and a text report in
sensor_check/, named by wall distance and laser setting, so runs can be compared.

Useful comparisons, each one a fresh run of the check:

Change If the pattern changes If it stays the same
Laser power Maximum → Reduced Glare or saturation Calibration or the window
Wall at about 30, 40 and 60 cm Glare or saturation Calibration or optics
Camera turned 10–20° off square Glare off the wall The camera
Camera upside down or slid sideways Stays with the wall: the wall is not flat Stays with the image: the camera

Which pixels are ignored is decided exactly as in 0.2.0. One thing the breakdown
shows that the ignore-mask misses: a large area with a steady offset (a third of
the view reading 4 mm off, in the tests) is not ignored, because the old rule
compares each pixel with the spread across the whole view. The report says so when it happens.

Surface detail options (new in 0.2.1)

Under Quality, for the Smooth surface method. The defaults give exactly the
surface earlier versions gave.

Option What it does
Surface detail Grid size for fusing. Standard follows the Quality slider (2.5 mm at Low, about 1.5 mm in the middle, 1 mm at High). Fine / Finer / Finest fix it at 1.0 / 0.75 / 0.5 mm.
Narrow fusion band Sharper, but may leave holes where depth is noisy.
Only surface seen in 3+ frames Less noise, more holes. Needs 6 or more frames.
Final smoothing passes 0 = sharpest, 5 = as before.

Measured on a synthetic test object (a ball with 1 mm ripples, 40 frames, 1.5 mm
depth noise, subject isolated), with the camera positions known exactly:

Setting 6 mm ripples kept 3 mm ripples kept Fusing time
Standard, Quality in the middle (as before) 64% 48% 0.7 s
Standard, smoothing 0 70% 66% 0.7 s
Fine 1.0 mm, smoothing 0 73% 71% 1.1 s
Fine 1.0 mm, narrow band, smoothing 0 77% 73% 1.1 s
Finest 0.5 mm, smoothing 0 76% 75% 5.0 s

So these options help, modestly. How accurately the frames are lined up matters
far more.
The same test with small errors added to every camera position:

Error per frame 6 mm ripples kept (Fine, smoothing 0) 3 mm ripples kept
none 73% 71%
0.1° and 0.3 mm 71% 63%
0.25° and 0.5 mm 65% 46%
0.5° and 1 mm 48% 7%

Fine grids need more memory. If a scan would need too much, the app uses the
finest grid that fits and says so. Scanning only the subject ("Only keep the
subject in the middle") keeps the volume small.

Raw stream and clean-up

Clean-up dialog

Tick Record every camera frame before scanning to keep the raw colour and depth
(and optionally infrared) on disk. Afterwards, Open recording and clean up…
replays a recording folder (or a RealSense .bag) through these passes, each optional:

  • Depth gate: drop anything outside the near/far range.
  • Remove the table: finds the flat supporting surface (RANSAC) and removes it and everything below.
  • Edge-aware smoothing: smooths depth noise but stops at edges the colour picture shows.
  • Track camera movement from the picture: matches features in infrared first, then colour, and lifts them to 3D using the depth. The resulting poses guide the mesh alignment: they seed the ICP, rescue frames ICP can't verify, and veto an ICP result that contradicts confident tracking.
  • Compare neighbouring frames: re-projects neighbours into each frame, drops depth that disagrees (noise) and fills small holes.
  • Small AI background mask (optional, off by default): needs pip install onnxruntime into rs_env and models/u2netp.onnx.

Then it loads the result as normal scan frames, ready for BUILD MESH. How each pass
works, and where it can go wrong, is in HOW_IT_WORKS.md.

Quality and detail options

Notes, research and tools

Where What
DESIGN_NOTES.md What was looked into, what was measured, what was decided and why, what is untested, what to build next. Start here.
docs/research The full research report on soft scans and damaged sensors (68 sources), the working notes behind it, a printable PDF in plain English, and the Kinect driver bug report.
HOW_IT_WORKS.md What the app does, step by step, written from the code.
PROJECT_NOTES.md Short hand-over notes: where things stand and what is open.
tools detail_test.py repeats the surface-detail measurements; make_screenshots.py retakes every picture here from made-up data; make_research_pdf.py rebuilds the PDF; bench/ is the stitching benchmark (python tools/bench/bench.py --mode rotary --seeds 0-1).
scan_target.py The printable scan target, its compare report, and the turntable marker ring.

Source code: The-Dorkknight/scantastic on GitHub

Top comments (0)