A Python CLI, FastAPI, and Web UI tool for preparing product images for marketplace cards.
The tool can batch-process product images, resize them relative to a canvas or template, optionally remove the background with neural network models, and place the processed product image onto a marketplace-style card.
The project can be used in four ways:
- as a local Python CLI tool
- as a FastAPI backend service
- through a simple browser-based web interface
- inside Docker for reproducible execution
v0.20 — Simple Web UI
- Batch processing of product images
- Support for
.jpg,.jpeg,.png, and.webp - Product resizing relative to a canvas or template
- Custom canvas size support
- Custom template/background support
- Product positioning with
--offset-xand--offset-y - Relative product scaling with
--product-scale - Optional background removal with neural network models
- Background removal backend selection with
--bg-backend - Background removal model selection with
--bg-model - Reuse of rembg sessions for faster batch processing
- Correct handling of transparent RGBA images using alpha masks
- Controlled parallel batch processing with
--workers - Progress output during batch processing
- JSON processing report export
- Total file count, worker count, failed files, and processing time in reports
- Friendly errors for missing or empty input folders
- Broken image skipping without stopping the whole batch
- High-quality resize with LANCZOS
- Optional
--no-upscalemode for small images - Docker support for reproducible local execution
- Docker volume support for input/output files
- Docker model cache volume for background removal models
- FastAPI backend for HTTP-based image processing
- Swagger UI documentation at
/docs - Health check endpoint with
GET /health - Image processing endpoint with
POST /process - Simple browser-based web interface at
/ui - Web form for configuring image processing parameters
- Request payload preview before processing
- JSON result display after processing
- Web UI powered by the existing FastAPI backend
- Support for running the CLI, API, and Web UI locally or inside Docker
- Python — core programming language
- Pillow — image loading, resizing, composition, and saving
- rembg — neural network based background removal
- ONNX Runtime — CPU inference backend used by background removal models
- argparse — command-line interface
- FastAPI — HTTP API backend
- Pydantic — request validation and API data models
- Uvicorn — ASGI server for running the API and Web UI
- HTML — simple web interface structure
- CSS — basic web interface styling
- JavaScript — browser-side request handling with
fetch - concurrent.futures — controlled parallel batch processing
- JSON — processing reports
- Docker — reproducible containerized execution
- PowerShell — local command examples and performance measurement
.jpg.jpeg.png.webp
product_card_processor/
├── app/
│ ├── __init__.py
│ ├── api.py
│ ├── background_removal.py
│ ├── cli.py
│ ├── config.py
│ ├── image_io.py
│ ├── processor.py
│ └── transforms.py
├── data/
│ ├── input/
│ ├── output/
│ └── template.png
├── docs/
│ └── assets/
│ ├── demo_frames/
│ │ └── demo_1.gif
│ └── screenshots/
│ ├── web-ui.png
│ └── web-ui_1.png
├── tools/
│ └── make_gif.py
├── web/
│ └── index.html
├── Dockerfile
├── .dockerignore
├── .gitignore
├── requirements.txt
└── README.md
The project can be run in two main environments:
- locally with Python
- inside Docker
For local execution, install the project dependencies:
pip install -r requirements.txtThe project uses rembg with CPU support for optional background removal.
Background removal models are downloaded automatically on first use. Large models may require additional disk space and may take longer to download. For example, birefnet-general is significantly heavier than the default u2net model.
For Docker execution, local Python dependencies are not required.
Build the Docker image:
docker build -t product-card-processor .Then run the tool inside a container using mounted input and output folders.
Docker is the recommended option if you want reproducible execution without manually configuring a local Python environment.
Process images from the default input folder and save results to the default output folder:
python -m app.cli --input data/input --output data/outputShow all available CLI options:
python -m app.cli --helpThe project includes a FastAPI backend that exposes the image processing pipeline through HTTP endpoints.
The API uses the same ImageProcessor core as the CLI version, so the processing logic is shared between the command-line interface, the API, and the Web UI.
Start the API server:
uvicorn app.api:app --reloadThe API will be available at:
http://127.0.0.1:8000
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Basic service information |
GET |
/health |
Health check endpoint |
GET |
/ui |
Browser-based Web UI |
POST |
/echo |
Test endpoint for JSON request bodies |
POST |
/process |
Run product image processing |
FastAPI automatically generates interactive API documentation.
Open:
http://127.0.0.1:8000/docs
The Swagger UI can be used to test API endpoints directly in the browser.
Example request body for POST /process without background removal:
{
"input_folder": "data/input",
"output_folder": "data/output_api",
"canvas_width": 1080,
"canvas_height": 1440,
"allow_upscale": true,
"template_path": "data/template.png",
"offset_x": 0,
"offset_y": 0,
"product_scale": 0.6,
"remove_bg": false,
"bg_backend": "rembg",
"bg_model": "u2net",
"workers": 2,
"save_report": true,
"report_path": "data/output_api/report.json"
}Example request body for POST /process with background removal:
{
"input_folder": "data/input",
"output_folder": "data/output_api_bg",
"canvas_width": 1080,
"canvas_height": 1440,
"allow_upscale": true,
"template_path": "data/template.png",
"offset_x": 0,
"offset_y": 0,
"product_scale": 0.6,
"remove_bg": true,
"bg_backend": "rembg",
"bg_model": "u2net",
"workers": 1,
"save_report": true,
"report_path": "data/output_api_bg/report.json"
}Example response:
{
"status": "completed",
"report": {
"processed_count": 11,
"failed_count": 0,
"failed_files": [],
"total_files": 11,
"settings": {
"input_folder": "data\\input",
"output_folder": "data\\output_api_bg",
"canvas_width": 1080,
"canvas_height": 1440,
"allow_upscale": true,
"template_path": "data\\template.png",
"offset_x": 0,
"offset_y": 0,
"product_scale": 0.6,
"remove_bg": true,
"bg_backend": "rembg",
"bg_model": "u2net",
"workers": 1
},
"processing_time_seconds": 10.027,
"report_path": "data\\output_api_bg\\report.json"
}
}The project includes a simple browser-based web interface for running image processing through the FastAPI backend.
The Web UI is available at:
http://127.0.0.1:8000/ui
The interface allows users to configure the main processing parameters without using the command line or Swagger UI.
It supports:
- input and output folder paths
- canvas width and height
- template path
- product scale
- X and Y offsets
- background removal settings
- background removal model selection
- worker count
- report path
- request payload preview
- processing result display
Start the FastAPI server:
uvicorn app.api:app --reloadOpen the Web UI:
http://127.0.0.1:8000/ui
Fill in the processing settings and click:
Process images
The web page sends a JSON request to:
POST /process
and displays the response report directly in the browser.
Browser Web UI
↓
fetch("/process")
↓
FastAPI backend
↓
ImageProcessor
↓
processed images + JSON report
The tool supports controlled parallel batch processing with a configurable number of worker threads.
Use one worker for regular sequential processing:
python -m app.cli --template data/template.png --product-scale 0.6 --workers 1Use multiple workers for parallel processing:
python -m app.cli --template data/template.png --product-scale 0.6 --workers 4Parallel processing can improve performance on large image batches, especially when processing many files without heavy background removal.
When background removal is enabled, using too many workers may increase memory usage because neural network inference is more resource-intensive.
Recommended starting points:
| Mode | Recommended workers |
|---|---|
| Resize/template processing only | 2–8 |
Background removal with u2net |
1–4 |
Background removal with isnet-general-use |
1–2 |
Background removal with birefnet-general |
1–2 |
If background removal is enabled with more than two workers, the tool prints a warning about possible memory usage increase.
Use a custom canvas size:
python -m app.cli --canvas-width 1200 --canvas-height 1600Use a custom template/background:
python -m app.cli --template data/template.pngWhen a template is provided, the output image size is based on the template size.
Resize the product relative to the canvas or template size:
python -m app.cli --product-scale 0.8Use a template with relative product scaling:
python -m app.cli --template data/template.png --product-scale 0.6Move the product from the center using pixel offsets:
python -m app.cli --template data/template.png --offset-y -100python -m app.cli --template data/template.png --offset-x 50 --offset-y -120Disable upscaling for small images:
python -m app.cli --no-upscaleRemove product background before placing it on the canvas or template:
python -m app.cli --remove-bg --template data/template.png --product-scale 0.6Remove product background with the selected backend:
python -m app.cli --remove-bg --bg-backend rembg --template data/template.png --product-scale 0.6Select a background removal model:
python -m app.cli --remove-bg --bg-model u2net --template data/template.png --product-scale 0.6python -m app.cli --remove-bg --bg-model isnet-general-use --template data/template.png --product-scale 0.6python -m app.cli --remove-bg --bg-model birefnet-general --template data/template.png --product-scale 0.6| Model | Description | Notes |
|---|---|---|
u2net |
Default general-purpose background removal model | Good lightweight baseline |
isnet-general-use |
General-purpose object segmentation model | Best balance in the current tests |
birefnet-general |
Larger general-purpose segmentation model | Best quality in the current tests, but much heavier and slower |
For most regular product images:
python -m app.cli --remove-bg --bg-model isnet-general-use --template data/template.png --product-scale 0.6 --workers 2For faster lightweight processing:
python -m app.cli --remove-bg --bg-model u2net --template data/template.png --product-scale 0.6 --workers 4For best quality on difficult product images:
python -m app.cli --remove-bg --bg-model birefnet-general --template data/template.png --product-scale 0.6 --workers 1The tool can save a JSON report with processing statistics, selected settings, failed files, total file count, worker count, and total processing time.
Save a report to the default path:
python -m app.cli --remove-bg --bg-model isnet-general-use --template data/template.png --product-scale 0.6 --save-reportSave a report to a custom path:
python -m app.cli --remove-bg --bg-model isnet-general-use --template data/template.png --product-scale 0.6 --save-report --report-path reports/test_report.jsonExample report structure:
{
"processed_count": 11,
"failed_count": 1,
"failed_files": [
{
"image_path": "data\\input\\broken.jpg",
"reason": "cannot identify image file"
}
],
"total_files": 12,
"settings": {
"input_folder": "data\\input",
"output_folder": "data\\output",
"canvas_width": 1080,
"canvas_height": 1440,
"allow_upscale": true,
"template_path": "data\\template.png",
"offset_x": 0,
"offset_y": 0,
"product_scale": 0.6,
"remove_bg": true,
"bg_backend": "rembg",
"bg_model": "isnet-general-use",
"workers": 4
},
"processing_time_seconds": 17.45
}The project can be run inside Docker, so it does not require a local Python virtual environment to process images.
Docker support was added in:
v0.18 — Docker support
From the project root, run:
docker build -t product-card-processor .This command builds a Docker image named:
product-card-processor
To check that the container starts correctly:
docker run --rm product-card-processorBy default, the container runs:
python -m app.cli --helpSo it should print the available CLI arguments.
Input images should be placed in:
data/input
The processed images will be saved to:
data/output
PowerShell command:
docker run --rm `
-v "${PWD}\data:/app/data" `
product-card-processor `
python -m app.cli --input data/input --output data/output --template data/template.png --product-scale 0.6 --workers 2 --save-reportExplanation:
-v "${PWD}\data:/app/data"
mounts the local data folder into the container.
This allows Docker to read images from the local folder:
data/input
and save results back to:
data/output
Background removal is supported through rembg.
For background removal, it is recommended to start with:
--workers 1
because background removal is more memory-intensive than regular resizing and composition.
PowerShell command:
docker run --rm `
-v "${PWD}\data:/app/data" `
-v product_card_models:/models `
-e U2NET_HOME=/models `
product-card-processor `
python -m app.cli --input data/input --output data/output_bg --template data/template.png --product-scale 0.6 --remove-bg --bg-model u2net --workers 1 --save-report --report-path data/output_bg/report.jsonThe processed images will be saved to:
data/output_bg
The JSON report will be saved to:
data/output_bg/report.json
The FastAPI backend and Web UI can also be started inside Docker.
Run API and Web UI without background removal model cache:
docker run --rm `
-p 8000:8000 `
-v "${PWD}\data:/app/data" `
product-card-processor `
uvicorn app.api:app --host 0.0.0.0 --port 8000Open Swagger UI:
http://127.0.0.1:8000/docs
Open Web UI:
http://127.0.0.1:8000/ui
Run API and Web UI with background removal model cache:
docker run --rm `
-p 8000:8000 `
-v "${PWD}\data:/app/data" `
-v product_card_models:/models `
-e U2NET_HOME=/models `
product-card-processor `
uvicorn app.api:app --host 0.0.0.0 --port 8000This command starts the FastAPI backend and serves the Web UI inside Docker. The background removal models are cached between container runs.
The Docker background removal command uses a Docker volume:
-v product_card_models:/modelsand an environment variable:
-e U2NET_HOME=/modelsThis is needed so that the rembg model is downloaded only once and reused between container runs.
Without this volume, the model could be downloaded again when the container is recreated.
The first run with background removal may take longer because the model needs to be downloaded:
u2net.onnx
After that, repeated runs should start faster.
Example report created after Docker processing with background removal:
{
"processed_count": 11,
"failed_count": 0,
"failed_files": [],
"total_files": 11,
"settings": {
"input_folder": "data/input",
"output_folder": "data/output_bg",
"canvas_width": 1080,
"canvas_height": 1440,
"allow_upscale": true,
"template_path": "data/template.png",
"offset_x": 0,
"offset_y": 0,
"product_scale": 0.6,
"remove_bg": true,
"bg_backend": "rembg",
"bg_model": "u2net",
"workers": 1
},
"processing_time_seconds": 89.569
}Build image:
docker build -t product-card-processor .Run CLI help:
docker run --rm product-card-processorRun CLI without background removal:
docker run --rm `
-v "${PWD}\data:/app/data" `
product-card-processor `
python -m app.cli --input data/input --output data/output --template data/template.png --product-scale 0.6 --workers 2 --save-reportRun CLI with background removal:
docker run --rm `
-v "${PWD}\data:/app/data" `
-v product_card_models:/models `
-e U2NET_HOME=/models `
product-card-processor `
python -m app.cli --input data/input --output data/output_bg --template data/template.png --product-scale 0.6 --remove-bg --bg-model u2net --workers 1 --save-report --report-path data/output_bg/report.jsonRun FastAPI backend and Web UI:
docker run --rm `
-p 8000:8000 `
-v "${PWD}\data:/app/data" `
product-card-processor `
uvicorn app.api:app --host 0.0.0.0 --port 8000Run FastAPI backend and Web UI with background removal model cache:
docker run --rm `
-p 8000:8000 `
-v "${PWD}\data:/app/data" `
-v product_card_models:/models `
-e U2NET_HOME=/models `
product-card-processor `
uvicorn app.api:app --host 0.0.0.0 --port 8000If Docker build fails because of a network timeout while installing Python packages, try running the build again:
docker build -t product-card-processor .If the issue persists, check the Dockerfile and make sure pip uses increased timeout and retries.
Example:
RUN pip install --no-cache-dir --timeout=120 --retries=10 --progress-bar off -r requirements.txtIf the build fails with a message like:
cannot allocate memory
increase Docker Desktop resources:
Docker Desktop → Settings → Resources
Recommended starting point:
Memory: 4 GB or more
Swap: 2 GB or more
When running FastAPI inside Docker, use:
uvicorn app.api:app --host 0.0.0.0 --port 8000The --host 0.0.0.0 option is required so the API can be accessed from outside the container.
Also make sure the port is published:
-p 8000:8000Then open:
http://127.0.0.1:8000/ui
Background removal uses neural network inference and is much heavier than regular image resizing.
Start with:
--workers 1
Then increase worker count carefully if the system has enough memory.
To compare background removal models, process the same input folder with different models and save the results into separate output folders.
python -m app.cli --remove-bg --bg-model u2net --template data/template.png --product-scale 0.6 --output data/output/u2netpython -m app.cli --remove-bg --bg-model isnet-general-use --template data/template.png --product-scale 0.6 --output data/output/isnet-general-usepython -m app.cli --remove-bg --bg-model birefnet-general --template data/template.png --product-scale 0.6 --output data/output/birefnet-generalProcessing time was measured locally with PowerShell Measure-Command.
Example:
Measure-Command { python -m app.cli --remove-bg --bg-model u2net --template data/template.png --product-scale 0.6 --output data/output/u2net }The measurements below are based on the current local test set and environment. Actual results may vary depending on hardware, image resolution, number of files, selected worker count, selected background removal model, and whether the model has already been downloaded.
| Model | Total time, seconds | Relative speed | Notes |
|---|---|---|---|
u2net |
6.85 | 1.0x | Fastest tested model |
isnet-general-use |
12.89 | 1.9x slower than u2net |
Slower, but better quality |
birefnet-general |
185.24 | 27.0x slower than u2net |
Best quality, but very slow and heavy |
The models were compared manually using real automotive product images.
The main criteria were:
- object edge quality
- preservation of small details
- handling of holes and inner cutouts
- shadow and reflection removal
- processing speed
- model size and disk space usage
- stability on different product types
The following models were tested:
u2netisnet-general-usebirefnet-general
u2net works as a solid baseline model.
It handles simple product shapes reasonably well, but it shows weaker results on more difficult geometry, especially inner cutouts, holes, and complex object boundaries.
It was the fastest model in the current test run.
Recommended role:
- lightweight baseline
- fastest tested option
- useful when speed and model size matter more than maximum quality
isnet-general-use produced cleaner masks than u2net in the tested examples.
It handled several product images more accurately and provided a better balance between quality and practical usability.
It was slower than u2net, but still much faster than birefnet-general.
Recommended role:
- best balanced option
- good candidate for the default model
- suitable for regular batch processing
birefnet-general produced the best masks in the tested examples.
It handled complex product geometry and inner cutouts better than the other tested models. However, it is significantly heavier and much slower.
In the current test run, it was about 27 times slower than u2net.
Recommended role:
- best quality option
- useful for difficult product images
- suitable when quality is more important than speed and model size
| Model | Quality | Speed | Practicality | Notes |
|---|---|---|---|---|
u2net |
Medium | Fast | High | Good lightweight baseline, weaker on difficult shapes |
isnet-general-use |
High | Medium | High | Best balance between quality and usability |
birefnet-general |
Very high | Very slow | Medium | Best quality, but heavy and much slower |
The README demo GIF can be regenerated from two prepared frames:
python tools/make_gif.pyInput frames:
docs/assets/demo_frames/before.jpg
docs/assets/demo_frames/after.jpg
Expected output:
docs/assets/demo_frames/demo_1.gif
The GIF generation script keeps the original image proportions and fits frames into a shared canvas instead of stretching them.
v0.1— project structurev0.2— single image processingv0.3— batch image processingv0.4— centered product card generationv0.5— configurable CLI argumentsv0.6— friendly error handlingv0.7— improved resize behavior and--no-upscalev0.8— template/background supportv0.9— pixel offsets from centerv0.10— relative product scalingv0.11— background removal with rembg backendv0.12— rembg session reuse for faster batch processingv0.13— background removal model selectionv0.14— background removal model comparisonv0.15— JSON processing reportv0.16— README demo GIFv0.17— controlled parallel batch processingv0.18— Docker supportv0.19— FastAPI backendv0.20— simple web interface
- Add automated tests
- Add recursive folder processing
- Add configuration presets


