retoucher / API_REFERENCE.md
esmaill1
Force lossless PNG output for API images to preserve full resolution
9131a7f
|
Raw
History Blame Contribute Delete
11.9 kB

A newer version of the Gradio SDK is available: 6.22.0

Upgrade

πŸͺ„ API Reference β€” ID Photo Retoucher

Base URL: https://esmailx51-retoucher.hf.space
Gradio API Prefix: /gradio_api
API Endpoint: /gradio_api/run/retouch
Interactive Docs: View on Hugging Face


Overview

The retoucher exposes its interface and programmatic prediction endpoints through Gradio.

Hugging Face Spaces Queue Requirement (Gradio 5):
Since this Space runs on ZeroGPU with queueing enabled, direct stateless HTTP POST requests (using raw requests or cURL) to the /gradio_api/run/retouch endpoint are blocked with a 404 Not Found error ("This API endpoint does not accept direct HTTP POST requests. Please join the queue to use this API.").

To consume the API programmatically, you must use the official client libraries (gradio_client in Python or @gradio/client in JavaScript/TypeScript) as shown in Section 1 and Section 3. The clients automatically handle the SSE queue handshake and state tracking. Raw HTTP/cURL calls will only work in local development environments where the queue is disabled.

Field Value
Endpoint (Local/No Queue) POST /gradio_api/run/retouch
Upload Endpoint (Local/No Queue) POST /gradio_api/upload
Queue Enabled (requests are queued)
GPU ZeroGPU A10G (allocated on-demand per request)
Max File Size No limit
Cold Start ~30–60s (first request after idle downloads model weights)

Parameters

# Name Type Default Range Description
1 image Image required β€” Input face photo (file path, URL, or base64)
2 strength float 0.6 0.0 – 1.0 Skin retouching intensity. 0 = no change, 1 = full GFPGAN restoration
3 undereye_strength float 0.5 0.0 – 1.0 Under-eye correction intensity. 0 = no correction, 1 = maximum brightening
4 crease_strength float 0.4 0.0 – 1.0 Crease/sag softening. Softens smile lines, marionette folds, double chins
5 jaw_tighten float 0.3 0.0 – 1.0 Jawline tightening. Gently warps/lifts sagging jowls inward
6 show_masks bool false β€” If true, returns a debug visualization with mask overlays

Returns

# Name Type Description
1 retouched_image Image The retouched face photo
2 debug_image Image | null Debug visualization (only if show_masks=true). Green = skin, Orange = under-eye, Blue = wrinkle zones

Usage Examples

1. Python β€” Gradio Client (Recommended)

The easiest way. Install with pip install gradio_client.

from gradio_client import Client

# Connect to the Space
client = Client("esmailx51/retoucher")

# Basic usage β€” just retouch with defaults
result = client.predict(
    "photo.jpg",       # local file path
    0.6,               # skin strength
    0.5,               # undereye strength
    0.4,               # crease strength
    0.3,               # jaw tighten
    False,             # show debug masks
    api_name="/retouch"
)

retouched_path = result[0]  # path to the retouched image
debug_path = result[1]      # None (since show_masks=False)
print(f"Retouched image saved to: {retouched_path}")

From a URL instead of a local file

from gradio_client import Client, handle_file

client = Client("esmailx51/retoucher")

result = client.predict(
    handle_file("https://example.com/face.jpg"),
    0.7, 0.5, 0.4, 0.3, False,
    api_name="/retouch"
)

Aggressive retouching (older subjects)

result = client.predict(
    "photo.jpg",
    0.8,    # strong skin smoothing
    0.7,    # strong undereye correction
    0.7,    # strong wrinkle reduction
    0.5,    # strong jaw tightening
    False,
    api_name="/retouch"
)

Minimal retouching (young subjects)

result = client.predict(
    "photo.jpg",
    0.3,    # light skin smoothing
    0.2,    # light undereye
    0.1,    # minimal wrinkle reduction
    0.0,    # no jaw tightening
    False,
    api_name="/retouch"
)

With debug masks

result = client.predict(
    "photo.jpg",
    0.6, 0.5, 0.4, 0.3,
    True,   # show debug masks
    api_name="/retouch"
)
retouched = result[0]
debug_vis = result[1]  # side-by-side: masks overlay | retouched result

2. Python β€” requests (Raw HTTP)

Local/No-Queue only: This raw HTTP request method will return a 404 / Please join the queue error on the hosted Hugging Face Space. It only works in local development environments where the Gradio queue is disabled. For hosted Spaces, you must use the gradio_client library (Section 1).

import requests
import json
from pathlib import Path

# In Gradio 5, endpoints are prefixed with /gradio_api
BASE_URL = "http://127.0.0.1:7860/gradio_api"

# Step 1: Upload the image to the local Gradio server
with open("photo.jpg", "rb") as f:
    upload_resp = requests.post(
        f"{BASE_URL}/upload",
        files={"files": ("photo.jpg", f, "image/jpeg")}
    )
    uploaded_files = upload_resp.json()
    file_path = uploaded_files[0]  # server-side temp path

# Step 2: Call the local API prediction endpoint (/run/retouch)
payload = {
    "data": [
        {"path": file_path, "meta": {"_type": "gradio.FileData"}},
        0.6,    # skin strength
        0.5,    # undereye strength
        0.4,    # crease strength
        0.3,    # jaw tighten
        False   # show masks
    ]
}

resp = requests.post(f"{BASE_URL}/run/retouch", json=payload)
result = resp.json()

# Step 3: Extract & download the result
# In Gradio 5, the direct response maps outputs to keys like "output" (or "data" fallback)
if "data" in result:
    retouched_url = result["data"][0]["url"]
