Eight stages from a folder of photographs to finished slides
A practice hands over a drive. The system finds the work on it, sorts every frame, pairs the befores to the afters, puts both frames at one scale with the eye line level, renders every format, and sheets the batch for review. Each stage writes files and stops at a gate a person looks at.
Put a before and an after at one scale
Load two photographs, click the same two fixed points on each, and the pair comes back at one size with the anchor line level and the frame cropped to what both photographs contain. The same two points download as a file the batch matcher takes with --points, which is how a body case gets an anchor at all. The pictures are read by this page in your browser. Nothing is uploaded and nothing is stored.
JPEG, PNG, HEIC-exported, any size
The pair may be portrait and landscape
Take these two points to the batch run
The points file is the anchor for every other view of the same person, and it is the only anchor a body case has. Download it, then run the matcher over the raw frames with it.
What the aligner does with the two points
The two points give a distance and an angle on each photograph. The photograph whose anchor distance is the larger share of its short side is the tighter frame, and it becomes the reference. The other frame is rotated and scaled by one number in both directions until its two points sit exactly on the reference's two points. The output frame is then grown outward from the anchor until it would leave one of the two photographs, which is the largest frame both pictures actually contain.
What it refuses to do
It will not stretch one axis to make a pair line up. A non-uniform scale slims a jaw or widens a smile, which fabricates a result. It will not enlarge past the point where the softer frame goes visibly soft without saying so in the readout. It will not crop into a region only one of the two photographs holds.
Eight stages, each with a gate
Every stage writes files to disk and then stops. The gate is a page or a sheet a person looks at, not a number in a log. Nothing moves forward until the gate is passed, so an interruption costs one stage rather than the batch.
Thirteen rules every slide obeys
These are the decisions that were wrong at least once and are now fixed in code. Each one is enforced by the matcher or the renderer, not left to the person building the slide.
The anchor changes with the procedure
The face detector returns five points. Which of them the transform is fitted on decides whether the slide shows the change or hides it. Align on the part that was operated on and the operation is scaled away.
Interocular distance over the short side, never over the height. Practices shoot the before in portrait and the after in landscape on the same camera. Measured against height those two read as a 42 percent difference in framing when the head is the same size in both, and the wrong frame gets picked as the reference.
| Procedure | Anchored on | Because |
|---|---|---|
| Facelift, neck lift, skin | eyes | The eyes do not move. Everything below them does. |
| Blepharoplasty, brow lift | nose+mouth | The eyes are the result. Anchoring there erases the lift. |
| Rhinoplasty | eyes+mouth | The nose is the result and is dropped from the fit. |
| Veneers, orthodontics, lips, filler | eyes+nose | The mouth is the result. The upper face holds still. |
| Hair transplant | all | The whole face is unchanged. The hairline above it is the result. |
| Breast and body | two clicked points | No face, no detector. Two marks a person picks set the scale and the roll, and the matcher takes them with --points. |
One facelift front view, end to end
Carlin Plastic Surgery, front view, built 2026-09-11. Two camera originals off the practice's drive, one portrait and one landscape, shot against two different backdrops. Every number below is read out of that case's record on disk.
| Measurement | Before · DSC_0054 | After · DSC_0042 | What it decided |
|---|---|---|---|
| Pixels | 1944 × 2896 portrait | 2896 × 1944 landscape | Short side is 1944 on both, so the two are comparable |
| Interocular | 372.9 px | 342.3 px | The after is the wider frame |
| Tightness | 0.1918 | 0.1761 | The before is tighter, so the before is the reference |
| Head roll | 0.33° | −3.45° | 3.78° of tilt to take out |
| Backdrop | #808482 grey, even | #0A0A0A black, even | Grounds disagree, so the slide uses the theme instead of the wall |
| Anchor | eyes · facelift leaves the eyes alone | Two landmarks drive the fit | |
| Transform on the after | scale 1.0675 · rotate 4.40° · shift −556.3, −16.4 px | One scale in both directions, no shear | |
| Landmark drift | 11.8 px, 3.2% of interocular | Inside tolerance | |
| Alignment score | 0.3249 from the landmarks, 0.5172 after refinement | Refinement earned 0.19 | |
| Common crop | 1883 × 1642 out of 1944 × 2896 | The largest frame both photographs hold | |
Ten cases, thirty-seven views, where each one landed
The whole Carlin set run through the matcher. Face cases carry a landmark anchor and a drift figure. Body cases have no face to anchor on, fall back to matching content, and every one of them is held for review by eye. This table is the argument for the body anchor being the next piece of work.
| Case | Procedure | Subject | Views | Anchor | Best view | Alignment range | Ruling |
|---|
Alignment is the correlation after refinement, per view, read from each case record. Ruling is the stage 6 decision: a face case with a landmark anchor and drift inside tolerance ships; a body case with no anchor is held until a person has read its proof sheet.
Seventy-five folders on one machine
The finder walked every project drive, the user's Pictures, Downloads, OneDrive and Dropbox folders and scored each folder on its name, its filenames, its image count and how many of those are camera originals. Nothing is decoded and nothing is moved. Our own outputs are excluded, and sibling case folders roll up so a ten-case set reads as one row.
| Score | Folder | Images | Why it scored |
|---|---|---|---|
| 15.7 | ACTIVE-CARLIN \ from-brenda \ bna | 81 | 10 case folders, before and after words in filenames, 45 camera originals |
| 15.0 | ACTIVE-CARLIN \ content \ bna-census | 305 | 5 case folders, 184 filenames carrying before or after, 64 camera originals |
| 14.7 | ACTIVE-LACERNA \ 2025 new work \ case 1 | 16 | Named before and after, all 16 camera originals |
| 13.0 | ACTIVE-CARLIN \ new photos from SOMA \ August-2026 | 118 | 11 case folders, finished slide sizes in the names |
| 13.0 | ACTIVE-JONES \ 2026-2-10-JONES-BNA | 27 | 16 filenames carrying before or after, 6 camera originals |
| 12.0 | ACTIVE-ODANIEL \ BNA from site morphs | 10 | Retouched portraits, already published |
| 11.0 | Dropbox \ 2019 backup \ O'Daniel face galleries | 224 | 11 case folders never on the board |
| 11.0 | Dropbox \ Lynam before and after books, 2019 | 104 | 104 camera originals, nothing derived |
| 11.0 | Dropbox \ Langdon face slides, 2024 | 41 | 3 case folders, 46 filenames carrying before or after |
| 10.7 | Dropbox \ Hetter lecture support \ bensimon case | 18 | A case inside a lecture folder, 10 camera originals |
Top ten of 75. The Dropbox layer underneath was the finding: four practices' complete galleries, none of them on any list, some of them the only surviving copy of a 2019 shoot. A phone is a folder too. Point the finder at a Camera Roll or a practice's shared Dropbox and it reads the same way.
Twenty-seven files sorted into five buckets
The Jones hair restoration folder, surveyed and planned. The survey measures every frame and groups them into sittings by shutter time. The plan sorts each frame into a bucket and then pairs the keepers, twice: named twins first, then sittings a day or more apart matched by class and nearest tightness.
18 keep
The raw material. Camera originals and full-size exports with a subject the matcher can work on.
5 composite
Slide-sized with no face, or named after-before or vert. A finished graphic from a previous vendor, not a source.
4 low-res
Short side under 500 pixels or under 0.35 megapixels. Web thumbnails, including one that is a site logo.
5 named pairs
Two filenames differing only by a before or after word. Typo tolerance found man-bwefore3 and paired it to man-after3.
2 check pairs
Sittings 17 years apart and one date taken from a file time rather than the camera. Flagged yellow on the plan page, never silently shipped.
2 orphans
Two Nikon frames from 2001 with no partner in any sitting. A lone after proves nothing, so neither is used.
What is built and what is not
The gaps are listed because a system that hides them ships a bad slide. Each open item names the work that closes it.
| Area | State | Detail |
|---|---|---|
| Finding the work on a machine | Built | 75 folders ranked in one pass, Dropbox and phone folders included |
| Sorting a folder into cases | Built | Five buckets, named twins, sitting pairs, a plan page as the gate |
| Orientation | Fixed 2026-09-16 | Every read applies the EXIF tag. Ten Carlin frames were matched sideways before it |
| Face matching and scaling | Built and measured | Five landmarks, five anchor sets, closed-form similarity fit, gradient refinement |
| Body and torso matching, by hand | Built 2026-09-16 | Two marks a person picks are passed to the matcher with --points. It measures the distance and the angle between them exactly as it measures an eye line, and reports how far refinement walked from the marks. The aligner above writes that file |
| Body and torso matching, automatic | No detector | 8 of 10 Carlin cases are body cases. Without points they fall back to content matching and every one is held. A shoulder line, nipple line, navel or silhouette fit is the next piece |
| Same person across sittings | Not built | Pairing is by filename or by sitting. Face recognition across a folder of many patients is not written |
| Rendering every format | Built | 16:9, 4K, 9:16, 1:1 and 4:5 per case, layout following the subject, head box carried through the transform |
| A practice's own slide card | Partial | Five studio themes with the ground sampled from the photograph. Carlin's mahogany card with the gold hairline is not reproduced |
| Contact sheets and case pages | Built | One sheet per batch, an index with the numbers, a page per case carrying every format and both proof sheets |
| Quality control rulings | Pattern only | The checklist and the rulings file exist. No command writes the ruling onto the case record yet |
| Delivery naming | Convention only | Folder convention and read-me are written by the organiser. The slide renamer and the JPEG and WebP web copies are not built |
| This aligner | Live on this page | Two clicked points, uniform scale, common crop, four proofs, three downloads, nothing uploaded |
The whole run, one command at a time
The command-line side runs on Python with OpenCV and NumPy, plus Node 18 and Chrome for the renderer. Each command writes into one output directory and prints what it wrote.
A practice from scratch
# 0 · rank every folder on the machine python find.py --out reports/before-after # 1 · measure the folder, then propose the cases python survey.py "D:\PRACTICE\raw" --out work/survey python organize.py work/survey/survey.json \ --out work/plan --practice "Practice Name" # open work/plan/plan.html and confirm every pair # 2 · the house decisions, once edit work/house.json # 3 · prove it on one case, then on the strongest few python build_cases.py work/plan/plan.json --out build \ --procedure facelift --faces-only node render/slide.mjs build/case-01 # 4 · the full pass python build_cases.py work/plan/plan.json --out build node render/slide.mjs build # 5 · sheet the batch python gallery.py build --title "Practice Name" # 6 · rule on every case against the checklist # 7 · deliver python organize.py work/survey/survey.json --out delivery \ --practice "Practice Name" --apply
Reading a pair before you build it
# what the detector sees in one pair, before you build anything python match.py report before.JPG after.JPG # one pair, one proof sheet, no case folder python match.py pair before.JPG after.JPG \ --on nose+mouth --out proof/ # one case folder that already exists, re-matched python match.py case build/case-01 --on eyes
The flags that matter
--procedure | Picks the anchor set from the operation name |
--on | Overrides it with eyes, eyes+nose, eyes+mouth, nose+mouth or all |
--flip before|after | Mirrors one side when the practice shot opposite profiles |
--subject face|smile|body | Overrides what the detector decided the frame is |
--faces-only | Builds the face cases and skips the body cases still waiting on an anchor |
--root | Points the builder at the photographs when the folder has moved since the survey |
--force | Rebuilds a case that already carries a record. Without it a second run costs nothing |
--points | Two marks per frame, picked by hand. The only anchor a body case has. The aligner on this page writes the file |
--apply | The one flag that copies files. Everything else only reads |
--apply touches a source file. The survey, the plan, the match and the render all read the originals and write somewhere else. A practice's drive comes back exactly as it went in.Send us the drive
Most practices have four or five folders of before and after photography and no gallery. The first pass is the finder and the plan page, which costs nothing to look at and tells you what is actually on the drive before anyone builds a slide.