my parents gifted me a wonderfully quirky piece of 80s technology a few years ago, and it’s been a joy to shoot with. it’s a 4-lens stereoscopic camera (designed here in atlanta!) that takes four photos at once, each from a slightly different angle. they used to print them on lenticular sheets and, depending on the angle, you’d see a different shot.

this ‘wiggling’ is due to a phenomenon called parallax; objects further away appear to move more relative to the objects in the foreground. this is highlighted when you see the images switch rapidly from one to the next.
but scanning and digitizing these is a pain. you get four separate jpgs with no guarantee that the images will wiggle if you stack them on top of each other. the subject drifts across the frame, exposures are all different, it’s a mess. so i built nap (nimslo alignment pipeline) to handle all of this automatically.
what it does
nap takes those four wonky scans and turns them into a smooth boomerang gif or mp4 that loops back and forth, showing that classic 3d parallax effect where the background shifts around a stationary subject. here’s the pipeline:
preprocessing - runs a denoising pass to reduce film grain, balances exposure across frames using histogram equalization, and normalizes sizes so everything matches up
segmentation - figures out what the main subject is so it can center the alignment around it. uses u²-net (via rembg) for the heavy lifting, with depth-based fallback and opencv grabcut refinement if needed
alignment - uses sift feature matching to find corresponding points across frames, estimates homography transforms, and warps everything into alignment. optimizes for intersection-over-union of the segmented subject
render - applies those transforms to the original scans (so you keep all that nice film grain), crops out any black borders from the warping, and normalizes brightness so you don’t get flashing from exposure differences
export - spits out either a gif or mp4 boomerang. mp4 is tuned for film grain with ffmpeg’s
tune grain, crf 18, and proper even dimensions
how to use it
simple as:
# single batch
python nimslo_cli.py ./nimslo_raw/01/ -o output.gif
# batch process a whole folder
python nimslo_cli.py ./nimslo_raw/ --batch -o ./outputs/
# high quality mp4 with preview
python nimslo_cli.py ./nimslo_raw/01/ -o my_photo.mp4 -q best --preview
quality presets trade off speed vs accuracy:
- fast: 500 features, 400px max, no denoising
- balanced: 1000 features, 600px max, denoising (default)
- best: 2000 features, 800px max, denoising
if a batch only has 3 scans (camera malfunction or whatever), it’ll still work, you just get a 3-frame boomerang instead of 4.
what i learned
computer vision is wild. sift matching is surprisingly robust even with noisy film scans. homography transforms are like magic for aligning perspectives. segmentation models have gotten insanely good - u²-net picks out the subject reliably even from grainy 35mm scans.
the pipeline handles a lot of edge cases automatically: different image sizes, exposure differences, black borders from warping. it’s satisfying when it just works on a fresh batch of scans.
code’s all up at yuckyman/nap if you want to poke around or adapt it for your own camera workflows.