Build PhotoRoom

KINDAreplaces $12.99/mosaves $155.88/yrback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A pipeline that takes a folder of product photographs, cuts out the subject with a segmentation model, composites onto a chosen background, applies consistent framing and padding, and exports at the exact sizes each destination needs, with every output reproducible from the source and a settings file.

estimated effort weekendthe files for this build are in the project pack

RuntimePython 3.12Segmentationrembg for speed, BiRefNet for edge quality, behind one interfaceCompositingPillow with alpha compositing in linear lightFramingSubject bounding box from the alpha mask, then padding rulesStorageSources untouched, outputs plus a settings hash per run

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the pipeline and hosts the model runtimes.

    Get it python.org or your package manager, then a virtual environment.

    Verify python3 --version prints 3.12 or higher

  2. have readyfree if you have suitable hardware; renting GPU time is the alternative and has a per-hour cost

    Why rembg runs acceptably on a processor; higher quality models are much slower without a GPU, which changes whether batch processing is practical.

    Get it Check what you have first. Time one image through both models before committing to a model for a two hundred image catalogue.

    Verify One image through the chosen model completes in a time you can multiply by your catalogue size

  3. have readyfree to download; check commercial use terms individually

    Why They are the engine, and their licences differ in ways that matter for commercial product photography.

    Get it rembg downloads its models on first use. Higher quality models are separate downloads. Read each licence before using it commercially rather than after.

    Verify Each model runs and its licence is recorded

  4. have readyfree

    Why Including at least one with hair or fur, one on a busy background and one where the subject touches the frame edge. Clean studio shots hide every problem this pipeline exists to solve.

    Get it Use your own catalogue. If you do not have one, this build has no use case yet and the pipeline decisions cannot be made well.

    Verify Twenty images are present with the three hard cases included

  5. have readyfree for generated backgrounds

    Why A composited background is redistributed with every product image you publish.

    Get it Solid colours and gradients you generate are safest. If you use photographs, check the licence permits commercial redistribution as part of a composite.

    Verify Every background asset's licence is recorded

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- runs(id, at, settings_hash, model, source_dir, output_dir)
- images(id, run_id, source_path, output_path, subject_bbox_json, alpha_coverage, warnings_json)
- settings(id, hash, model, background_json, padding_json, output_presets_json) · hashed so an output can always be traced to how it was made
- The settings hash on every output is what makes a catalogue reproducible: the same sources and the same hash produce the same images.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
SEGMENTATION_MODELrequiredrembgWhich model to use. Chosen by the comparison in Phase 1, not by reputation.
SOURCE_DIRrequired./photos/sourceInput directory. Never written to.
OUTPUT_DIRrequired./photos/outWhere composites and masks are written.
SUBJECT_FRAME_FRACTIONrequired0.78What proportion of the frame the subject fills. The single most important setting for a consistent catalogue.
BASELINE_FRACTIONrequired0.88Where the subject's bottom edge sits vertically. Anchoring here rather than centring is what aligns a grid.
BATCH_CONCURRENCYrequired2Concurrent images. Too high exhausts memory on a GPU faster than you expect.

The build, in order

  1. One cutout, and an honest look at the edges

    A single image is cut out, and you can see exactly where the model struggles.

    1. Save the alpha mask as its own file. The mask is what you are actually evaluating.

      terminal
      pip install rembg pillow
      rembg i input.jpg output.png
    2. A saturated colour, not white. Every edge problem becomes visible immediately.

      Files src/compare.py

    3. With the reason and the subject type. Hard-edged products and hair are genuinely different problems.

      Files docs/model-choice.md

    done when · tick each as it passes
    watch out
    • Comparing composites on a white background hides almost every edge failure, because a soft or wrong edge against white looks fine. Look at the alpha mask itself, and composite onto a saturated colour where a bad edge is obvious.
  2. Compositing without fringes

    The cutout sits on a new background with no dark halo around its edges.

    1. Undo the transfer function, composite, reapply. Do it once in a helper so no code path can skip it.

      Files src/composite.py

    2. Premultiplied or straight alpha, chosen deliberately and applied consistently. Mixing the two is how fringes reappear.

      Files src/composite.py

    3. The same subject on both. A fringe visible on one and not the other means the conversion is half applied.

    done when · tick each as it passes
    watch out
    • Alpha compositing in gamma-encoded space produces a dark fringe around every soft edge, which is subtle on white and glaring on a coloured background. Convert to linear light first, composite, then convert back. This one step is the difference between output that looks composited and output that looks photographed.
  3. Consistent framing across a catalogue

    Fifty products photographed at different distances end up looking like one set.

    1. Threshold the mask and find the tight bounds. Ignore isolated specks, which are usually mask noise rather than subject.

      Files src/frame.py

    2. The subject occupies a chosen fraction of the frame. This is what makes different photographs match.

      Files src/frame.py

    3. Horizontally centred, vertically sitting on a line. Compare a grid of outputs before and after to see why.

      Files src/frame.py

    done when · tick each as it passes
    watch out
    • Centring the bounding box vertically makes tall and short products look like they are floating at different heights when placed side by side in a grid. Anchor to a baseline instead, so everything sits on the same line, which is what makes a catalogue look deliberate.
  4. Batch that is reproducible

    A whole folder processes unattended, and any output can be regenerated exactly.

    1. Every setting that affects output goes into the hash. If changing something does not change the hash, the hash is wrong.

      Files src/settings.py

    2. Pin seeds and resampling filters. Run twice and compare bytes as a test.

      Files tests/test_determinism.py

    3. One unreadable file must not stop a run of two hundred. Report it and continue.

      Files src/batch.py

    done when · tick each as it passes
    watch out
    • A pipeline with any nondeterminism, such as a model running with a random seed or a resize using a nondeterministic path, cannot be reproduced, so a catalogue cannot be corrected image by image later. Pin the seed, pin the resampling filter, and verify by running twice and comparing bytes.
  5. Export presets and a review pass

    Each destination gets the size it needs, and the ones the model got wrong are easy to find.

    1. Named sizes per destination, with a test asserting output dimensions rather than trusting arithmetic.

      Files src/presets.py

    2. Alpha coverage, edge perimeter relative to area, and the count of partially transparent pixels. Sort by it.

      Files src/review.py

    3. Mark twenty by hand, then check whether the sort surfaces them. If it does not, the signal is wrong.

    done when · tick each as it passes
    watch out
    • Reviewing two hundred cutouts in file order means the five bad ones are found by someone else after publication. Sort by a signal that correlates with difficulty, because the failures cluster at one end and reviewing the top twenty catches most of them.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more generative media.