Vibecode Pixelcut
track this build4 phases, 12 steps, beginner friendly0%The core loop is buildable, but a dependable replacement becomes a real weekend or multi-day project. For Pixelcut, batch-remove backgrounds, resize product images, and apply simple local templates. The hard boundary is mobile polish, hosted models, team assets, and api scale, plus frontier models, compute, and data.
You are building a lean indie version of Pixelcut. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Pixelcut · indie build A product image pipeline where the difficult parts are the edges: hair and transparent objects need a real alpha matte rather than a hard mask, a cut-out with no shadow looks pasted on, and a replaced background changes the colour the product appears to be, which for a listing is a returns problem. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Segmentation | A local matting model producing a soft alpha channel | a binary mask cannot represent hair, glass or motion blur | | Imaging | A library with correct colour management and high bit depth | eight-bit compositing in the wrong colour space visibly degrades edges | | Composition | Shadow synthesis and edge decontamination | a cut-out without these reads as fake immediately | | Batch | A worker queue with per-image isolation and a manifest | hundreds of images, and one failure must not cost the run | | Runtime | Python 3.12 | the ecosystem for imaging and models is here | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Python 3.12 or newer** · free - Why: Runs the pipeline and the model. - Get it: python.org or your package manager, then a virtual environment. - Verify: python3 --version prints 3.12 or higher - [ ] **A local matting model** · free for open models; needs a capable machine - Why: A binary segmentation model cannot represent hair, glass or motion blur, which is where every real product catalogue fails. - Get it: An open matting model with published weights you may use for your purpose. Check the licence covers commercial use if this is for a business. - Verify: It outputs a soft alpha channel rather than a binary mask - [ ] **An imaging library with colour management** · free - Why: Compositing in the wrong colour space darkens edges in a way that looks like a bad cut-out rather than a bug, so it is never diagnosed. - Get it: A library supporting high bit depth and explicit colour space conversion. - Verify: A round trip through linear space and back is lossless at high bit depth - [ ] **Five genuinely hard product images** · free - Why: Anything succeeds on a shoe against white. The acceptance set decides whether the pipeline is usable. - Get it: Photograph or find: hair or fur, a glass or transparent object, a mesh fabric, something with motion blur, and a product on a background close to its own colour. - Verify: All five exist and each fails a naive binary mask - [ ] **A colour reference in some shots** · the price of a colour card, or free with a known product - Why: Measuring how far a composite moved the product's colour requires knowing what the colour was, and eyeballing it does not work. - Get it: A colour card in a few reference shots, or at minimum a known product whose true colour you can state. - Verify: At least three images have a known reference colour ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. - mobile polish, hosted models, team assets, and API scale - frontier proprietary models - hosted GPU capacity - licensed training data - moderation and fast global delivery If one of those is essential to you, that is the reason to keep paying for Pixelcut, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Pixelcut The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me batch background removal and product image preparation, run locally to replace Pixelcut. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Segmentation: A local matting model producing a soft alpha channel · a binary mask cannot represent hair, glass or motion blur - Imaging: A library with correct colour management and high bit depth · eight-bit compositing in the wrong colour space visibly degrades edges - Composition: Shadow synthesis and edge decontamination · a cut-out without these reads as fake immediately - Batch: A worker queue with per-image isolation and a manifest · hundreds of images, and one failure must not cost the run - Runtime: Python 3.12 · the ecosystem for imaging and models is here ### Data model (create this before Phase 1) - images(id, path, width, height, colour_profile, content_hash, imported_at) - mattes(image_id, alpha_path, model, refined, edge_quality) · alpha as a separate channel, kept - compositions(id, image_id, background_kind, background_ref, shadow_params_json, output_path, at) - reviews(composition_id, verdict, note, at) · verdict is accepted, needs_manual or rejected - batches(id, started_at, ended_at, input_count, succeeded, failed, manifest_path) - colour_checks(composition_id, delta_e, region) · how far the product's colour moved, measured rather than assumed - The alpha matte is stored separately from any composition, because the expensive step should be reused when the background changes. ### Phase 1 · An alpha matte, not a mask Build: Run a local matting model producing a soft alpha channel. Keep the alpha separately from any composite. Evaluate on the hard cases rather than on a product on a white background, which anything can do. Trap: Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. Done when: Hair, a glass object and a mesh fabric all produce plausible soft edges rather than a hard cut. The alpha is stored separately and is reusable across backgrounds. A product photographed on a similar-coloured background is handled or reported as low quality. Matting runs with networking disabled. Do not build yet: No refinement, backgrounds or batch. ### Phase 2 · Edges that do not carry the old background Build: Decontaminate edge colour so pixels partially covered by the subject do not carry the original background's colour. Composite in a linear colour space. Verify on a subject cut from a strongly coloured background. Trap: Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. Done when: A subject cut from a strongly coloured background shows no colour fringe on a new one, verified by inspecting edge pixels. Compositing happens in linear space, verified by comparing against a reference composite. Semi-transparent regions blend correctly. The output carries a correct colour profile. Do not build yet: No shadows, backgrounds or batch yet. ### Phase 3 · Shadows, because floating objects look wrong Build: Synthesise a contact shadow from the alpha's lower boundary, with configurable softness and direction. Detect the original lighting direction where possible and match it. Allow no shadow as a deliberate choice. Trap: A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. Done when: A product on a plain background reads as resting rather than floating. Shadow direction does not contradict the product's own lighting, checked across ten images. Shadow parameters are reproducible from stored values. No shadow is available as an explicit choice rather than the absence of a setting. Do not build yet: No batch or colour verification yet. ### Phase 4 · Measuring what you did to the colour Build: Measure the colour difference in the product region between the original and the composite. Warn above a threshold. Keep the product region unmodified by any background adjustment. Trap: Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. Done when: The colour difference in the product region is measured and reported per composition. A shift above the threshold produces a warning rather than a silent output. Background adjustments do not alter product pixels, verified by comparing the product region before and after. The threshold is configurable and its default is stated. Do not build yet: No batch or export yet. ### Phase 5 · Hundreds of images, unattended Build: A batch queue processing a directory with per-image isolation, output sizing for target placements, and a manifest recording every input, its settings and its outputs. Flag images needing manual attention rather than shipping them. Trap: A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. Done when: Three hundred images process unattended with per-image failure isolation. Low-quality mattes are routed to review rather than output, verified with a deliberately hard set. The manifest records inputs, settings, outputs and flags. Re-running with the same settings produces identical outputs, verified by checksum. Do not build yet: Nothing after this. ### Out of scope (and why) - Generative background creation, which is a different problem and one where the generated scene often implies lighting the product does not have. - Commercial-grade matting quality, which is where the hosted products have invested most and shows on the hardest ten percent of images. - Mobile capture and editing, which is how a lot of this category is actually used. - Marketplace-specific compliance, since each platform has its own image rules and they change. ### README must contain - That a soft alpha matte is produced rather than a binary mask, and why hair and glass require it - That compositing happens in linear space and edge colour is decontaminated - That shadow direction is matched to the product's own lighting rather than chosen - That the colour shift in the product region is measured and warned on - That low-quality mattes are routed to review rather than shipped ===== AGENTS.md ===== # Agent instructions · Pixelcut indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A local matting model producing a soft alpha channel, A library with correct colour management and high bit depth, Shadow synthesis and edge decontamination, A worker queue with per-image isolation and a manifest, Python 3.12. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ===== BUILD_PLAN.md ===== # Build plan · Pixelcut A product image pipeline where the difficult parts are the edges: hair and transparent objects need a real alpha matte rather than a hard mask, a cut-out with no shadow looks pasted on, and a replaced background changes the colour the product appears to be, which for a listing is a returns problem. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · An alpha matte, not a mask Hair and transparent edges survive the cut-out. ### Steps 1. Produce and store a soft alpha Separately from any composite. It is the expensive step and it is reusable. Files: `src/matte.py` 2. Build a hard-case acceptance set Hair, glass, mesh, motion blur, similar-coloured background. Five real ones. Files: `fixtures/hard/` 3. Report low quality rather than guessing A bad matte silently composited is worse than a flagged one. Files: `src/quality.py` ### Done when - [ ] Hair, glass and mesh produce soft edges - [ ] Alpha is stored separately and reusable - [ ] A similar-coloured background is handled or reported - [ ] Matting works offline ### Watch out - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. ## Phase 2 · Edges that do not carry the old background A cut-out placed on a new background has no halo from the old one. ### Steps 1. Decontaminate edge colour Partially covered pixels carry the old background otherwise. Files: `src/decontaminate.py` 2. Composite in linear space Convert, composite, convert back. Display-space compositing darkens edges. Files: `src/composite.py`, `tests/test_linear.py` 3. Preserve the colour profile An output with no profile is interpreted differently everywhere. Files: `src/colour.py` ### Done when - [ ] No colour fringe from a strong original background - [ ] Compositing matches a linear-space reference - [ ] Semi-transparent regions blend correctly - [ ] Output carries a correct colour profile ### Watch out - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. ## Phase 3 · Shadows, because floating objects look wrong A product on a new background looks like it is resting on something. ### Steps 1. Synthesise a contact shadow from the alpha The lower boundary of the subject. Soft and short beats dramatic. Files: `src/shadow.py` 2. Match the product's own lighting A contradicting shadow is worse than none. Files: `src/lighting.py` 3. Store shadow parameters So a composition is reproducible rather than a one-off result. Files: `src/compositions.py` ### Done when - [ ] Products read as resting rather than floating - [ ] Shadow direction does not contradict the lighting - [ ] Shadow parameters reproduce the same result - [ ] No shadow is an explicit option ### Watch out - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. ## Phase 4 · Measuring what you did to the colour You know whether the product still looks like the product. ### Steps 1. Measure the product region shift A stated metric, per composition, recorded. Files: `src/colour_check.py` 2. Warn above a threshold A listing image that misrepresents colour causes returns. Files: `src/colour_check.py` 3. Adjust only the background The product region is not yours to change. Files: `src/composite.py`, `tests/test_product_untouched.py` ### Done when - [ ] Colour shift is measured and reported - [ ] A large shift produces a warning - [ ] Background adjustment leaves product pixels unchanged - [ ] The threshold is configurable with a stated default ### Watch out - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ## Not in this build - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. ## After v1, if you want it - Consistent framing and margins across a catalogue, which matters more than any single image - Reflection synthesis for products on glossy surfaces - A manual refinement brush for the images that reach review ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Source images, opened read only. INPUT_DIR=./input # Required. Composites and manifests. Never the input directory. OUTPUT_DIR=./output # Required. The matting model. Its licence matters if this is commercial work. MATTE_MODEL=./models/matting.onnx # Required. Below this an image goes to review rather than output. MATTE_QUALITY_THRESHOLD=0.75 # Required. How far the product's colour may move before warning. Small, because listings cause returns. COLOUR_SHIFT_WARN_DELTA_E=2.0 # Required. Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. SHADOW_DEFAULT=contact_soft
You are building a lean indie version of Pixelcut. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Pixelcut · indie build A product image pipeline where the difficult parts are the edges: hair and transparent objects need a real alpha matte rather than a hard mask, a cut-out with no shadow looks pasted on, and a replaced background changes the colour the product appears to be, which for a listing is a returns problem. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Segmentation | A local matting model producing a soft alpha channel | a binary mask cannot represent hair, glass or motion blur | | Imaging | A library with correct colour management and high bit depth | eight-bit compositing in the wrong colour space visibly degrades edges | | Composition | Shadow synthesis and edge decontamination | a cut-out without these reads as fake immediately | | Batch | A worker queue with per-image isolation and a manifest | hundreds of images, and one failure must not cost the run | | Runtime | Python 3.12 | the ecosystem for imaging and models is here | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Python 3.12 or newer** · free - Why: Runs the pipeline and the model. - Get it: python.org or your package manager, then a virtual environment. - Verify: python3 --version prints 3.12 or higher - [ ] **A local matting model** · free for open models; needs a capable machine - Why: A binary segmentation model cannot represent hair, glass or motion blur, which is where every real product catalogue fails. - Get it: An open matting model with published weights you may use for your purpose. Check the licence covers commercial use if this is for a business. - Verify: It outputs a soft alpha channel rather than a binary mask - [ ] **An imaging library with colour management** · free - Why: Compositing in the wrong colour space darkens edges in a way that looks like a bad cut-out rather than a bug, so it is never diagnosed. - Get it: A library supporting high bit depth and explicit colour space conversion. - Verify: A round trip through linear space and back is lossless at high bit depth - [ ] **Five genuinely hard product images** · free - Why: Anything succeeds on a shoe against white. The acceptance set decides whether the pipeline is usable. - Get it: Photograph or find: hair or fur, a glass or transparent object, a mesh fabric, something with motion blur, and a product on a background close to its own colour. - Verify: All five exist and each fails a naive binary mask - [ ] **A colour reference in some shots** · the price of a colour card, or free with a known product - Why: Measuring how far a composite moved the product's colour requires knowing what the colour was, and eyeballing it does not work. - Get it: A colour card in a few reference shots, or at minimum a known product whose true colour you can state. - Verify: At least three images have a known reference colour ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. - mobile polish, hosted models, team assets, and API scale - frontier proprietary models - hosted GPU capacity - licensed training data - moderation and fast global delivery If one of those is essential to you, that is the reason to keep paying for Pixelcut, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Pixelcut The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me batch background removal and product image preparation, run locally to replace Pixelcut. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Segmentation: A local matting model producing a soft alpha channel · a binary mask cannot represent hair, glass or motion blur - Imaging: A library with correct colour management and high bit depth · eight-bit compositing in the wrong colour space visibly degrades edges - Composition: Shadow synthesis and edge decontamination · a cut-out without these reads as fake immediately - Batch: A worker queue with per-image isolation and a manifest · hundreds of images, and one failure must not cost the run - Runtime: Python 3.12 · the ecosystem for imaging and models is here ### Data model (create this before Phase 1) - images(id, path, width, height, colour_profile, content_hash, imported_at) - mattes(image_id, alpha_path, model, refined, edge_quality) · alpha as a separate channel, kept - compositions(id, image_id, background_kind, background_ref, shadow_params_json, output_path, at) - reviews(composition_id, verdict, note, at) · verdict is accepted, needs_manual or rejected - batches(id, started_at, ended_at, input_count, succeeded, failed, manifest_path) - colour_checks(composition_id, delta_e, region) · how far the product's colour moved, measured rather than assumed - The alpha matte is stored separately from any composition, because the expensive step should be reused when the background changes. ### Phase 1 · An alpha matte, not a mask Build: Run a local matting model producing a soft alpha channel. Keep the alpha separately from any composite. Evaluate on the hard cases rather than on a product on a white background, which anything can do. Trap: Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. Done when: Hair, a glass object and a mesh fabric all produce plausible soft edges rather than a hard cut. The alpha is stored separately and is reusable across backgrounds. A product photographed on a similar-coloured background is handled or reported as low quality. Matting runs with networking disabled. Do not build yet: No refinement, backgrounds or batch. ### Phase 2 · Edges that do not carry the old background Build: Decontaminate edge colour so pixels partially covered by the subject do not carry the original background's colour. Composite in a linear colour space. Verify on a subject cut from a strongly coloured background. Trap: Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. Done when: A subject cut from a strongly coloured background shows no colour fringe on a new one, verified by inspecting edge pixels. Compositing happens in linear space, verified by comparing against a reference composite. Semi-transparent regions blend correctly. The output carries a correct colour profile. Do not build yet: No shadows, backgrounds or batch yet. ### Phase 3 · Shadows, because floating objects look wrong Build: Synthesise a contact shadow from the alpha's lower boundary, with configurable softness and direction. Detect the original lighting direction where possible and match it. Allow no shadow as a deliberate choice. Trap: A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. Done when: A product on a plain background reads as resting rather than floating. Shadow direction does not contradict the product's own lighting, checked across ten images. Shadow parameters are reproducible from stored values. No shadow is available as an explicit choice rather than the absence of a setting. Do not build yet: No batch or colour verification yet. ### Phase 4 · Measuring what you did to the colour Build: Measure the colour difference in the product region between the original and the composite. Warn above a threshold. Keep the product region unmodified by any background adjustment. Trap: Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. Done when: The colour difference in the product region is measured and reported per composition. A shift above the threshold produces a warning rather than a silent output. Background adjustments do not alter product pixels, verified by comparing the product region before and after. The threshold is configurable and its default is stated. Do not build yet: No batch or export yet. ### Phase 5 · Hundreds of images, unattended Build: A batch queue processing a directory with per-image isolation, output sizing for target placements, and a manifest recording every input, its settings and its outputs. Flag images needing manual attention rather than shipping them. Trap: A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. Done when: Three hundred images process unattended with per-image failure isolation. Low-quality mattes are routed to review rather than output, verified with a deliberately hard set. The manifest records inputs, settings, outputs and flags. Re-running with the same settings produces identical outputs, verified by checksum. Do not build yet: Nothing after this. ### Out of scope (and why) - Generative background creation, which is a different problem and one where the generated scene often implies lighting the product does not have. - Commercial-grade matting quality, which is where the hosted products have invested most and shows on the hardest ten percent of images. - Mobile capture and editing, which is how a lot of this category is actually used. - Marketplace-specific compliance, since each platform has its own image rules and they change. ### README must contain - That a soft alpha matte is produced rather than a binary mask, and why hair and glass require it - That compositing happens in linear space and edge colour is decontaminated - That shadow direction is matched to the product's own lighting rather than chosen - That the colour shift in the product region is measured and warned on - That low-quality mattes are routed to review rather than shipped ===== AGENTS.md ===== # Agent instructions · Pixelcut indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A local matting model producing a soft alpha channel, A library with correct colour management and high bit depth, Shadow synthesis and edge decontamination, A worker queue with per-image isolation and a manifest, Python 3.12. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ===== BUILD_PLAN.md ===== # Build plan · Pixelcut A product image pipeline where the difficult parts are the edges: hair and transparent objects need a real alpha matte rather than a hard mask, a cut-out with no shadow looks pasted on, and a replaced background changes the colour the product appears to be, which for a listing is a returns problem. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · An alpha matte, not a mask Hair and transparent edges survive the cut-out. ### Steps 1. Produce and store a soft alpha Separately from any composite. It is the expensive step and it is reusable. Files: `src/matte.py` 2. Build a hard-case acceptance set Hair, glass, mesh, motion blur, similar-coloured background. Five real ones. Files: `fixtures/hard/` 3. Report low quality rather than guessing A bad matte silently composited is worse than a flagged one. Files: `src/quality.py` ### Done when - [ ] Hair, glass and mesh produce soft edges - [ ] Alpha is stored separately and reusable - [ ] A similar-coloured background is handled or reported - [ ] Matting works offline ### Watch out - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. ## Phase 2 · Edges that do not carry the old background A cut-out placed on a new background has no halo from the old one. ### Steps 1. Decontaminate edge colour Partially covered pixels carry the old background otherwise. Files: `src/decontaminate.py` 2. Composite in linear space Convert, composite, convert back. Display-space compositing darkens edges. Files: `src/composite.py`, `tests/test_linear.py` 3. Preserve the colour profile An output with no profile is interpreted differently everywhere. Files: `src/colour.py` ### Done when - [ ] No colour fringe from a strong original background - [ ] Compositing matches a linear-space reference - [ ] Semi-transparent regions blend correctly - [ ] Output carries a correct colour profile ### Watch out - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. ## Phase 3 · Shadows, because floating objects look wrong A product on a new background looks like it is resting on something. ### Steps 1. Synthesise a contact shadow from the alpha The lower boundary of the subject. Soft and short beats dramatic. Files: `src/shadow.py` 2. Match the product's own lighting A contradicting shadow is worse than none. Files: `src/lighting.py` 3. Store shadow parameters So a composition is reproducible rather than a one-off result. Files: `src/compositions.py` ### Done when - [ ] Products read as resting rather than floating - [ ] Shadow direction does not contradict the lighting - [ ] Shadow parameters reproduce the same result - [ ] No shadow is an explicit option ### Watch out - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. ## Phase 4 · Measuring what you did to the colour You know whether the product still looks like the product. ### Steps 1. Measure the product region shift A stated metric, per composition, recorded. Files: `src/colour_check.py` 2. Warn above a threshold A listing image that misrepresents colour causes returns. Files: `src/colour_check.py` 3. Adjust only the background The product region is not yours to change. Files: `src/composite.py`, `tests/test_product_untouched.py` ### Done when - [ ] Colour shift is measured and reported - [ ] A large shift produces a warning - [ ] Background adjustment leaves product pixels unchanged - [ ] The threshold is configurable with a stated default ### Watch out - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ## Not in this build - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. ## After v1, if you want it - Consistent framing and margins across a catalogue, which matters more than any single image - Reflection synthesis for products on glossy surfaces - A manual refinement brush for the images that reach review ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Source images, opened read only. INPUT_DIR=./input # Required. Composites and manifests. Never the input directory. OUTPUT_DIR=./output # Required. The matting model. Its licence matters if this is commercial work. MATTE_MODEL=./models/matting.onnx # Required. Below this an image goes to review rather than output. MATTE_QUALITY_THRESHOLD=0.75 # Required. How far the product's colour may move before warning. Small, because listings cause returns. COLOUR_SHIFT_WARN_DELTA_E=2.0 # Required. Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. SHADOW_DEFAULT=contact_soft
You are building a production product version of Pixelcut. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Pixelcut · product brief ## Problem The core loop is buildable, but a dependable replacement becomes a real weekend or multi-day project. For Pixelcut, batch-remove backgrounds, resize product images, and apply simple local templates. The hard boundary is mobile polish, hosted models, team assets, and api scale, plus frontier models, compute, and data. ## Product outcome A batch pipeline that cuts out hair and glass properly, places products on new backgrounds without a halo or a floating look, and tells you when it changed the colour the product appears to be. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - GPU-capable machine or user-supplied generation API - ComfyUI - model files with appropriate licenses - local storage ## Explicit non-goals for v1 - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. - mobile polish, hosted models, team assets, and API scale - frontier proprietary models - hosted GPU capacity - licensed training data - moderation and fast global delivery ## Success criteria - Hair, glass and mesh are confirmed to produce soft edges - No colour fringe is confirmed from a strong original background - Product pixels are confirmed unchanged by background adjustment - Low-quality mattes are confirmed routed to review - Re-running is confirmed to produce identical outputs ===== BRIEF.md ===== # Build brief · Pixelcut The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me batch background removal and product image preparation, run locally to replace Pixelcut. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Segmentation: A local matting model producing a soft alpha channel · a binary mask cannot represent hair, glass or motion blur - Imaging: A library with correct colour management and high bit depth · eight-bit compositing in the wrong colour space visibly degrades edges - Composition: Shadow synthesis and edge decontamination · a cut-out without these reads as fake immediately - Batch: A worker queue with per-image isolation and a manifest · hundreds of images, and one failure must not cost the run - Runtime: Python 3.12 · the ecosystem for imaging and models is here ### Data model (create this before Phase 1) - images(id, path, width, height, colour_profile, content_hash, imported_at) - mattes(image_id, alpha_path, model, refined, edge_quality) · alpha as a separate channel, kept - compositions(id, image_id, background_kind, background_ref, shadow_params_json, output_path, at) - reviews(composition_id, verdict, note, at) · verdict is accepted, needs_manual or rejected - batches(id, started_at, ended_at, input_count, succeeded, failed, manifest_path) - colour_checks(composition_id, delta_e, region) · how far the product's colour moved, measured rather than assumed - The alpha matte is stored separately from any composition, because the expensive step should be reused when the background changes. ### Phase 1 · An alpha matte, not a mask Build: Run a local matting model producing a soft alpha channel. Keep the alpha separately from any composite. Evaluate on the hard cases rather than on a product on a white background, which anything can do. Trap: Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. Done when: Hair, a glass object and a mesh fabric all produce plausible soft edges rather than a hard cut. The alpha is stored separately and is reusable across backgrounds. A product photographed on a similar-coloured background is handled or reported as low quality. Matting runs with networking disabled. Do not build yet: No refinement, backgrounds or batch. ### Phase 2 · Edges that do not carry the old background Build: Decontaminate edge colour so pixels partially covered by the subject do not carry the original background's colour. Composite in a linear colour space. Verify on a subject cut from a strongly coloured background. Trap: Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. Done when: A subject cut from a strongly coloured background shows no colour fringe on a new one, verified by inspecting edge pixels. Compositing happens in linear space, verified by comparing against a reference composite. Semi-transparent regions blend correctly. The output carries a correct colour profile. Do not build yet: No shadows, backgrounds or batch yet. ### Phase 3 · Shadows, because floating objects look wrong Build: Synthesise a contact shadow from the alpha's lower boundary, with configurable softness and direction. Detect the original lighting direction where possible and match it. Allow no shadow as a deliberate choice. Trap: A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. Done when: A product on a plain background reads as resting rather than floating. Shadow direction does not contradict the product's own lighting, checked across ten images. Shadow parameters are reproducible from stored values. No shadow is available as an explicit choice rather than the absence of a setting. Do not build yet: No batch or colour verification yet. ### Phase 4 · Measuring what you did to the colour Build: Measure the colour difference in the product region between the original and the composite. Warn above a threshold. Keep the product region unmodified by any background adjustment. Trap: Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. Done when: The colour difference in the product region is measured and reported per composition. A shift above the threshold produces a warning rather than a silent output. Background adjustments do not alter product pixels, verified by comparing the product region before and after. The threshold is configurable and its default is stated. Do not build yet: No batch or export yet. ### Phase 5 · Hundreds of images, unattended Build: A batch queue processing a directory with per-image isolation, output sizing for target placements, and a manifest recording every input, its settings and its outputs. Flag images needing manual attention rather than shipping them. Trap: A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. Done when: Three hundred images process unattended with per-image failure isolation. Low-quality mattes are routed to review rather than output, verified with a deliberately hard set. The manifest records inputs, settings, outputs and flags. Re-running with the same settings produces identical outputs, verified by checksum. Do not build yet: Nothing after this. ### Out of scope (and why) - Generative background creation, which is a different problem and one where the generated scene often implies lighting the product does not have. - Commercial-grade matting quality, which is where the hosted products have invested most and shows on the hardest ten percent of images. - Mobile capture and editing, which is how a lot of this category is actually used. - Marketplace-specific compliance, since each platform has its own image rules and they change. ### README must contain - That a soft alpha matte is produced rather than a binary mask, and why hair and glass require it - That compositing happens in linear space and edge colour is decontaminated - That shadow direction is matched to the product's own lighting rather than chosen - That the colour shift in the product region is measured and warned on - That low-quality mattes are routed to review rather than shipped ===== ARCHITECTURE.md ===== # Architecture · Pixelcut ## Stack | Part | Choice | Why | | --- | --- | --- | | Segmentation | A local matting model producing a soft alpha channel | a binary mask cannot represent hair, glass or motion blur | | Imaging | A library with correct colour management and high bit depth | eight-bit compositing in the wrong colour space visibly degrades edges | | Composition | Shadow synthesis and edge decontamination | a cut-out without these reads as fake immediately | | Batch | A worker queue with per-image isolation and a manifest | hundreds of images, and one failure must not cost the run | | Runtime | Python 3.12 | the ecosystem for imaging and models is here | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Matting | Producing and storing a soft alpha. | Any model producing alpha. A binary mask cannot do the hard cases at all. | | Compositing | Linear-space blending and decontamination. | Any implementation, provided the colour space handling is explicit. | | Shadow | Contact shadow synthesis matched to lighting. | Any synthesiser. Contradicting the product's lighting is the failure to avoid. | | Colour check | Measuring the product region shift. | Any metric, provided the product region is never adjusted. | | Batch | Isolation, review routing and the manifest. | Any queue, provided low-quality results are flagged rather than shipped. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `INPUT_DIR` · required · Source images, opened read only. - `OUTPUT_DIR` · required · Composites and manifests. Never the input directory. - `MATTE_MODEL` · required · The matting model. Its licence matters if this is commercial work. - `MATTE_QUALITY_THRESHOLD` · required · Below this an image goes to review rather than output. - `COLOUR_SHIFT_WARN_DELTA_E` · required · How far the product's colour may move before warning. Small, because listings cause returns. - `SHADOW_DEFAULT` · required · Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Pixelcut product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A local matting model producing a soft alpha channel, A library with correct colour management and high bit depth, Shadow synthesis and edge decontamination, A worker queue with per-image isolation and a manifest, Python 3.12. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. - A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. ===== MILESTONES.md ===== # Delivery milestones · Pixelcut Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · An alpha matte, not a mask Hair and transparent edges survive the cut-out. ### Steps 1. Produce and store a soft alpha Separately from any composite. It is the expensive step and it is reusable. Files: `src/matte.py` 2. Build a hard-case acceptance set Hair, glass, mesh, motion blur, similar-coloured background. Five real ones. Files: `fixtures/hard/` 3. Report low quality rather than guessing A bad matte silently composited is worse than a flagged one. Files: `src/quality.py` ### Done when - [ ] Hair, glass and mesh produce soft edges - [ ] Alpha is stored separately and reusable - [ ] A similar-coloured background is handled or reported - [ ] Matting works offline ### Watch out - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. ## M2 · Edges that do not carry the old background A cut-out placed on a new background has no halo from the old one. ### Steps 1. Decontaminate edge colour Partially covered pixels carry the old background otherwise. Files: `src/decontaminate.py` 2. Composite in linear space Convert, composite, convert back. Display-space compositing darkens edges. Files: `src/composite.py`, `tests/test_linear.py` 3. Preserve the colour profile An output with no profile is interpreted differently everywhere. Files: `src/colour.py` ### Done when - [ ] No colour fringe from a strong original background - [ ] Compositing matches a linear-space reference - [ ] Semi-transparent regions blend correctly - [ ] Output carries a correct colour profile ### Watch out - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. ## M3 · Shadows, because floating objects look wrong A product on a new background looks like it is resting on something. ### Steps 1. Synthesise a contact shadow from the alpha The lower boundary of the subject. Soft and short beats dramatic. Files: `src/shadow.py` 2. Match the product's own lighting A contradicting shadow is worse than none. Files: `src/lighting.py` 3. Store shadow parameters So a composition is reproducible rather than a one-off result. Files: `src/compositions.py` ### Done when - [ ] Products read as resting rather than floating - [ ] Shadow direction does not contradict the lighting - [ ] Shadow parameters reproduce the same result - [ ] No shadow is an explicit option ### Watch out - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. ## M4 · Measuring what you did to the colour You know whether the product still looks like the product. ### Steps 1. Measure the product region shift A stated metric, per composition, recorded. Files: `src/colour_check.py` 2. Warn above a threshold A listing image that misrepresents colour causes returns. Files: `src/colour_check.py` 3. Adjust only the background The product region is not yours to change. Files: `src/composite.py`, `tests/test_product_untouched.py` ### Done when - [ ] Colour shift is measured and reported - [ ] A large shift produces a warning - [ ] Background adjustment leaves product pixels unchanged - [ ] The threshold is configurable with a stated default ### Watch out - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ## M5 · Hundreds of images, unattended (production only) A folder processes overnight and you know exactly what happened. ### Steps 1. Isolate per-image failures One bad file must not end a three hundred image run. Files: `src/batch.py` 2. Route low-quality mattes to review Shipping a bad cut-out costs far more than flagging it. Files: `src/review.py` 3. Write a complete manifest Inputs, settings, outputs, flags. What makes the batch auditable. Files: `src/manifest.py` ### Done when - [ ] Three hundred images process unattended - [ ] Low-quality mattes go to review, not output - [ ] The manifest records settings and flags - [ ] Re-running produces identical outputs ### Watch out - A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. ===== OPERATIONS.md ===== # Operations · Pixelcut ## Backup Source images are the irreplaceable asset. Mattes are expensive to compute and worth keeping, since they are reusable across every background. Composites regenerate from both. ## Restore Restore sources and mattes, re-run, and compare against a kept output by checksum. Identical output proves the pipeline is deterministic and the restore complete. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring The review rate is the metric that matters. A rising proportion of images routed to review usually means the photography changed rather than the model degrading. ## Incident checklist A batch of listings shipped with visible halos means edge decontamination or the colour space is wrong, and both are reproducible on a single image from the hard set rather than needing the whole batch. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Hair, glass and mesh are confirmed to produce soft edges - [ ] No colour fringe is confirmed from a strong original background - [ ] Product pixels are confirmed unchanged by background adjustment - [ ] Low-quality mattes are confirmed routed to review - [ ] Re-running is confirmed to produce identical outputs ## Launch constraint Do not market omitted Pixelcut capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Source images, opened read only. INPUT_DIR=./input # Required. Composites and manifests. Never the input directory. OUTPUT_DIR=./output # Required. The matting model. Its licence matters if this is commercial work. MATTE_MODEL=./models/matting.onnx # Required. Below this an image goes to review rather than output. MATTE_QUALITY_THRESHOLD=0.75 # Required. How far the product's colour may move before warning. Small, because listings cause returns. COLOUR_SHIFT_WARN_DELTA_E=2.0 # Required. Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. SHADOW_DEFAULT=contact_soft
# Pixelcut · indie build A product image pipeline where the difficult parts are the edges: hair and transparent objects need a real alpha matte rather than a hard mask, a cut-out with no shadow looks pasted on, and a replaced background changes the colour the product appears to be, which for a listing is a returns problem. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Segmentation | A local matting model producing a soft alpha channel | a binary mask cannot represent hair, glass or motion blur | | Imaging | A library with correct colour management and high bit depth | eight-bit compositing in the wrong colour space visibly degrades edges | | Composition | Shadow synthesis and edge decontamination | a cut-out without these reads as fake immediately | | Batch | A worker queue with per-image isolation and a manifest | hundreds of images, and one failure must not cost the run | | Runtime | Python 3.12 | the ecosystem for imaging and models is here | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Python 3.12 or newer** · free - Why: Runs the pipeline and the model. - Get it: python.org or your package manager, then a virtual environment. - Verify: python3 --version prints 3.12 or higher - [ ] **A local matting model** · free for open models; needs a capable machine - Why: A binary segmentation model cannot represent hair, glass or motion blur, which is where every real product catalogue fails. - Get it: An open matting model with published weights you may use for your purpose. Check the licence covers commercial use if this is for a business. - Verify: It outputs a soft alpha channel rather than a binary mask - [ ] **An imaging library with colour management** · free - Why: Compositing in the wrong colour space darkens edges in a way that looks like a bad cut-out rather than a bug, so it is never diagnosed. - Get it: A library supporting high bit depth and explicit colour space conversion. - Verify: A round trip through linear space and back is lossless at high bit depth - [ ] **Five genuinely hard product images** · free - Why: Anything succeeds on a shoe against white. The acceptance set decides whether the pipeline is usable. - Get it: Photograph or find: hair or fur, a glass or transparent object, a mesh fabric, something with motion blur, and a product on a background close to its own colour. - Verify: All five exist and each fails a naive binary mask - [ ] **A colour reference in some shots** · the price of a colour card, or free with a known product - Why: Measuring how far a composite moved the product's colour requires knowing what the colour was, and eyeballing it does not work. - Get it: A colour card in a few reference shots, or at minimum a known product whose true colour you can state. - Verify: At least three images have a known reference colour ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. - mobile polish, hosted models, team assets, and API scale - frontier proprietary models - hosted GPU capacity - licensed training data - moderation and fast global delivery If one of those is essential to you, that is the reason to keep paying for Pixelcut, and the README should say so rather than pretend.
# Build brief · Pixelcut The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me batch background removal and product image preparation, run locally to replace Pixelcut. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Segmentation: A local matting model producing a soft alpha channel · a binary mask cannot represent hair, glass or motion blur - Imaging: A library with correct colour management and high bit depth · eight-bit compositing in the wrong colour space visibly degrades edges - Composition: Shadow synthesis and edge decontamination · a cut-out without these reads as fake immediately - Batch: A worker queue with per-image isolation and a manifest · hundreds of images, and one failure must not cost the run - Runtime: Python 3.12 · the ecosystem for imaging and models is here ### Data model (create this before Phase 1) - images(id, path, width, height, colour_profile, content_hash, imported_at) - mattes(image_id, alpha_path, model, refined, edge_quality) · alpha as a separate channel, kept - compositions(id, image_id, background_kind, background_ref, shadow_params_json, output_path, at) - reviews(composition_id, verdict, note, at) · verdict is accepted, needs_manual or rejected - batches(id, started_at, ended_at, input_count, succeeded, failed, manifest_path) - colour_checks(composition_id, delta_e, region) · how far the product's colour moved, measured rather than assumed - The alpha matte is stored separately from any composition, because the expensive step should be reused when the background changes. ### Phase 1 · An alpha matte, not a mask Build: Run a local matting model producing a soft alpha channel. Keep the alpha separately from any composite. Evaluate on the hard cases rather than on a product on a white background, which anything can do. Trap: Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. Done when: Hair, a glass object and a mesh fabric all produce plausible soft edges rather than a hard cut. The alpha is stored separately and is reusable across backgrounds. A product photographed on a similar-coloured background is handled or reported as low quality. Matting runs with networking disabled. Do not build yet: No refinement, backgrounds or batch. ### Phase 2 · Edges that do not carry the old background Build: Decontaminate edge colour so pixels partially covered by the subject do not carry the original background's colour. Composite in a linear colour space. Verify on a subject cut from a strongly coloured background. Trap: Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. Done when: A subject cut from a strongly coloured background shows no colour fringe on a new one, verified by inspecting edge pixels. Compositing happens in linear space, verified by comparing against a reference composite. Semi-transparent regions blend correctly. The output carries a correct colour profile. Do not build yet: No shadows, backgrounds or batch yet. ### Phase 3 · Shadows, because floating objects look wrong Build: Synthesise a contact shadow from the alpha's lower boundary, with configurable softness and direction. Detect the original lighting direction where possible and match it. Allow no shadow as a deliberate choice. Trap: A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. Done when: A product on a plain background reads as resting rather than floating. Shadow direction does not contradict the product's own lighting, checked across ten images. Shadow parameters are reproducible from stored values. No shadow is available as an explicit choice rather than the absence of a setting. Do not build yet: No batch or colour verification yet. ### Phase 4 · Measuring what you did to the colour Build: Measure the colour difference in the product region between the original and the composite. Warn above a threshold. Keep the product region unmodified by any background adjustment. Trap: Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. Done when: The colour difference in the product region is measured and reported per composition. A shift above the threshold produces a warning rather than a silent output. Background adjustments do not alter product pixels, verified by comparing the product region before and after. The threshold is configurable and its default is stated. Do not build yet: No batch or export yet. ### Phase 5 · Hundreds of images, unattended Build: A batch queue processing a directory with per-image isolation, output sizing for target placements, and a manifest recording every input, its settings and its outputs. Flag images needing manual attention rather than shipping them. Trap: A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. Done when: Three hundred images process unattended with per-image failure isolation. Low-quality mattes are routed to review rather than output, verified with a deliberately hard set. The manifest records inputs, settings, outputs and flags. Re-running with the same settings produces identical outputs, verified by checksum. Do not build yet: Nothing after this. ### Out of scope (and why) - Generative background creation, which is a different problem and one where the generated scene often implies lighting the product does not have. - Commercial-grade matting quality, which is where the hosted products have invested most and shows on the hardest ten percent of images. - Mobile capture and editing, which is how a lot of this category is actually used. - Marketplace-specific compliance, since each platform has its own image rules and they change. ### README must contain - That a soft alpha matte is produced rather than a binary mask, and why hair and glass require it - That compositing happens in linear space and edge colour is decontaminated - That shadow direction is matched to the product's own lighting rather than chosen - That the colour shift in the product region is measured and warned on - That low-quality mattes are routed to review rather than shipped
# Agent instructions · Pixelcut indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A local matting model producing a soft alpha channel, A library with correct colour management and high bit depth, Shadow synthesis and edge decontamination, A worker queue with per-image isolation and a manifest, Python 3.12. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only.
# Build plan · Pixelcut A product image pipeline where the difficult parts are the edges: hair and transparent objects need a real alpha matte rather than a hard mask, a cut-out with no shadow looks pasted on, and a replaced background changes the colour the product appears to be, which for a listing is a returns problem. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · An alpha matte, not a mask Hair and transparent edges survive the cut-out. ### Steps 1. Produce and store a soft alpha Separately from any composite. It is the expensive step and it is reusable. Files: `src/matte.py` 2. Build a hard-case acceptance set Hair, glass, mesh, motion blur, similar-coloured background. Five real ones. Files: `fixtures/hard/` 3. Report low quality rather than guessing A bad matte silently composited is worse than a flagged one. Files: `src/quality.py` ### Done when - [ ] Hair, glass and mesh produce soft edges - [ ] Alpha is stored separately and reusable - [ ] A similar-coloured background is handled or reported - [ ] Matting works offline ### Watch out - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. ## Phase 2 · Edges that do not carry the old background A cut-out placed on a new background has no halo from the old one. ### Steps 1. Decontaminate edge colour Partially covered pixels carry the old background otherwise. Files: `src/decontaminate.py` 2. Composite in linear space Convert, composite, convert back. Display-space compositing darkens edges. Files: `src/composite.py`, `tests/test_linear.py` 3. Preserve the colour profile An output with no profile is interpreted differently everywhere. Files: `src/colour.py` ### Done when - [ ] No colour fringe from a strong original background - [ ] Compositing matches a linear-space reference - [ ] Semi-transparent regions blend correctly - [ ] Output carries a correct colour profile ### Watch out - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. ## Phase 3 · Shadows, because floating objects look wrong A product on a new background looks like it is resting on something. ### Steps 1. Synthesise a contact shadow from the alpha The lower boundary of the subject. Soft and short beats dramatic. Files: `src/shadow.py` 2. Match the product's own lighting A contradicting shadow is worse than none. Files: `src/lighting.py` 3. Store shadow parameters So a composition is reproducible rather than a one-off result. Files: `src/compositions.py` ### Done when - [ ] Products read as resting rather than floating - [ ] Shadow direction does not contradict the lighting - [ ] Shadow parameters reproduce the same result - [ ] No shadow is an explicit option ### Watch out - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. ## Phase 4 · Measuring what you did to the colour You know whether the product still looks like the product. ### Steps 1. Measure the product region shift A stated metric, per composition, recorded. Files: `src/colour_check.py` 2. Warn above a threshold A listing image that misrepresents colour causes returns. Files: `src/colour_check.py` 3. Adjust only the background The product region is not yours to change. Files: `src/composite.py`, `tests/test_product_untouched.py` ### Done when - [ ] Colour shift is measured and reported - [ ] A large shift produces a warning - [ ] Background adjustment leaves product pixels unchanged - [ ] The threshold is configurable with a stated default ### Watch out - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ## Not in this build - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. ## After v1, if you want it - Consistent framing and margins across a catalogue, which matters more than any single image - Reflection synthesis for products on glossy surfaces - A manual refinement brush for the images that reach review
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Source images, opened read only. INPUT_DIR=./input # Required. Composites and manifests. Never the input directory. OUTPUT_DIR=./output # Required. The matting model. Its licence matters if this is commercial work. MATTE_MODEL=./models/matting.onnx # Required. Below this an image goes to review rather than output. MATTE_QUALITY_THRESHOLD=0.75 # Required. How far the product's colour may move before warning. Small, because listings cause returns. COLOUR_SHIFT_WARN_DELTA_E=2.0 # Required. Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. SHADOW_DEFAULT=contact_soft
# Pixelcut · product brief ## Problem The core loop is buildable, but a dependable replacement becomes a real weekend or multi-day project. For Pixelcut, batch-remove backgrounds, resize product images, and apply simple local templates. The hard boundary is mobile polish, hosted models, team assets, and api scale, plus frontier models, compute, and data. ## Product outcome A batch pipeline that cuts out hair and glass properly, places products on new backgrounds without a halo or a floating look, and tells you when it changed the colour the product appears to be. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - GPU-capable machine or user-supplied generation API - ComfyUI - model files with appropriate licenses - local storage ## Explicit non-goals for v1 - Generative background creation. - Commercial-grade matting on the hardest images. - Mobile capture and editing. - Marketplace-specific image compliance. - mobile polish, hosted models, team assets, and API scale - frontier proprietary models - hosted GPU capacity - licensed training data - moderation and fast global delivery ## Success criteria - Hair, glass and mesh are confirmed to produce soft edges - No colour fringe is confirmed from a strong original background - Product pixels are confirmed unchanged by background adjustment - Low-quality mattes are confirmed routed to review - Re-running is confirmed to produce identical outputs
# Build brief · Pixelcut The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me batch background removal and product image preparation, run locally to replace Pixelcut. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Segmentation: A local matting model producing a soft alpha channel · a binary mask cannot represent hair, glass or motion blur - Imaging: A library with correct colour management and high bit depth · eight-bit compositing in the wrong colour space visibly degrades edges - Composition: Shadow synthesis and edge decontamination · a cut-out without these reads as fake immediately - Batch: A worker queue with per-image isolation and a manifest · hundreds of images, and one failure must not cost the run - Runtime: Python 3.12 · the ecosystem for imaging and models is here ### Data model (create this before Phase 1) - images(id, path, width, height, colour_profile, content_hash, imported_at) - mattes(image_id, alpha_path, model, refined, edge_quality) · alpha as a separate channel, kept - compositions(id, image_id, background_kind, background_ref, shadow_params_json, output_path, at) - reviews(composition_id, verdict, note, at) · verdict is accepted, needs_manual or rejected - batches(id, started_at, ended_at, input_count, succeeded, failed, manifest_path) - colour_checks(composition_id, delta_e, region) · how far the product's colour moved, measured rather than assumed - The alpha matte is stored separately from any composition, because the expensive step should be reused when the background changes. ### Phase 1 · An alpha matte, not a mask Build: Run a local matting model producing a soft alpha channel. Keep the alpha separately from any composite. Evaluate on the hard cases rather than on a product on a white background, which anything can do. Trap: Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. Done when: Hair, a glass object and a mesh fabric all produce plausible soft edges rather than a hard cut. The alpha is stored separately and is reusable across backgrounds. A product photographed on a similar-coloured background is handled or reported as low quality. Matting runs with networking disabled. Do not build yet: No refinement, backgrounds or batch. ### Phase 2 · Edges that do not carry the old background Build: Decontaminate edge colour so pixels partially covered by the subject do not carry the original background's colour. Composite in a linear colour space. Verify on a subject cut from a strongly coloured background. Trap: Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. Done when: A subject cut from a strongly coloured background shows no colour fringe on a new one, verified by inspecting edge pixels. Compositing happens in linear space, verified by comparing against a reference composite. Semi-transparent regions blend correctly. The output carries a correct colour profile. Do not build yet: No shadows, backgrounds or batch yet. ### Phase 3 · Shadows, because floating objects look wrong Build: Synthesise a contact shadow from the alpha's lower boundary, with configurable softness and direction. Detect the original lighting direction where possible and match it. Allow no shadow as a deliberate choice. Trap: A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. Done when: A product on a plain background reads as resting rather than floating. Shadow direction does not contradict the product's own lighting, checked across ten images. Shadow parameters are reproducible from stored values. No shadow is available as an explicit choice rather than the absence of a setting. Do not build yet: No batch or colour verification yet. ### Phase 4 · Measuring what you did to the colour Build: Measure the colour difference in the product region between the original and the composite. Warn above a threshold. Keep the product region unmodified by any background adjustment. Trap: Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. Done when: The colour difference in the product region is measured and reported per composition. A shift above the threshold produces a warning rather than a silent output. Background adjustments do not alter product pixels, verified by comparing the product region before and after. The threshold is configurable and its default is stated. Do not build yet: No batch or export yet. ### Phase 5 · Hundreds of images, unattended Build: A batch queue processing a directory with per-image isolation, output sizing for target placements, and a manifest recording every input, its settings and its outputs. Flag images needing manual attention rather than shipping them. Trap: A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged. Done when: Three hundred images process unattended with per-image failure isolation. Low-quality mattes are routed to review rather than output, verified with a deliberately hard set. The manifest records inputs, settings, outputs and flags. Re-running with the same settings produces identical outputs, verified by checksum. Do not build yet: Nothing after this. ### Out of scope (and why) - Generative background creation, which is a different problem and one where the generated scene often implies lighting the product does not have. - Commercial-grade matting quality, which is where the hosted products have invested most and shows on the hardest ten percent of images. - Mobile capture and editing, which is how a lot of this category is actually used. - Marketplace-specific compliance, since each platform has its own image rules and they change. ### README must contain - That a soft alpha matte is produced rather than a binary mask, and why hair and glass require it - That compositing happens in linear space and edge colour is decontaminated - That shadow direction is matched to the product's own lighting rather than chosen - That the colour shift in the product region is measured and warned on - That low-quality mattes are routed to review rather than shipped
# Architecture · Pixelcut ## Stack | Part | Choice | Why | | --- | --- | --- | | Segmentation | A local matting model producing a soft alpha channel | a binary mask cannot represent hair, glass or motion blur | | Imaging | A library with correct colour management and high bit depth | eight-bit compositing in the wrong colour space visibly degrades edges | | Composition | Shadow synthesis and edge decontamination | a cut-out without these reads as fake immediately | | Batch | A worker queue with per-image isolation and a manifest | hundreds of images, and one failure must not cost the run | | Runtime | Python 3.12 | the ecosystem for imaging and models is here | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Matting | Producing and storing a soft alpha. | Any model producing alpha. A binary mask cannot do the hard cases at all. | | Compositing | Linear-space blending and decontamination. | Any implementation, provided the colour space handling is explicit. | | Shadow | Contact shadow synthesis matched to lighting. | Any synthesiser. Contradicting the product's lighting is the failure to avoid. | | Colour check | Measuring the product region shift. | Any metric, provided the product region is never adjusted. | | Batch | Isolation, review routing and the manifest. | Any queue, provided low-quality results are flagged rather than shipped. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `INPUT_DIR` · required · Source images, opened read only. - `OUTPUT_DIR` · required · Composites and manifests. Never the input directory. - `MATTE_MODEL` · required · The matting model. Its licence matters if this is commercial work. - `MATTE_QUALITY_THRESHOLD` · required · Below this an image goes to review rather than output. - `COLOUR_SHIFT_WARN_DELTA_E` · required · How far the product's colour may move before warning. Small, because listings cause returns. - `SHADOW_DEFAULT` · required · Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Pixelcut product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A local matting model producing a soft alpha channel, A library with correct colour management and high bit depth, Shadow synthesis and edge decontamination, A worker queue with per-image isolation and a manifest, Python 3.12. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. - A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged.
# Delivery milestones · Pixelcut Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · An alpha matte, not a mask Hair and transparent edges survive the cut-out. ### Steps 1. Produce and store a soft alpha Separately from any composite. It is the expensive step and it is reusable. Files: `src/matte.py` 2. Build a hard-case acceptance set Hair, glass, mesh, motion blur, similar-coloured background. Five real ones. Files: `fixtures/hard/` 3. Report low quality rather than guessing A bad matte silently composited is worse than a flagged one. Files: `src/quality.py` ### Done when - [ ] Hair, glass and mesh produce soft edges - [ ] Alpha is stored separately and reusable - [ ] A similar-coloured background is handled or reported - [ ] Matting works offline ### Watch out - Judging segmentation on a shoe photographed on white makes every model look excellent, and then hair, glass, mesh and motion blur all fail in production. Assemble the hard cases first and treat them as the acceptance set, because a binary mask will pass the easy ones and cannot represent the hard ones at all. ## M2 · Edges that do not carry the old background A cut-out placed on a new background has no halo from the old one. ### Steps 1. Decontaminate edge colour Partially covered pixels carry the old background otherwise. Files: `src/decontaminate.py` 2. Composite in linear space Convert, composite, convert back. Display-space compositing darkens edges. Files: `src/composite.py`, `tests/test_linear.py` 3. Preserve the colour profile An output with no profile is interpreted differently everywhere. Files: `src/colour.py` ### Done when - [ ] No colour fringe from a strong original background - [ ] Compositing matches a linear-space reference - [ ] Semi-transparent regions blend correctly - [ ] Output carries a correct colour profile ### Watch out - Compositing in the display colour space rather than a linear one produces edges that are visibly too dark, and the effect is subtle enough to look like a slightly bad cut-out rather than a colour management bug, so it never gets diagnosed. Convert to linear, composite, convert back. ## M3 · Shadows, because floating objects look wrong A product on a new background looks like it is resting on something. ### Steps 1. Synthesise a contact shadow from the alpha The lower boundary of the subject. Soft and short beats dramatic. Files: `src/shadow.py` 2. Match the product's own lighting A contradicting shadow is worse than none. Files: `src/lighting.py` 3. Store shadow parameters So a composition is reproducible rather than a one-off result. Files: `src/compositions.py` ### Done when - [ ] Products read as resting rather than floating - [ ] Shadow direction does not contradict the lighting - [ ] Shadow parameters reproduce the same result - [ ] No shadow is an explicit option ### Watch out - A shadow whose direction contradicts the lighting visible on the product itself looks worse than no shadow at all, because the viewer cannot say why the image is wrong but can see that it is. Derive the direction from the product's own highlights where you can, and default to a neutral contact shadow rather than a dramatic angled one. ## M4 · Measuring what you did to the colour You know whether the product still looks like the product. ### Steps 1. Measure the product region shift A stated metric, per composition, recorded. Files: `src/colour_check.py` 2. Warn above a threshold A listing image that misrepresents colour causes returns. Files: `src/colour_check.py` 3. Adjust only the background The product region is not yours to change. Files: `src/composite.py`, `tests/test_product_untouched.py` ### Done when - [ ] Colour shift is measured and reported - [ ] A large shift produces a warning - [ ] Background adjustment leaves product pixels unchanged - [ ] The threshold is configurable with a stated default ### Watch out - Adjusting brightness or white balance across the whole composite to make the product sit better on a new background changes the product's apparent colour, which for a clothing or paint listing produces returns and complaints that nobody traces back to the image pipeline. Measure the shift, warn on it, and apply adjustments to the background only. ## M5 · Hundreds of images, unattended (production only) A folder processes overnight and you know exactly what happened. ### Steps 1. Isolate per-image failures One bad file must not end a three hundred image run. Files: `src/batch.py` 2. Route low-quality mattes to review Shipping a bad cut-out costs far more than flagging it. Files: `src/review.py` 3. Write a complete manifest Inputs, settings, outputs, flags. What makes the batch auditable. Files: `src/manifest.py` ### Done when - [ ] Three hundred images process unattended - [ ] Low-quality mattes go to review, not output - [ ] The manifest records settings and flags - [ ] Re-running produces identical outputs ### Watch out - A batch that treats a poor matte as success ships a hundred listings with visibly bad cut-outs, and the cost of that is far higher than the cost of flagging thirty for review. Score every matte, route the low scores to a review queue, and make the manifest say how many were flagged.
# Operations · Pixelcut ## Backup Source images are the irreplaceable asset. Mattes are expensive to compute and worth keeping, since they are reusable across every background. Composites regenerate from both. ## Restore Restore sources and mattes, re-run, and compare against a kept output by checksum. Identical output proves the pipeline is deterministic and the restore complete. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring The review rate is the metric that matters. A rising proportion of images routed to review usually means the photography changed rather than the model degrading. ## Incident checklist A batch of listings shipped with visible halos means edge decontamination or the colour space is wrong, and both are reproducible on a single image from the hard set rather than needing the whole batch. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Hair, glass and mesh are confirmed to produce soft edges - [ ] No colour fringe is confirmed from a strong original background - [ ] Product pixels are confirmed unchanged by background adjustment - [ ] Low-quality mattes are confirmed routed to review - [ ] Re-running is confirmed to produce identical outputs ## Launch constraint Do not market omitted Pixelcut capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Source images, opened read only. INPUT_DIR=./input # Required. Composites and manifests. Never the input directory. OUTPUT_DIR=./output # Required. The matting model. Its licence matters if this is commercial work. MATTE_MODEL=./models/matting.onnx # Required. Below this an image goes to review rather than output. MATTE_QUALITY_THRESHOLD=0.75 # Required. How far the product's colour may move before warning. Small, because listings cause returns. COLOUR_SHIFT_WARN_DELTA_E=2.0 # Required. Neutral by default. A dramatic angled shadow contradicting the lighting looks worse than none. SHADOW_DEFAULT=contact_soft
$ choose a build depth, inspect the files, then open the complete pack in your agent
People still pay for Pixelcut because the product value is the model and compute fleet, not the prompt box around it. The recurring cost buys GPU procurement, model licensing, safety filters, queueing, storage, and rapid model replacement, not just the visible interface.
xmobile polish, hosted models, team assets, and API scale
xfrontier proprietary models
xhosted GPU capacity
xlicensed training data
xmoderation and fast global delivery
Don't feel like building it? These folks already made it free.
no votes, no pay-to-list · just what's real
Pixelcut pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| free | $0/workspace | $0/workspace | Limited background removal and upscaling with watermark-free exports; numeric monthly caps are not published. |
| pro | $10/workspace | $8/workspace | 600 AI credits/month, unlimited background removal/upscale, 3 seats included and 1,000 batch exports/month. |
| business | $30/workspace | $24/workspace | 3,600 AI credits/month at the base selection, 10 seats included and 2,000 batch exports/month; some tools allow up to 1,200 uses/day. |
free tierLimited background removal and upscaling; watermark-free exports; numeric recurring caps are not published.
billingmonthly + annual (-20%)
hidden costsCredits are shared across the workspace. Business price rises with the selected credit tier; third-party models can consume different numbers of credits. Included seats are 3 on Pro and 10 on Business.
verified 2026-08-14 · source ↗
Vibecode Pixelcut
Kinda. The core of Pixelcut is buildable in a weekend with the prompt on this page, but there are real gaps: mobile polish, hosted models, team assets, and API scale, frontier proprietary models. Read the honest list above before committing.
How much does Pixelcut cost?
Pixelcut costs about $10/month (Pro, checked 2026-08-14), which is $120 per year.
What do I lose by replacing Pixelcut?
Honestly: mobile polish, hosted models, team assets, and API scale; frontier proprietary models; hosted GPU capacity; licensed training data; moderation and fast global delivery. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Pixelcut?
Yes: chaiNNer (Build the background-removal and resize chain once, then throw a folder at it.) The prompt is for when you want it exactly your way.