else:
    retouched_url = result["output"]["url"]

img_data = requests.get(retouched_url).content
Path("retouched.jpg").write_bytes(img_data)
print("Saved retouched.jpg")

3. JavaScript / TypeScript

Install with npm install @gradio/client.

import { Client } from "@gradio/client";

const client = await Client.connect("esmailx51/retoucher");

const result = await client.predict("/retouch", {
    image: "https://example.com/face.jpg",  // URL or Blob
    strength: 0.6,
    undereye_strength: 0.5,
    crease_strength: 0.4,
    jaw_tighten: 0.3,
    show_masks: false,
});

console.log(result.data);
// [{ url: "https://...retouched.webp", ... }, null]

With a local file (Node.js)

import { Client, handle_file } from "@gradio/client";
import fs from "fs";

const client = await Client.connect("esmailx51/retoucher");

const result = await client.predict("/retouch", {
    image: handle_file("./photo.jpg"),
    strength: 0.6,
    undereye_strength: 0.5,
    crease_strength: 0.4,
    jaw_tighten: 0.3,
    show_masks: false,
});

// Download the retouched image
const imageUrl = result.data[0].url;
const response = await fetch(imageUrl);
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync("retouched.jpg", buffer);

Browser (Fetch from a file input)

import { Client } from "@gradio/client";

async function retouchPhoto(fileInput) {
    const client = await Client.connect("esmailx51/retoucher");
    const file = fileInput.files[0];

    const result = await client.predict("/retouch", {
        image: new Blob([await file.arrayBuffer()], { type: file.type }),
        strength: 0.6,
        undereye_strength: 0.5,
        crease_strength: 0.4,
        jaw_tighten: 0.3,
        show_masks: false,
    });

    // Display the result
    const imgUrl = result.data[0].url;
    document.getElementById("result").src = imgUrl;
}

4. cURL

Local/No-Queue only: This cURL method will return a 404 / Please join the queue error on the hosted Hugging Face Space. It only works in local development environments where the Gradio queue is disabled. For hosted Spaces, you must use the official client libraries (Section 1 & 3).

# Step 1: Upload the image (pointing to local Gradio 5 API prefix)
FILE_PATH=$(curl -s -X POST \
  "http://127.0.0.1:7860/gradio_api/upload" \
  -F "files=@photo.jpg" \
  | jq -r '.[0]')

# Step 2: Call the API prediction endpoint
curl -s -X POST \
  "http://127.0.0.1:7860/gradio_api/run/retouch" \
  -H "Content-Type: application/json" \
  -d "{
    \"data\": [
      {\"path\": \"$FILE_PATH\", \"meta\": {\"_type\": \"gradio.FileData\"}},
      0.6,
      0.5,
      0.4,
      0.3,
      false
    ]
  }" | jq -r '.output.url'

Batch Processing (Python)

Process multiple images in sequence:

from gradio_client import Client
from pathlib import Path

client = Client("esmailx51/retoucher")
input_dir = Path("./input_photos")
output_dir = Path("./retouched")
output_dir.mkdir(exist_ok=True)

for img_path in input_dir.glob("*.jpg"):
    print(f"Processing {img_path.name}...")
    result = client.predict(
        str(img_path),
        0.6, 0.5, 0.4, 0.3, False,
        api_name="/retouch"
    )
    # Copy result to output directory
    retouched = Path(result[0])
    retouched.rename(output_dir / img_path.name)
    print(f"  β†’ Saved to {output_dir / img_path.name}")

Integration Example: Flask Backend

from flask import Flask, request, send_file
from gradio_client import Client
import tempfile, shutil

app = Flask(__name__)
gr_client = Client("esmailx51/retoucher")

@app.route("/retouch", methods=["POST"])
def retouch():
    # Save uploaded file
    photo = request.files["photo"]
    strength = float(request.form.get("strength", 0.6))
    undereye = float(request.form.get("undereye", 0.5))
    creases = float(request.form.get("creases", 0.4))
    jaw = float(request.form.get("jaw", 0.3))

    with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
        photo.save(tmp.name)
        result = gr_client.predict(
            tmp.name,
            strength, undereye, creases, jaw, False,
            api_name="/retouch"
        )
    return send_file(result[0], mimetype="image/webp")

if __name__ == "__main__":
    app.run(port=5000)

Error Handling

from gradio_client import Client
from gradio_client.exceptions import AppError

client = Client("esmailx51/retoucher")

try:
    result = client.predict(
        "photo.jpg", 0.6, 0.5, 0.4, 0.3, False,
        api_name="/retouch"
    )
except AppError as e:
    if "No face detected" in str(e):
        print("No face found in the image")
    elif "queue is full" in str(e):
        print("Server is busy, try again later")
    else:
        print(f"API error: {e}")
except ConnectionError:
    print("Space is sleeping β€” the first request wakes it up (~60s)")

Tuning Guide

Goal strength undereye creases jaw
Natural / Minimal 0.3 0.2 0.1 0.0
Balanced (default) 0.6 0.5 0.4 0.3
Aggressive (older subjects) 0.8 0.7 0.7 0.5
Skin only (no anti-aging) 0.6 0.0 0.0 0.0
Under-eye only 0.0 0.7 0.0 0.0

Rate Limits & Notes

  • Cold start: If the Space has been idle, the first request takes 30–60 seconds (model download + loading). Subsequent requests are fast (5–10s on GPU).
  • Queue: Requests are queued. If the Space is busy, your request will wait in line.
  • GPU timeout: ZeroGPU allocates GPU per-request. Very large images may time out.
  • Output format: Retouched images are returned as PNG by default to maintain high-resolution lossless quality.
  • No face detected: If no face is found, the original image is returned unchanged.