{"id":"9ad9c870-9d9c-4965-909f-67d819da721b","entityType":"agent","slug":"clawhub-guoxh-smart-photo-editor","name":"Smart Photo Editor","canonicalUrl":"https://www.xpersona.co/agent/clawhub-guoxh-smart-photo-editor","canonicalPath":"/agent/clawhub-guoxh-smart-photo-editor","generatedAt":"2026-10-10T13:32:38.426Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":null},"description":"AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. Skill: Smart Photo Editor Owner: guoxh Summary: AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. Tags: ai:1.0.0, editing:1.0.0, imagemagick:1.0.0, latest:1.5.2, object-removal:1.0.0, opencv:1.0.0, photo:1.0.0, restoration:1.0.0 Version history: v1.5.2 | 2026-07-24T09:21:21.128Z | auto No changes detected in this version. - Version numbe","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.5K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17dsvj6tbs3jy3xgjps2tqzn183jx3e:smart-photo-editor","sourceUrl":"https://clawhub.ai/guoxh/smart-photo-editor","homepage":"https://clawhub.ai/guoxh/skills/smart-photo-editor","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/guoxh/smart-photo-editor","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/guoxh/skills/smart-photo-editor","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. Skill: Smart Photo Editor Own"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":null},"stars":null,"forks":null,"downloads":1500,"packageName":null,"latestVersion":"1.5.2","tractionLabel":"1.5K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T10:18:26.872Z","lastCrawledAt":"2026-10-10T10:18:26.872Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T10:18:26.872Z","lastVerifiedAt":null,"highlights":[{"version":"1.5.2","createdAt":"2026-07-24T09:21:21.128Z","changelog":"No changes detected in this version. - Version number updated to 1.5.2, but no file or documentation changes were made from the previous release.","fileCount":10,"zipByteSize":64096},{"version":"1.5.1","createdAt":"2026-07-24T09:14:59.218Z","changelog":"Republish to update latest tag. Changes since 1.4.1: --position/--scale for replace-scene; R2 large-file upload with graceful data-URI fallback; portable #!/usr/bin/env python3 shebang; removed all hardcoded personal paths/URLs; documented Seedream dependency.","fileCount":10,"zipByteSize":63982},{"version":"1.5.0","createdAt":"2026-07-24T09:10:13.845Z","changelog":"New: --position/--scale for replace-scene; R2 large-file upload with graceful data-URI fallback; portable #!/usr/bin/env python3 shebang; removed all hardcoded personal paths/URLs; documented Seedream dependency.","fileCount":10,"zipByteSize":64102},{"version":"1.4.2","createdAt":"2026-07-24T09:08:59.891Z","changelog":"**1.5.0 is a major update improving compatibility and simplifying usage.** - Switched all scripts to a portable `#!/usr/bin/env python3` shebang — no longer hardcoded to a specific venv path. - Clarified which features require only OpenCV/ImageMagick and which need the Seedream skill, making AI features and open-source features clearly separable. - Improved documentation: feature availability, dependency checks, and installation steps are now clearer and more user-friendly. - Removed redundant or outdated documentation files (`skill-card.md`), and updated all feature and policy references for easier onboarding. - Scripts now gracefully skip optional features when dependencies are missing, instead of failing outright.","fileCount":10,"zipByteSize":64030},{"version":"1.4.1","createdAt":"2026-07-14T23:38:40.559Z","changelog":"Version 1.4.1 - Expanded trigger keyword list to support more user intents and Chinese-language terms (e.g., remove person, 换背景, 美颜, 自动裁剪). - Removed deprecated documentation file: skill-card.md. - Minor updates to documentation structure and examples for improved clarity. - Updated version and metadata in SKILL.md.","fileCount":10,"zipByteSize":61214},{"version":"1.4.0","createdAt":"2026-07-14T14:35:31.095Z","changelog":"smart-photo-editor v1.4.0 - Added support for the new \"replace-scene\" task, using Seedream as the default and erroring with guidance if the AI model is unavailable. - Updated tool selection policy documentation (in SKILL.md) to describe \"replace-scene\" behavior and clarify default tool logic. - Removed redundant documentation file (skill-card.md). - Other internal improvements and documentation updates for clarity.","fileCount":10,"zipByteSize":60963},{"version":"1.3.3","createdAt":"2026-06-13T13:46:20.428Z","changelog":"Seedream-first remove-object auto-routing; fix stale OpenCV keyword routing; document semantic-vs-deterministic tool policy; keep inpaint.py guidance for known-geometry cases.","fileCount":10,"zipByteSize":52062},{"version":"1.3.0","createdAt":"2026-06-11T01:12:15.225Z","changelog":"Version 1.3.0 – Major Update - Added new scripts: `edit.py`, `exif_utils.py`, `portrait.py`, and `smart_crop.py`, significantly expanding editing and enhancement capabilities, including portrait retouching and smart cropping. - Introduced EXIF metadata preservation and reading support (piexif, exif dependencies now documented). - Enhanced OpenCV-based operations to include denoising, sharpening, gamma/brighness/contrast adjust, and portrait-specific edits. - Updated documentation to detail new features, dependencies, and usage examples. - Removed obsolete file: `skill-card.md`.","fileCount":10,"zipByteSize":40517}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17dsvj6tbs3jy3xgjps2tqzn183jx3e:smart-photo-editor","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T13:32:38.423Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-guoxh-smart-photo-editor/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":null},"readme":"Skill: Smart Photo Editor\n\nOwner: guoxh\n\nSummary: AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nTags: ai:1.0.0, editing:1.0.0, imagemagick:1.0.0, latest:1.5.2, object-removal:1.0.0, opencv:1.0.0, photo:1.0.0, restoration:1.0.0\n\nVersion history:\n\nv1.5.2 | 2026-07-24T09:21:21.128Z | auto\n\nNo changes detected in this version.\n\n- Version number updated to 1.5.2, but no file or documentation changes were made from the previous release.\n\nv1.5.1 | 2026-07-24T09:14:59.218Z | user\n\nRepublish to update latest tag. Changes since 1.4.1: --position/--scale for replace-scene; R2 large-file upload with graceful data-URI fallback; portable #!/usr/bin/env python3 shebang; removed all hardcoded personal paths/URLs; documented Seedream dependency.\n\nv1.5.0 | 2026-07-24T09:10:13.845Z | user\n\nNew: --position/--scale for replace-scene; R2 large-file upload with graceful data-URI fallback; portable #!/usr/bin/env python3 shebang; removed all hardcoded personal paths/URLs; documented Seedream dependency.\n\nv1.4.2 | 2026-07-24T09:08:59.891Z | auto\n\n**1.5.0 is a major update improving compatibility and simplifying usage.**\n\n- Switched all scripts to a portable `#!/usr/bin/env python3` shebang — no longer hardcoded to a specific venv path.\n- Clarified which features require only OpenCV/ImageMagick and which need the Seedream skill, making AI features and open-source features clearly separable.\n- Improved documentation: feature availability, dependency checks, and installation steps are now clearer and more user-friendly.\n- Removed redundant or outdated documentation files (`skill-card.md`), and updated all feature and policy references for easier onboarding.\n- Scripts now gracefully skip optional features when dependencies are missing, instead of failing outright.\n\nv1.4.1 | 2026-07-14T23:38:40.559Z | auto\n\nVersion 1.4.1\n\n- Expanded trigger keyword list to support more user intents and Chinese-language terms (e.g., remove person, 换背景, 美颜, 自动裁剪).\n- Removed deprecated documentation file: skill-card.md.\n- Minor updates to documentation structure and examples for improved clarity.\n- Updated version and metadata in SKILL.md.\n\nv1.4.0 | 2026-07-14T14:35:31.095Z | auto\n\nsmart-photo-editor v1.4.0\n\n- Added support for the new \"replace-scene\" task, using Seedream as the default and erroring with guidance if the AI model is unavailable.\n- Updated tool selection policy documentation (in SKILL.md) to describe \"replace-scene\" behavior and clarify default tool logic.\n- Removed redundant documentation file (skill-card.md).\n- Other internal improvements and documentation updates for clarity.\n\nv1.3.3 | 2026-06-13T13:46:20.428Z | user\n\nSeedream-first remove-object auto-routing; fix stale OpenCV keyword routing; document semantic-vs-deterministic tool policy; keep inpaint.py guidance for known-geometry cases.\n\nv1.3.0 | 2026-06-11T01:12:15.225Z | auto\n\nVersion 1.3.0 – Major Update\n\n- Added new scripts: `edit.py`, `exif_utils.py`, `portrait.py`, and `smart_crop.py`, significantly expanding editing and enhancement capabilities, including portrait retouching and smart cropping.\n- Introduced EXIF metadata preservation and reading support (piexif, exif dependencies now documented).\n- Enhanced OpenCV-based operations to include denoising, sharpening, gamma/brighness/contrast adjust, and portrait-specific edits.\n- Updated documentation to detail new features, dependencies, and usage examples.\n- Removed obsolete file: `skill-card.md`.\n\nv1.1.0 | 2026-06-09T14:26:52.425Z | user\n\nMajor inpaint.py enhancement: added diagonal line removal, rectangle region removal with feathered edges, multi-spot batch mode, multi-line batch mode, JSON batch configuration, algorithm selection (NS/Telea), coordinate clipping, comprehensive error handling, and detailed help with examples\n\nv1.0.3 | 2026-06-09T13:52:41.576Z | user\n\nAdded link to official VolcEngine Ark documentation and setup notes for Seedream model configuration\n\nv1.0.2 | 2026-06-09T13:44:54.069Z | user\n\nCorrected dependency description: Seedream requires VolcEngine Ark API access (not exclusively Agent Plan)\n\nv1.0.1 | 2026-06-09T13:39:49.428Z | user\n\nUpdated Dependency Status section to be generic for public users; added installation instructions for each dependency\n\nv1.0.0 | 2026-06-09T10:54:19.533Z | user\n\nInitial release: AI-powered photo editing skill with smart object removal, background removal, old photo restoration, and basic image editing tools. Combines Seedream AI, ImageMagick, and OpenCV with automatic fallback and large image handling.\n\nArchive index:\n\nArchive v1.5.2: 10 files, 64096 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (86796b), scripts/exif_utils.py (13253b), scripts/inpaint.py (21020b), scripts/portrait.py (28801b), scripts/remove_bg.sh (2903b), scripts/smart_crop.py (19750b), skill-card.md (2569b), SKILL.md (41534b)\n\nFile v1.5.2:SKILL.md\n\n---\nname: smart-photo-editor\nlicense: MIT\ndescription: |\n  AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nmetadata:\n  author: Team\n  version: \"1.5.1\"\n  category: ai/image-editing\n  compatibility: Requires Node.js 18+ and network access to VolcEngine Ark API (with Seedream model enabled) for AI features.\n---\n\n# Smart Photo Editor Skill\n\nAI-powered photo editing and restoration skill for OpenClaw. Unifies Seedream (AI edits), ImageMagick (basic edits), and OpenCV (programmatic fixes) into one intuitive workflow.\n\n## Overview\n\nAll-in-one intelligent photo editing skill - automatically selects the best tool for each image processing task.\n\n✨ **Key Advantages:**\n- ✅ **Smart Tool Selection** - Automatically chooses Seedream / ImageMagick / OpenCV based on task\n- ✅ **Unified Interface** - All operations use the same calling pattern\n- ✅ **Bilingual Support** - Optimized prompts for both Chinese and English contexts\n- ✅ **Automatic Fallback** - Switches to backup tools if primary tool fails\n- ✅ **Large Image Auto-Handling** - Avoids \"image too large\" API errors\n\n## Feature Availability\n\nThis skill provides two tiers of functionality:\n\n### ✅ Works out of the box (no extra dependencies)\n\nThese features only require ImageMagick and/or OpenCV (both widely available on Linux/macOS):\n\n- **Resize / Crop / Smart-crop** — dimension changes, aspect-ratio-preserving scaling\n- **Color adjustment** — brightness, contrast, saturation, grayscale\n- **Perspective correction** — 4-point skew/warp correction\n- **Smart compression** — quality targeting, binary-search for target file size\n- **HDR tonemapping** — log/bilateral/shadow/highlight recovery\n- **Background removal (basic)** — solid-color background removal via ImageMagick\n- **Geometric inpainting** — wire/line/rect removal with known coordinates (`inpaint.py`)\n\n### 🔒 Requires Seedream skill (AI features)\n\nThese features require the `byted-ark-seedream-skill` (VolcEngine Ark Agent Plan, managed skill):\n\n- **Object removal (natural language)** — remove objects described in text (people, vehicles, watermarks)\n- **Old photo restoration** — AI scratch/dust/fading repair\n- **Scene replacement (`replace-scene`)** — put subject into a new scene via multi-reference fusion\n- **Background removal (AI)** — rembg-based, or Seedream-based for complex edges\n\n> **Note:** The `byted-ark-seedream-skill` is an OpenClaw managed skill that requires a VolcEngine Ark account with the Seedream model enabled. Install with `openclaw skills install byted-ark-seedream-skill`.\n\n---\n\n## Trigger Conditions\n\nActivates automatically when users mention keywords like:\n- photo editing, edit image, retouch, smart photo edit\n- remove object, delete object, erase, remove person, remove watermark, remove logo, 去除, 消除\n- remove background, background removal, cutout, 抠图, 换背景\n- restore, fix, old photo restoration, repair, 修复老照片, 老照片修复\n- portrait retouching, portrait edit, smooth skin, whiten teeth, enhance eyes, remove blemish, red eye, 美颜, 人像精修, 红眼\n- replace scene, change scene, put subject in, 换场景, 多图融合\n- color adjustment, color correction, color grading, brightness, 调色, 色彩调整\n- crop, resize, compress, auto crop, smart crop, 裁剪, 自动裁剪, 智能裁剪\n- perspective, fix skew, flatten, perspective correct, 透视矫正, 视角矫正\n- hdr, tonemap, highlight recovery, shadow recovery, 高动态, 阴影增强\n- sharpen, denoise, 锐化, 降噪\n\n---\n\n## Tool Selection Policy\n\nThe skill mixes three classes of tool. Picking the right one for each task is\nwhat makes the unified entry-point useful, so the routing is explicit:\n\n**Use Seedream first for semantic / generative edits.**\n- Object removal in complex scenes (people, vehicles, watermarks, signs)\n- Old-photo restoration (scratches, fading, color loss)\n- Background replacement / scene swap\n- Subjective enhancement: “make this look better / natural / cinematic”\n- Edits where the model must infer missing visual content\n- Natural-language requests, especially in Chinese\n\nFor these, Seedream is the value-add. OpenCV/ImageMagick can’t compete on\nquality, and a deterministic tool can’t “invent” plausible content.\n\n**Use deterministic tools first for mechanical edits.**\n- Resize, crop, format conversion\n- Compression / quality targeting\n- Brightness, contrast, saturation, gamma adjustments\n- Geometric inpainting when coordinates are known (wires, dust spots,\n  exact rectangles — call `inpaint.py` directly)\n- Batch operations where reproducibility matters\n\nFor these, Seedream would be slower, costlier, and less predictable.\n\n**Encoded policy (auto mode):**\n```text\nsemantic edit / restoration / object removal       → Seedream first; deterministic fallback\nmechanical edit / resize / crop / compress / color → deterministic tools first\nuser explicitly asks for AI / natural restoration  → Seedream\nuser explicitly forces a tool with --tool ...      → honored verbatim\n```\n\n**Per-task defaults (`--tool auto`):**\n\n| Task | Default | Notes |\n|------|---------|-------|\n| `remove-object` | **Seedream** | OpenCV branch only fires when Seedream is unavailable; redirects to `inpaint.py` for known-geometry cases |\n| `restore` | **Seedream** | Seedream-only operation by design |\n| `remove-background` | **rembg** | ImageMagick fallback for solid-color backgrounds when rembg is missing |\n| `resize` / `crop` / `color-adjust` | **OpenCV/ImageMagick** | Deterministic, instant, free |\n| `smart-compress` | **OpenCV** | Content-aware quality + format selection |\n| `perspective-correct` | **OpenCV** | Document/whiteboard correction |\n| `hdr-tonemap` | **OpenCV** | All four modes (auto / bilateral / log / shadows) are deterministic |\n| `replace-scene` | **Seedream** | AI-only; no deterministic fallback (would produce poor results). If Seedream is unavailable, returns error directing user to install the Seedream skill. |\n\nOverride with `--tool seedream | opencv | imagemagick | rembg`.\n\n---\n\n## Installation & Dependencies\n\n### Standard Installation Path\n`~/.openclaw/skills/smart-photo-editor/`\n\n### Python Interpreter\nAll Python scripts (`scripts/*.py`) use a portable `#!/usr/bin/env python3` shebang.\n\nYou can run them directly:\n\n```bash\n./scripts/edit.py --help\n```\n\nOr explicitly with your Python of choice (e.g. a virtualenv where you have\ninstalled the dependencies below):\n\n```bash\npython3 scripts/edit.py --help\n```\n\n**Make sure the Python interpreter you use has the required dependencies**\n(OpenCV, Pillow, NumPy). Optional deps (`piexif`, `exif`, `rembg`) add extra\nfeatures; the skill will gracefully skip those features if they are missing.\n\n```bash\n# Sanity check — required deps\\python3 -c \"import cv2, numpy, PIL; print('core deps ok')\"\n\n# Sanity check — full deps (includes optional rembg/piexif/exif)\npython3 -c \"import cv2, numpy, PIL, piexif, exif, rembg; print('all deps ok')\"\n```\n\n### Required & Optional Dependencies\n| Dependency | Required | Purpose | Installation |\n|------------|----------|---------|--------------|\n| **byted-ark-seedream-skill** | ✅ Required | AI object removal, old photo restoration, image-to-image editing | Requires VolcEngine Ark API access. Follow [official setup guide](https://www.volcengine.com/docs/82379/2375486) to enable Seedream model access |\n| **imagemagick** | ✅ Required | Basic image editing (resize, crop, format conversion, color adjustments) | `sudo apt install imagemagick` (Debian/Ubuntu) or `brew install imagemagick` (macOS) |\n| **opencv-python-headless** | ✅ Required | Wire removal, spot removal, image resizing | `pip install opencv-python-headless` |\n| **rembg** | ⚠️ Optional | AI-powered background removal (better results for complex scenes) | `pip install rembg` |\n| **piexif** | ⚠️ Optional | EXIF metadata preservation during edits | `pip install piexif` |\n| **exif** | ⚠️ Optional | Extended EXIF tag reading | `pip install exif` |\n\n### Install Optional Dependencies\n```bash\nsource ~/.openclaw/venv-clawd/bin/activate\npip install rembg piexif exif\n```\n\n### Cloudflare R2 Upload (Large Reference Images)\n\nWhen a reference image (subject or scene image) exceeds **1.5 MB**, the skill can upload it to Cloudflare R2 instead of embedding it as a base64 data URI. This avoids hitting Seedream API payload size limits.\n\n**R2 is optional.** Without configuration, large images fall back to base64 data URI (which may fail for very large files due to CLI argument limits).\n\n**To enable R2 upload, deploy your own Cloudflare Worker:**\n\n1. Create a Cloudflare R2 bucket and a Worker that accepts PUT requests (see the [Cloudflare R2 documentation](https://developers.cloudflare.com/r2/))\n2. Set the following environment variables:\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `SEEDREAM_UPLOAD_TOKEN` | ✅ Yes | Bearer token for your R2 upload worker. |\n| `SEEDREAM_UPLOAD_WORKER_URL` | ✅ Yes | Your worker URL, e.g. `https://your-worker.your-subdomain.workers.dev`. |\n\n```bash\n# Add to your shell profile or ~/.openclaw/.env\nexport SEEDREAM_UPLOAD_TOKEN=\"your-token-here\"\nexport SEEDREAM_UPLOAD_WORKER_URL=\"https://your-worker.your-subdomain.workers.dev\"\n```\n\nWithout both variables, large images gracefully fall back to the data URI path (works for most cases; may hit CLI arg limits for very large multi-image batches).\n\n### VolcEngine Ark Setup\nFor AI editing features (object removal, photo restoration), ensure:\n1. You have a VolcEngine Ark account with API access\n2. The Seedream (豆包生图) model is enabled for your account\n3. Your OpenClaw configuration has valid VolcEngine API credentials\n\nSee the [official VolcEngine Ark documentation](https://www.volcengine.com/docs/82379/2375486) for detailed setup instructions.\n\n---\n\n## Core Features & Implementation\n\n### 1. Object Removal\n**Primary Tool:** Seedream Image-to-Image  \n**Fallback Tool:** OpenCV Inpainting (small scratches/lines)\n\n**Usage:**\n```bash\n# AI method (recommended) - complex scenes\nimage_generate \\\n  model=\"byted-ark-seedream-skill\" \\\n  mode=\"image-to-image\" \\\n  image=\"/path/to/photo.jpg\" \\\n  reference_strength=0.85 \\\n  prompt=\"Remove the [object description] located at [location description]. Restore the seamless texture, keep everything else exactly the same.\"\n```\n\n**OpenCV method** — simple lines/minor imperfections:\n```bash\n# Remove horizontal wire\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type wire --y 760 --thickness 10\n\n# Remove diagonal/angled line (supports any angle)\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n\n# Remove rectangular region (watermarks, logos, text)\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n\n# Remove multiple sensor dust spots in one command\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Remove multiple lines in one command\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type batch --batch tasks.json\n\n# JSON config example (tasks.json):\n# {\n#   \"operations\": [\n#     {\"type\": \"spot\", \"x\": 100, \"y\": 150, \"radius\": 8},\n#     {\"type\": \"spot\", \"x\": 200, \"y\": 300, \"radius\": 10},\n#     {\"type\": \"wire\", \"y\": 500, \"thickness\": 5},\n#     {\"type\": \"rect\", \"x\": 50, \"y\": 50, \"w\": 200, \"h\": 50, \"feather\": 10}\n#   ]\n# }\n```\n\n**Algorithm Selection:**\n- `ns` (Navier-Stokes) - Better for textures and larger regions (default for wire/line)\n- `telea` (Telea) - Faster, better for small regions (default for spot)\nUse `--algo ns` or `--algo telea` to override the default selection.\n\n**Prompt Optimization Examples:**\n- \"Remove the black power cable at the bottom of the image\" → \"Remove the thin black horizontal power cable at the bottom 20% of the image. Restore the mountain texture seamlessly, keep everything else exactly the same.\"\n- \"Remove the pedestrian in the middle\" → \"Remove the pedestrian in the center. Fill with matching background texture naturally.\"\n\n---\n\n### 2. Background Removal\n**Primary Tool:** rembg (AI)  \n**Fallback Tool:** ImageMagick (inline – solid color backgrounds)\n\n**Usage:**\n```bash\n# rembg AI method (complex backgrounds)\nrembg i input.jpg output.png\n\n# ImageMagick method (solid color backgrounds)\n./scripts/remove_bg.sh input.png output.png 20 \"#FFFFFF\"\n```\n\n---\n\n### 3. Old Photo Restoration\n**Primary Tool:** Seedream Image-to-Image\n\n**Usage:**\n```bash\nimage_generate \\\n  model=\"byted-ark-seedream-skill\" \\\n  mode=\"image-to-image\" \\\n  image=\"/path/to/old_photo.jpg\" \\\n  reference_strength=0.7 \\\n  prompt=\"Restore this old photo. Remove all scratches, dust spots, and damage. Enhance clarity and contrast. Restore natural, vivid colors while preserving the original photo's character. Do not change the composition or subjects.\"\n```\n\n---\n\n### 4. Basic Editing\n**Primary Tool:** ImageMagick + OpenCV\n\n**Common Commands:**\n```bash\n# Resize\nconvert input.jpg -resize 1920x1920\\> output.jpg\n\n# Crop\nconvert input.jpg -crop 800x600+100+50 output.jpg\n\n# Format conversion + compression\nconvert input.png -quality 85 output.webp\n\n# Color adjustment\nconvert input.jpg -brightness-contrast 10x5 output.jpg  # Brighter, higher contrast\nconvert input.jpg -modulate 100,130,100 output.jpg      # Increase saturation\nconvert input.jpg -grayscale Rec709Luma output.jpg      # Convert to B&W\n```\n\n**OpenCV Operations (inpaint.py):**\n```bash\n# Denoise (reduce noise in low-light photos)\n./scripts/inpaint.py input.jpg output.jpg --type denoise --strength 15\n\n# Sharpen (enhance edges and focus)\n./scripts/inpaint.py input.jpg output.jpg --type sharpen --strength 1.5\n\n# Brightness/contrast/gamma adjustment\n./scripts/inpaint.py input.jpg output.jpg --type adjust --brightness 15 --contrast 10 --gamma 0.9\n```\n\n### 5. Portrait Retouching\n**Primary Tool:** OpenCV (face detection + image processing)  \n**Dependencies:** `opencv-python-headless` (already required)\n\nPortrait retouching provides face-aware enhancements for portrait photography:\n- **Skin smoothing** — bilateral filter preserves edges while softening skin\n- **Red-eye removal** — detects and corrects flash red-eye\n- **Teeth whitening** — targets lower-face region, preserves surrounding\n- **Eye enhancement** — brightens and sharpens eyes\n- **Face brightness/contrast** — applies adjustments only to detected face\n- **Blemish removal** — removes small spots using inpainting\n- **Skin tone enhancement** — warm, healthy color correction\n\n```bash\n# Skin smoothing only\n./scripts/portrait.py input.jpg output.jpg --smooth 3\n\n# All enhancements (balanced)\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle preset (conservative)\n./scripts/portrait.py input.jpg output.jpg --subtle\n\n# Custom combination\n./scripts/portrait.py input.jpg output.jpg \\\n  --smooth 2 --enhance-eyes --whiten-teeth 0.3 --brightness 10\n\n# JSON output\n./scripts/portrait.py input.jpg output.jpg --all --json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--smooth` | Skin smoothing strength 1-10 |\n| `--denoise` | Denoise strength 1-30 |\n| `--red-eye` | Remove flash red-eye |\n| `--whiten-teeth` | Teeth whitening strength 0.1-0.8 |\n| `--enhance-eyes` | Brighten/sharpen eyes |\n| `--brightness` | Face brightness -100 to 100 |\n| `--contrast` | Face contrast -100 to 100 |\n| `--gamma` | Face gamma correction 0.1-3.0 |\n| `--sharpen` | Sharpening strength 0.5-3.0 |\n| `--blemish-removal` | Remove small blemishes |\n| `--skin-tone` | Warm skin tone enhancement |\n| `--all` | Apply all enhancements (balanced) |\n| `--subtle` | Conservative all enhancements |\n| `--no-auto-detect` | Skip face/eye detection |\n| `--no-exif` | Do not preserve EXIF |\n| `--json` | JSON output mode |\n\n### 6. EXIF Preservation\n**Automatic:** All write operations preserve EXIF metadata by default  \n**Tool:** `scripts/exif_utils.py` — standalone EXIF utility\n\nAll editing scripts automatically preserve EXIF metadata from input to output.\n\n```bash\n# Read EXIF from an image\n./scripts/exif_utils.py read photo.jpg\n\n# Strip EXIF from an image\n./scripts/exif_utils.py strip photo.jpg -o output.jpg\n\n# Copy EXIF from one image to another\n./scripts/exif_utils.py copy source.jpg dest.jpg\n```\n\nSupported tags: Make, Model, DateTime, Orientation, Exposure Time, F-Number, ISO, Focal Length, Lens Model, and more.\n\n---\n\n### 7. Smart Crop (Auto-Crop)\n**Primary Tool:** OpenCV saliency detection + optional GrabCut refinement  \n**Dependencies:** `opencv-python-headless` (already required)\n\nAutomatically detects the most \"interesting\" region in an image and crops to it.\nUses OpenCV's StaticSaliencyFineGrained algorithm by default, with spectral and edge-based fallbacks.\n\n```bash\n# Auto-crop to salient region with default padding\n./scripts/smart_crop.py input.jpg output.jpg\n\n# Crop to specific aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9\n\n# Crop to 4:3 with 10% margin around subject\n./scripts/smart_crop.py input.jpg output.jpg --aspect 4/3 --padding 0.1\n\n# Resize to exact dimensions after smart crop\n./scripts/smart_crop.py input.jpg output.jpg --width 800 --height 600\n\n# Use GrabCut refinement for cleaner boundaries\n./scripts/smart_crop.py input.jpg output.jpg --grabcut\n\n# Generate debug saliency map overlay\n./scripts/smart_crop.py input.jpg output.jpg --debug\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--aspect`, `-a` | Aspect ratio (e.g. `16/9`, `4/3`, `1/1`) |\n| `--width`, `-w` | Target width in pixels |\n| `--height`, `-H` | Target height in pixels |\n| `--padding`, `-p` | Margin around subject (0.0-0.5, default 0.05) |\n| `--threshold`, `-t` | Saliency threshold 0.05-0.95 (default 0.3) |\n| `--algorithm` | `auto` / `finegrained` / `spectral` / `edge` |\n| `--grabcut`, `-g` | Use GrabCut to refine crop boundary |\n| `--debug`, `-d` | Generate debug saliency map overlay |\n\n### 8. Perspective Correction\n**Primary Tool:** OpenCV (auto-detection + warpPerspective)\n\nAuto-detects document/sheet borders using edge detection + contour analysis and corrects perspective distortion. Also supports manual corner specification.\n\n```bash\n# Auto-detect and correct\n./scripts/edit.py --task perspective-correct --image doc.jpg --output flat.jpg\n\n# With manual corners (top-left, top-right, bottom-right, bottom-left)\n./scripts/edit.py --task perspective-correct --image doc.jpg --output flat.jpg \\\n  --corners \"100,50,600,50,600,800,100,800\"\n\n# Batch JSON\n./scripts/edit.py --json < tasks.json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--corners` | 4 points as CSV `x1,y1,x2,y2,x3,y3,x4,y4` (TL,TR,BR,BL). Omit for auto-detection |\n\n**Algorithm:** Adaptive threshold → contour detection → largest 4-point quadrilateral → perspective transform.\n\n---\n\n### 9. Intelligent Compression\n**Primary Tool:** OpenCV (content analysis + format-specific encoding)\n\nContent-aware image compression using entropy, edge density, and color variance analysis to auto-select the best format and quality.\n\n```bash\n# Auto-select best format and quality\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.jpg\n\n# Target file size (auto binary-searches quality)\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.jpg --target-kb 200\n\n# Force WebP with specific quality\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.webp \\\n  --format webp --quality 85\n\n# Batch JSON\n./scripts/edit.py --json < tasks.json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--target-kb` | Target output size in KB (enables binary-search for optimal quality) |\n| `--format` | Force output: `jpeg` | `png` | `webp` |\n\n**Auto-decision logic:**\n- **JPEG** — high entropy (>6.5) + dense edges → complex photographic content\n- **PNG** — low color variance (<500) + low edges → flat graphics/screenshots; or alpha channel detected\n- **Quality** — auto-selected based on entropy (65–92) unless `--target-kb` is specified\n\n---\n\n### 10. HDR / Tonemapping\n**Primary Tool:** OpenCV (multi-scale bilateral decomposition + CLAHE)\n\nHDR-style tone mapping to enhance dynamic range on single images. Uses bilateral filter decomposition to separate illumination from detail, compress the illumination layer's dynamic range, then recombine — producing natural-looking highlight/shadow recovery.\n\n```bash\n# Auto mode (default — picks best method based on image analysis)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg\n\n# Bilateral mode — detail-preserving compression (best for most photos)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode bilateral --strength 1.2\n\n# Log mode — fast global compression (good for screenshots/graphics)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode log --gamma 2.2\n\n# Shadows mode — lighten dark regions (backlit photos)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode shadows --strength 1.5\n\n# Highlight mode — compress blown highlights\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode highlight --strength 1.2\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--mode` | auto / bilateral / log / shadows / highlight (default: auto) |\n| `--strength` | Enhancement strength 0.1-2.0 (default: 1.0) |\n| `--gamma` | Gamma value for log mode (default: 2.2) |\n\n**Algorithm:** Bilateral filter decomposition — base (illumination) layer compressed with S-curve; detail layer preserved and boosted; adaptive saturation adjustment.\n\n---\n\n### 11. Scene Replacement\n**Primary Tool:** Seedream multi-reference image fusion (AI-only, no deterministic fallback)\n\nPlace a subject (portrait / pet / product) into a new scene using Seedream's\nmulti-reference image fusion. Wraps 豆包 app's \"多图融合\" + \"换场景\" feature.\n\n**Requires:** the `byted-ark-seedream-skill` (this task is AI-only; an\nOpenCV/ImageMagick fallback would produce poor results and is intentionally\nomitted).\n\n**Usage:**\n```bash\n# 1) Subject + scene image (most common)\n./scripts/edit.py --task replace-scene \\\n    --subject photo.jpg --scene cafe.png --output out.jpg\n\n# 2) Subject + text-only scene description\n./scripts/edit.py --task replace-scene \\\n    --subject pet.jpg --scene-prompt \"阳光下的草地\" --output out.jpg\n\n# 3) Product photo into lifestyle scene\n./scripts/edit.py --task replace-scene \\\n    --subject product.png --scene lifestyle.jpg --output out.jpg \\\n    --subject-type product\n\n# 4) Custom prompt override (full artistic control)\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene beach.jpg --output out.jpg \\\n    --prompt \"把人物放在黄昏海边沙滩，长发随风，光线偏暖，景深虚化\"\n\n# 5) Subject in center, close-up framing\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene studio.jpg --output out.jpg \\\n    --position center --scale close\n\n# 6) Full-body shot, subject on the right\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene beach.jpg --output out.jpg \\\n    --position right --scale full\n\n# 7) JSON batch with position/scale\n./scripts/edit.py --json < tasks.json\n```\n\n**Argument table:**\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `--subject` / `-S` | path | ✅ | — | Subject image (portrait / pet / product) |\n| `--scene` | path | ⚠️ one of | — | Target scene image |\n| `--scene-prompt` | string | ⚠️ one of | — | Target scene text description (used if no scene image) |\n| `--subject-type` | enum | ❌ | `auto` | `auto` / `portrait` / `pet` / `product`. Selects prompt template + reference_strength. |\n| `--prompt` / `-p` | string | ❌ | (from template) | Override the default prompt |\n| `--reference-strength` | float | ❌ | 0.85 (portrait/pet) / 0.90 (product) | How strongly Seedream must preserve the subject. Higher = stricter. |\n| `--watermark` | flag | ❌ | `false` | Add Seedream watermark. Default OFF (most uses are product / academic). |\n| `--position` | enum | ❌ | `center` | Horizontal subject placement: `left` / `center` / `right`. Feeds into the scene-prompt as positional hint.\n| `--scale` | enum | ❌ | `medium` | Subject framing: `close` (特写) / `medium` (中景) / `full` (全身). Feeds into the scene-prompt as framing hint.\n| `--output-format` | enum | ❌ | follow subject | `jpeg` / `png` / `webp` |\n| `--output` / `-o` | path | ❌ | auto | Output path |\n\n**Validation rules:**\n- `--subject` is required.\n- **Exactly one** of `--scene` / `--scene-prompt` is required (both → error).\n- If `--scene-prompt` is given, it must be at least 3 characters.\n- Subject image is auto-resized to 2048px max side (existing API limit helper).\n\n**Subject-type auto-detection:**\nWhen `--subject-type auto` is passed (default), the skill uses two heuristics:\n1. **Filename keyword** — `pet/cat/dog/...` → `pet`; `portrait/selfie/face/...` → `portrait`; `product/item/bottle/...` → `product`\n2. **Corner solidity check** — if all 4 corners are within 15 RGB units, classified as `product` (typical product shot on flat backdrop)\n\nIf neither heuristic matches, falls back to `portrait` (most common case).\nFor certainty, always pass `--subject-type` explicitly.\n\n**JSON batch format:**\n```json\n{\n  \"operations\": [\n    {\"task\": \"replace-scene\", \"subject\": \"p1.jpg\", \"scene\": \"office.jpg\",\n     \"output\": \"p1_office.jpg\", \"subject-type\": \"portrait\"},\n    {\"task\": \"replace-scene\", \"subject\": \"p2.jpg\", \"scene-prompt\": \"雪山日落\",\n     \"output\": \"p2_mountain.jpg\", \"subject-type\": \"portrait\"},\n    {\"task\": \"replace-scene\", \"subject\": \"shoe.png\", \"scene\": \"running_track.jpg\",\n     \"output\": \"shoe_track.jpg\", \"subject-type\": \"product\", \"reference-strength\": 0.9}\n  ]\n}\n```\n\n**JSON batch key naming:** JSON keys use **underscores** (Python identifier\nconvention): `scene_prompt`, `subject_type`, `reference_strength`, etc. The\nCLI flags use dashes (`--scene-prompt`, `--subject-type`). The skill\n**automatically normalizes** dashed JSON keys to underscored ones, so both\nwork; use whichever is more natural for your tooling.\n\n**Output:**\nThe result JSON envelope includes a `generation_time_s` field (extracted from\nSeedream's own metadata) for quota tracking.\n\n---\n\n## Unified API Interface\n\n| Parameter | Type | Default | Required | Description |\n|-----------|------|---------|----------|-------------|\n| `task` | string | - | ✅ | Task type: `remove-object` / `remove-background` / `restore` / `resize` / `crop` / `color-adjust` / `perspective-correct` / `smart-compress` / `hdr-tonemap` / `replace-scene` |\n| `image` | string | - | ✅ | Input image path |\n| `prompt` | string | \"\" | ❌ | Object description/location (required for remove-object) |\n| `tool` | string | \"auto\" | ❌ | Force specific tool: `auto` / `seedream` / `imagemagick` / `opencv` / `rembg` |\n| `output_format` | string | \"jpeg\" | ❌ | Output format: jpeg / png / webp |\n| `quality` | integer | 95 | ❌ | Output quality (0-100) |\n\n---\n\n## Intelligent Decision Flow\n\n```\nUser request → Analyze task type\n    ↓\nObject removal? → Seedream (default) → Failed? → OpenCV fallback\n    ↓\nBackground removal? → Detect background → Solid? ImageMagick : rembg\n    ↓\nOld photo restoration? → Seedream (reference_strength=0.7)\n    ↓\nBasic editing? → ImageMagick\n```\n\n---\n\n## Examples\n\n### Remove Power Cable\n```\nTask: Remove the black power cable at the bottom of the image\nParameters:\n  task: remove-object\n  image: mountain.jpg\n  prompt: \"Remove the thin black horizontal power cable at the bottom 20% of the image. Restore the mountain texture seamlessly, keep everything else exactly the same.\"\n  tool: seedream\n```\n\n### Old Photo Restoration\n```\nTask: Restore this old photo\nParameters:\n  task: restore\n  image: old_photo.jpg\n  prompt: \"Remove scratches and dust spots, enhance clarity, restore natural colors\"\n```\n\n### Background Removal\n```\nTask: Remove background from portrait photo\nParameters:\n  task: remove-background\n  image: portrait.jpg\n  tool: auto\n```\n\n### Portrait Retouching\n```bash\n# Apply all portrait enhancements\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing and eye enhancement\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n```\n\n---\n\n## Error Handling & Fallbacks\n\n1. **Seedream API failure** → surface the Seedream error verbatim; for known-geometry cases use `scripts/inpaint.py` directly (`--type spot/wire/rect`) or pass `--tool opencv` to get the inpaint.py guidance message.\n2. **Seedream skill unavailable / `--tool opencv`** → `op_remove_object` returns an actionable redirect listing common `inpaint.py` invocations.\n3. **Image too large** → Auto-resize to 2048px max side, process, output.\n4. **rembg not installed** → Auto-fallback to ImageMagick remove-bg.\n5. **Unsupported format** → Auto-convert to JPEG for processing.\n\n---\n\n## Large Image Handling Strategy\n\n- Seedream API limit: ~2048px maximum side length\n- Auto-detect image dimensions, if exceeded:\n  1. Proportionally resize to 2048px max side\n  2. Perform editing operation\n  3. Output processed image\n- Prevents \"image too large\" errors\n\n---\n\n## Skill File Structure\n\n```\nsmart-photo-editor/\n├── SKILL.md              # This file\n├── README.md             # Quick start guide\n├── scripts/\n│   ├── edit.py           # ⭐ Unified CLI entry point (all operations)\n│   ├── inpaint.py        # OpenCV wire/spot/line/rect/denoise/sharpen/adjust\n│   ├── portrait.py        # Portrait retouching (skin, eyes, teeth, etc.)\n│   ├── smart_crop.py     # Smart auto-crop based on saliency detection\n│   ├── exif_utils.py     # EXIF read/strip/copy utility\n│   └── remove_bg.sh      # Background removal wrapper\n└── examples/             # Before/after comparison examples\n```\n\n---\n\n## Unified CLI (`edit.py`)\n\nThe recommended entry point for all photo editing operations.\n\n```bash\n# Object removal (AI)\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the person in the center\" --output out.jpg\n\n# Old photo restoration\n./scripts/edit.py --task restore --image old_photo.jpg --output restored.jpg\n\n# Background removal\n./scripts/edit.py --task remove-background --image portrait.png --output no_bg.png\n\n# Resize\n./scripts/edit.py --task resize --image photo.jpg --output small.jpg --width 800\n\n# Crop\n./scripts/edit.py --task crop --image photo.jpg --output crop.jpg \\\n  --x 100 --y 100 --width 400 --height 300\n\n# Color adjustment\n./scripts/edit.py --task color-adjust --image photo.jpg --output bright.jpg \\\n  --brightness 20 --saturation 30\n\n# Batch mode (JSON)\n./scripts/edit.py --json < batch_tasks.json\n```\n\n### Unified Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--task` | string | **required** | Operation: `remove-object`, `restore`, `remove-background`, `resize`, `crop`, `color-adjust`, `perspective-correct`, `smart-compress`, `hdr-tonemap` |\n| `--image` / `-i` | string | **required** | Input image path |\n| `--output` / `-o` | string | auto | Output path (default: `{input}.{task}{ext}`) |\n| `--prompt` / `-p` | string | - | Description for AI operations |\n| `--tool` / `-t` | string | `auto` | Force tool: `auto`, `seedream`, `opencv`, `imagemagick`, `rembg` |\n| `--width` / `-w` | int | - | Target width (resize/crop) |\n| `--height` / `-H` | int | - | Target height (resize/crop) |\n| `--max-dim` | int | - | Max dimension, maintains aspect (resize) |\n| `--x`, `--y` | int | - | Offset for crop |\n| `--brightness` | float | - | Brightness: -100 to 100 |\n| `--contrast` | float | - | Contrast: -100 to 100 |\n| `--saturation` | float | - | Saturation: -1 to 1 |\n| `--grayscale` | flag | false | Convert to grayscale |\n| `--corners` | string | - | Perspective corners: `x1,y1,x2,y2,x3,y3,x4,y4` (TL,TR,BR,BL) |\n| `--target-kb` | int | - | Target file size in KB (smart-compress quality search) |\n| `--format` | string | - | Output format: `jpeg` \\| `png` \\| `webp` |\n| `--mode` | string | auto | HDR tonemap mode: auto / bilateral / log / shadows / highlight |\n| `--strength` | float | 1.0 | Enhancement strength 0.1-2.0 (hdr-tonemap) |\n| `--gamma` | float | 2.2 | Gamma value for log mode (hdr-tonemap) |\n| `--quality` | int | auto | Output quality 1-100 (jpeg/webp; ignored when `--target-kb` is set) |\n| `--position` | string | - | Horizontal placement for `replace-scene`: `left` / `center` / `right` |\n| `--scale` | string | - | Framing for `replace-scene`: `close` / `medium` / `full` |\n| `--subject` / `-S` | string | - | Subject image path (required for `replace-scene`) |\n| `--scene` | string | - | Scene image path (one of `--scene` or `--scene-prompt` for `replace-scene`) |\n| `--scene-prompt` | string | - | Scene text description (one of `--scene` or `--scene-prompt` for `replace-scene`) |\n| `--subject-type` | string | `auto` | Subject type for `replace-scene`: `auto` / `portrait` / `pet` / `product` |\n| `--reference-strength` | float | 0.85 | How strongly Seedream preserves the subject |\n| `--watermark` | flag | false | Add Seedream watermark (default OFF) |\n| `--json` | flag | false | Emit JSON result envelope on stdout. Combine with `--batch` (or piped stdin) for JSON batch input. |\n| `--batch` / `-b` | string | - | JSON file for batch operations |\n\n### JSON Batch Format\n\n```json\n{\n  \"operations\": [\n    {\"task\": \"remove-object\", \"image\": \"a.jpg\", \"prompt\": \"Remove the person\", \"output\": \"a_out.jpg\"},\n    {\"task\": \"restore\", \"image\": \"b.jpg\", \"output\": \"b_out.jpg\"},\n    {\"task\": \"resize\", \"image\": \"c.jpg\", \"output\": \"c_small.jpg\", \"width\": 800}\n  ]\n}\n```\n\n---\n\n## Changelog\n\n### 1.5.0 — 2026-07-19\n\n**New `replace-scene` parameters**\n- `--position {left,center,right}` — controls horizontal placement of the subject in the generated scene. Feeds into the scene-prompt as a positional hint so Seedream places the subject accordingly.\n- `--scale {close,medium,full}` — controls subject framing (特写/中景/全身). Feeds into the scene-prompt as a framing hint.\n\n**R2 large-file upload for Seedream reference images**\n- When a reference image exceeds 1.5 MB, the skill can upload to Cloudflare R2 and pass the public URL to Seedream instead of embedding a base64 data URI.\n- Requires self-deployed Cloudflare R2 Worker + `SEEDREAM_UPLOAD_TOKEN` and `SEEDREAM_UPLOAD_WORKER_URL` env vars.\n- Without R2 configured, large images gracefully fall back to base64 data URI.\n\n### 1.4.0 — 2026-07-14\n\n**New feature: `replace-scene` task**\nAdds a new AI-driven task that places a subject (portrait / pet / product) into\na new scene using Seedream's multi-reference image fusion. Wraps 豆包 app's\n\"多图融合\" + \"换场景\" feature.\n- New `--subject` (alias of `--image` for this task) + mutually-exclusive\n  `--scene` (image) or `--scene-prompt` (text) input pair.\n- `--subject-type {auto,portrait,pet,product}` selects a per-type prompt\n  template and reference_strength. `auto` uses filename keyword + corner\n  solidity heuristics.\n- `--watermark` defaults to OFF (most uses are product / academic).\n- New `_call_seedream(reference_images=...)` parameter — passes a JSON array\n  of data URIs to Seedream (which accepts up to 14 reference images).\n- Subject image is auto-resized to 2048px max side; temp files are cleaned up.\n- Returns `info.generation_time_s` extracted from Seedream's metadata for\n  quota tracking.\n\n**Bug fixes (incidental, surfaced by v1.4.0 testing)**\n- `process_batch` now normalizes dashed JSON keys (`scene-prompt` →\n  `scene_prompt`, `target-kb` → `target_kb`, `subject-type` → `subject_type`,\n  `no-maintain-aspect` → `no_maintain_aspect`) before unpacking into\n  `process(**op)`. Previously these were silently dropped into the trailing\n  `**kwargs` and the real parameter received its default — a very confusing\n  failure mode (especially for `target-kb` where the result was a wildly\n  different file size than requested).\n- `process()` now translates `no_maintain_aspect=True` (from JSON batch) to\n  `maintain_aspect=False` (the inverted semantics the `op_resize` function\n  expects), mirroring the same translation `main()` does for the CLI.\n\n**Docs**\n- New section 11 \"Scene Replacement\" with 6 worked examples, full argument\n  table, validation rules, auto-detection logic, and JSON batch format.\n- Updated Tool Selection Policy + Per-task defaults tables to include\n  `replace-scene`.\n- Updated Unified API Interface task list.\n\n### 1.3.4 — 2026-07-14\n\n**ImageMagick argument fix**\n- `op_resize` / `op_crop` / `op_color_adjust` / `op_remove_background` (ImageMagick fallback): all ImageMagick CLI arguments are now passed as separate list elements instead of single space-joined strings. Previously ImageMagick would reject commands like `-resize 800x800>` because the flag and value were concatenated into one string.\n\n**HDR bilateral saturation fix**\n- `_tonemap_bilateral` no longer performs a pseudo-HSV operation directly on BGR channels (which corrupted colors). Now uses proper `cv2.cvtColor(BGR→HSV)` → boost saturation → `cv2.cvtColor(HSV→BGR)`.\n\n**Background removal fallback fix**\n- `remove_bg.sh` ImageMagick fallback: corrected `matte` floodfill coordinates (was passing RGB values as coordinates; now uses `0,0`). Removed erroneous `-alpha extract` which turned output into a pure alpha mask.\n- `edit.py` ImageMagick fallback: replaced `-trim` (which merely cropped edges) with `-transparent <detected-bg-color>` so the result is actually a transparent-background image.\n\n**Runtime robustness**\n- `op_remove_background` now probes both `$PATH` and the team venv (`venv-clawd/bin/rembg`) for `rembg`, matching Laoguo's actual deployment environment.\n- `_call_seedream` guards against `shutil.copyfile(local, output_path)` when source and destination are the same file (would truncate to zero bytes).\n- `_save_with_quality` now derives the actual output format from the file extension, preventing OpenCV warnings when `--format` and `--output` disagree (e.g. `--output foo.webp --format png`).\n\n**CLI**\n- Added `--no-maintain-aspect` flag for `resize` task to allow non-proportional stretching.\n\n### 1.3.3 — 2026-06-13\n\n**Tool selection policy**\n- Codified the routing policy (see \"Tool Selection Policy\" near the top of this file): Seedream first for semantic / generative edits, deterministic tools first for mechanical edits.\n- `op_remove_object` no longer keyword-sniffs the prompt for \"wire / cable / line / spot / dust / scratch\" and silently routes to a stub. `--tool auto` now picks Seedream when available; the OpenCV branch surfaces an actionable redirect to `scripts/inpaint.py` for known-geometry cases.\n- The redirect message also lists the most common `inpaint.py` invocations (`--type spot`, `--type wire`, `--type rect`) so users have a clear next step instead of a guess.\n\n### 1.3.2 — 2026-06-13\n\n**Bug fixes**\n- `op_resize` / `op_crop` / `op_color_adjust` no longer raise `TypeError: got an unexpected keyword argument 'mode'`. The CLI's `--mode` flag is now only forwarded for `hdr-tonemap`. (Was reported as \"numpy 2.x compat issue\"; root cause was kwargs leakage.)\n- `smart-compress --target-kb` no longer crashes with `No such file or directory: foo.q55.tmp`. The binary-search probe file now uses the format's real extension (`.jpg/.png/.webp`) so OpenCV can pick a codec.\n- `--quality` is now an actual CLI flag, declared in argparse and forwarded into `op_smart_compress` (was documented but unrecognized).\n- `--json` on a single-operation invocation now emits a JSON envelope on stdout instead of blocking on stdin. Batch input is still accepted via `--batch FILE` or piped stdin.\n- Markdown code fence around the AI-method / OpenCV-method examples is correctly paired (was rendered with broken nesting).\n- `compatibility` frontmatter key moved under `metadata.compatibility` (was rejected by the OpenClaw skill validator as an unknown top-level key).\n- `_tonemap_shadows` annotation corrected from `np.float32` to `np.ndarray`.\n\n**Seedream bridge rewrite**\nThe previous integration referenced a non-existent `bin/generate.sh` and a non-existent Python module. `_call_seedream` now invokes `node scripts/generate.js` with `--prompt`, `--mode image-to-image`, `--reference_images <data-URI JSON array>`, `--reference_strength`, and `--optimize false`, parses the JSON envelope from stdout, locates the first `download_success` image, and stages its `local_path` to the caller's `output_path`. Local file paths are encoded as `data:image/<type>;base64,<...>` data URIs because Seedream's validator only accepts HTTP URLs or data URIs. Verified end-to-end with a real ARK API call (200×200 input → 2048×2048 generated output, ~30 s).\n\n**Docs**\n- Added \"Python Interpreter\" section: all scripts hard-shebang the team venv (`~/.openclaw/venv-clawd/bin/python`); running them under system Python will spuriously report `piexif/exif/rembg` as missing.\n- `--quality` and `--json` table entries clarified.\n\nFile v1.5.2:README.md\n\n# Smart Photo Editor - Quick Start Guide\n\nAI-powered photo editing and restoration skill for OpenClaw.\n\n## Quick Start\n\n### ⭐ Recommended: Unified CLI (`edit.py`)\n```bash\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the power cable\" --output out.jpg\n```\n\n### Remove Object from Photo\n```\n\"Use smart-photo-editor to remove the power cable from this mountain photo\"\n```\n→ Automatically uses Seedream AI for complex scenes\n\n### Restore Old Photo\n```\n\"Use smart-photo-editor to restore this old photo\"\n```\n→ Removes scratches, enhances clarity, restores colors\n\n### Remove Background\n```\n\"Use smart-photo-editor to remove the background from this portrait\"\n```\n→ Uses rembg (if installed) or falls back to ImageMagick\n\n### Remove Diagonal/Angled Lines (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n```\n\n### Remove Watermark/Logo Region (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n```\n\n### Remove Multiple Spots/Lines (Batch Mode)\n```bash\n# Multiple spots in one command\n./scripts/inpaint.py input.jpg output.jpg --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Multiple lines in one command\n./scripts/inpaint.py input.jpg output.jpg --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py input.jpg output.jpg --type batch --batch tasks.json\n```\n\n### Resize for API Compatibility\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type resize --max-dim 2048\n```\n\n### Portrait Retouching\n```bash\n# All enhancements at once\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing + eye brightening\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n\n# Face brightness + contrast adjustment\n./scripts/portrait.py input.jpg output.jpg --brightness 10 --contrast 15\n```\n\n### EXIF Utilities\n```bash\n./scripts/exif_utils.py read photo.jpg        # Read EXIF tags\n./scripts/exif_utils.py strip photo.jpg -o out.jpg  # Remove EXIF\n./scripts/exif_utils.py copy src.jpg dst.jpg  # Copy EXIF to another image\n```\n\n### Smart Auto-Crop\n```bash\n./scripts/smart_crop.py input.jpg output.jpg               # Auto-detect salient region\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9 # Crop to aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --debug      # Generate debug overlay\n```\n\n### Additional OpenCV Operations (denoise / sharpen / adjust)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type denoise --strength 15\n./scripts/inpaint.py input.jpg output.jpg --type sharpen --strength 1.5\n./scripts/inpaint.py input.jpg output.jpg --type adjust --brightness 15 --contrast 10 --gamma 0.9\n```\n\n## Features\n\n| Feature | Best Tool | Quality |\n|---------|-----------|---------|\n| Object removal | Seedream AI | Excellent |\n| Old photo restoration | Seedream AI | Excellent |\n| Background removal | rembg AI | Excellent |\n| Solid background removal | ImageMagick | Good (fast) |\n| Wire/line removal | OpenCV | Good (fast) |\n| Sensor dust removal | OpenCV | Good (fast) |\n| Batch multi-region | OpenCV | Good (fast) |\n| Portrait retouching | OpenCV | Good |\n| Skin smoothing | OpenCV bilateral | Good |\n| Smart auto-crop | OpenCV saliency | Good |\n| Denoise / sharpen / adjust | OpenCV | Good |\n| Resize/crop/compress | ImageMagick | Excellent |\n| Color adjustment | ImageMagick | Excellent |\n| EXIF preservation | piexif/exif | — |\n\n## Skill File Structure\n\n```\n~/.openclaw/skills/smart-photo-editor/\n├── SKILL.md              # Full documentation\n├── README.md             # This file\n├── scripts/\n│   ├── edit.py           # ⭐ Unified CLI (all operations)\n│   ├── inpaint.py        # OpenCV wire/spot/line/rect/denoise/sharpen/adjust\n│   ├── portrait.py       # Portrait retouching (skin, eyes, teeth)\n│   ├── smart_crop.py     # Smart auto-crop based on saliency detection\n│   ├── exif_utils.py     # EXIF read/strip/copy utility\n│   └── remove_bg.sh      # Background removal wrapper\n└── examples/             # Before/after comparison examples (add your own)\n```\n\n## Tips\n\n1. **Large images** are automatically handled - no more \"image too large\" errors\n2. **Chinese prompts work** - the skill automatically translates to optimized English\n3. **Automatic fallback** - if Seedream fails, OpenCV will be tried for simple cases\n4. **EXIF preserved** - all editing scripts preserve camera metadata automatically\n5. **Face auto-detection** - portrait retouching automatically finds faces for targeted edits\n6. **Smart crop** - automatically finds the most interesting region in any image\n\n## Install Optional rembg\n\nFor better AI background removal:\n```bash\nsource ~/.openclaw/venv-clawd/bin/activate\npip install rembg\n```\n\nFile v1.5.2:_meta.json\n\n{\n  \"ownerId\": \"kn7b21fme4bx0xwpm700dj5ehh82zrgq\",\n  \"slug\": \"smart-photo-editor\",\n  \"version\": \"1.5.2\",\n  \"publishedAt\": 1784884881128\n}\n\nFile v1.5.2:skill-card.md\n\n## Description:\n\nAI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[guoxh](https://clawhub.ai/user/guoxh)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to select and run photo-editing workflows, including deterministic resizing, cropping, color adjustment, background removal, object removal, restoration, scene replacement, and portrait retouching.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Selected photos and metadata may be processed by external services for AI editing features.\n\nMitigation: Strip EXIF and location metadata before sensitive cloud AI edits, and use local deterministic tools when external processing is not acceptable.\n\nRisk: Large reference images may be sent through a user-configured Cloudflare R2 worker when upload support is enabled.\n\nMitigation: Enable R2 upload only with a trusted worker and token, and review worker access controls before use.\n\nRisk: Unpinned Python dependencies or optional image tools can change behavior across environments.\n\nMitigation: Pin dependencies in the deployment environment and test critical edits before batch use.\n\nRisk: Image editing commands write output files and can overwrite important files if paths are chosen poorly.\n\nMitigation: Use distinct output paths and keep backups of source images before running destructive or batch operations.\n\n## Reference(s):\n\n- [Smart Photo Editor on ClawHub](https://clawhub.ai/guoxh/skills/smart-photo-editor)\n- [VolcEngine Ark Seedream setup guide](https://www.volcengine.com/docs/82379/2375486)\n- [Cloudflare R2 documentation](https://developers.cloudflare.com/r2/)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands, CLI arguments, and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce edited image files through local scripts and optional external AI or upload services when configured.]\n\n## Skill Version(s):\n\n1.5.2 (source: server release metadata; artifact metadata reports 1.5.1)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.5.1: 10 files, 63982 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (86796b), scripts/exif_utils.py (13253b), scripts/inpaint.py (21020b), scripts/portrait.py (28801b), scripts/remove_bg.sh (2903b), scripts/smart_crop.py (19750b), skill-card.md (2321b), SKILL.md (41534b)\n\nFile v1.5.1:SKILL.md\n\n---\nname: smart-photo-editor\nlicense: MIT\ndescription: |\n  AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nmetadata:\n  author: Team\n  version: \"1.5.1\"\n  category: ai/image-editing\n  compatibility: Requires Node.js 18+ and network access to VolcEngine Ark API (with Seedream model enabled) for AI features.\n---\n\n# Smart Photo Editor Skill\n\nAI-powered photo editing and restoration skill for OpenClaw. Unifies Seedream (AI edits), ImageMagick (basic edits), and OpenCV (programmatic fixes) into one intuitive workflow.\n\n## Overview\n\nAll-in-one intelligent photo editing skill - automatically selects the best tool for each image processing task.\n\n✨ **Key Advantages:**\n- ✅ **Smart Tool Selection** - Automatically chooses Seedream / ImageMagick / OpenCV based on task\n- ✅ **Unified Interface** - All operations use the same calling pattern\n- ✅ **Bilingual Support** - Optimized prompts for both Chinese and English contexts\n- ✅ **Automatic Fallback** - Switches to backup tools if primary tool fails\n- ✅ **Large Image Auto-Handling** - Avoids \"image too large\" API errors\n\n## Feature Availability\n\nThis skill provides two tiers of functionality:\n\n### ✅ Works out of the box (no extra dependencies)\n\nThese features only require ImageMagick and/or OpenCV (both widely available on Linux/macOS):\n\n- **Resize / Crop / Smart-crop** — dimension changes, aspect-ratio-preserving scaling\n- **Color adjustment** — brightness, contrast, saturation, grayscale\n- **Perspective correction** — 4-point skew/warp correction\n- **Smart compression** — quality targeting, binary-search for target file size\n- **HDR tonemapping** — log/bilateral/shadow/highlight recovery\n- **Background removal (basic)** — solid-color background removal via ImageMagick\n- **Geometric inpainting** — wire/line/rect removal with known coordinates (`inpaint.py`)\n\n### 🔒 Requires Seedream skill (AI features)\n\nThese features require the `byted-ark-seedream-skill` (VolcEngine Ark Agent Plan, managed skill):\n\n- **Object removal (natural language)** — remove objects described in text (people, vehicles, watermarks)\n- **Old photo restoration** — AI scratch/dust/fading repair\n- **Scene replacement (`replace-scene`)** — put subject into a new scene via multi-reference fusion\n- **Background removal (AI)** — rembg-based, or Seedream-based for complex edges\n\n> **Note:** The `byted-ark-seedream-skill` is an OpenClaw managed skill that requires a VolcEngine Ark account with the Seedream model enabled. Install with `openclaw skills install byted-ark-seedream-skill`.\n\n---\n\n## Trigger Conditions\n\nActivates automatically when users mention keywords like:\n- photo editing, edit image, retouch, smart photo edit\n- remove object, delete object, erase, remove person, remove watermark, remove logo, 去除, 消除\n- remove background, background removal, cutout, 抠图, 换背景\n- restore, fix, old photo restoration, repair, 修复老照片, 老照片修复\n- portrait retouching, portrait edit, smooth skin, whiten teeth, enhance eyes, remove blemish, red eye, 美颜, 人像精修, 红眼\n- replace scene, change scene, put subject in, 换场景, 多图融合\n- color adjustment, color correction, color grading, brightness, 调色, 色彩调整\n- crop, resize, compress, auto crop, smart crop, 裁剪, 自动裁剪, 智能裁剪\n- perspective, fix skew, flatten, perspective correct, 透视矫正, 视角矫正\n- hdr, tonemap, highlight recovery, shadow recovery, 高动态, 阴影增强\n- sharpen, denoise, 锐化, 降噪\n\n---\n\n## Tool Selection Policy\n\nThe skill mixes three classes of tool. Picking the right one for each task is\nwhat makes the unified entry-point useful, so the routing is explicit:\n\n**Use Seedream first for semantic / generative edits.**\n- Object removal in complex scenes (people, vehicles, watermarks, signs)\n- Old-photo restoration (scratches, fading, color loss)\n- Background replacement / scene swap\n- Subjective enhancement: “make this look better / natural / cinematic”\n- Edits where the model must infer missing visual content\n- Natural-language requests, especially in Chinese\n\nFor these, Seedream is the value-add. OpenCV/ImageMagick can’t compete on\nquality, and a deterministic tool can’t “invent” plausible content.\n\n**Use deterministic tools first for mechanical edits.**\n- Resize, crop, format conversion\n- Compression / quality targeting\n- Brightness, contrast, saturation, gamma adjustments\n- Geometric inpainting when coordinates are known (wires, dust spots,\n  exact rectangles — call `inpaint.py` directly)\n- Batch operations where reproducibility matters\n\nFor these, Seedream would be slower, costlier, and less predictable.\n\n**Encoded policy (auto mode):**\n```text\nsemantic edit / restoration / object removal       → Seedream first; deterministic fallback\nmechanical edit / resize / crop / compress / color → deterministic tools first\nuser explicitly asks for AI / natural restoration  → Seedream\nuser explicitly forces a tool with --tool ...      → honored verbatim\n```\n\n**Per-task defaults (`--tool auto`):**\n\n| Task | Default | Notes |\n|------|---------|-------|\n| `remove-object` | **Seedream** | OpenCV branch only fires when Seedream is unavailable; redirects to `inpaint.py` for known-geometry cases |\n| `restore` | **Seedream** | Seedream-only operation by design |\n| `remove-background` | **rembg** | ImageMagick fallback for solid-color backgrounds when rembg is missing |\n| `resize` / `crop` / `color-adjust` | **OpenCV/ImageMagick** | Deterministic, instant, free |\n| `smart-compress` | **OpenCV** | Content-aware quality + format selection |\n| `perspective-correct` | **OpenCV** | Document/whiteboard correction |\n| `hdr-tonemap` | **OpenCV** | All four modes (auto / bilateral / log / shadows) are deterministic |\n| `replace-scene` | **Seedream** | AI-only; no deterministic fallback (would produce poor results). If Seedream is unavailable, returns error directing user to install the Seedream skill. |\n\nOverride with `--tool seedream | opencv | imagemagick | rembg`.\n\n---\n\n## Installation & Dependencies\n\n### Standard Installation Path\n`~/.openclaw/skills/smart-photo-editor/`\n\n### Python Interpreter\nAll Python scripts (`scripts/*.py`) use a portable `#!/usr/bin/env python3` shebang.\n\nYou can run them directly:\n\n```bash\n./scripts/edit.py --help\n```\n\nOr explicitly with your Python of choice (e.g. a virtualenv where you have\ninstalled the dependencies below):\n\n```bash\npython3 scripts/edit.py --help\n```\n\n**Make sure the Python interpreter you use has the required dependencies**\n(OpenCV, Pillow, NumPy). Optional deps (`piexif`, `exif`, `rembg`) add extra\nfeatures; the skill will gracefully skip those features if they are missing.\n\n```bash\n# Sanity check — required deps\\python3 -c \"import cv2, numpy, PIL; print('core deps ok')\"\n\n# Sanity check — full deps (includes optional rembg/piexif/exif)\npython3 -c \"import cv2, numpy, PIL, piexif, exif, rembg; print('all deps ok')\"\n```\n\n### Required & Optional Dependencies\n| Dependency | Required | Purpose | Installation |\n|------------|----------|---------|--------------|\n| **byted-ark-seedream-skill** | ✅ Required | AI object removal, old photo restoration, image-to-image editing | Requires VolcEngine Ark API access. Follow [official setup guide](https://www.volcengine.com/docs/82379/2375486) to enable Seedream model access |\n| **imagemagick** | ✅ Required | Basic image editing (resize, crop, format conversion, color adjustments) | `sudo apt install imagemagick` (Debian/Ubuntu) or `brew install imagemagick` (macOS) |\n| **opencv-python-headless** | ✅ Required | Wire removal, spot removal, image resizing | `pip install opencv-python-headless` |\n| **rembg** | ⚠️ Optional | AI-powered background removal (better results for complex scenes) | `pip install rembg` |\n| **piexif** | ⚠️ Optional | EXIF metadata preservation during edits | `pip install piexif` |\n| **exif** | ⚠️ Optional | Extended EXIF tag reading | `pip install exif` |\n\n### Install Optional Dependencies\n```bash\nsource ~/.openclaw/venv-clawd/bin/activate\npip install rembg piexif exif\n```\n\n### Cloudflare R2 Upload (Large Reference Images)\n\nWhen a reference image (subject or scene image) exceeds **1.5 MB**, the skill can upload it to Cloudflare R2 instead of embedding it as a base64 data URI. This avoids hitting Seedream API payload size limits.\n\n**R2 is optional.** Without configuration, large images fall back to base64 data URI (which may fail for very large files due to CLI argument limits).\n\n**To enable R2 upload, deploy your own Cloudflare Worker:**\n\n1. Create a Cloudflare R2 bucket and a Worker that accepts PUT requests (see the [Cloudflare R2 documentation](https://developers.cloudflare.com/r2/))\n2. Set the following environment variables:\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `SEEDREAM_UPLOAD_TOKEN` | ✅ Yes | Bearer token for your R2 upload worker. |\n| `SEEDREAM_UPLOAD_WORKER_URL` | ✅ Yes | Your worker URL, e.g. `https://your-worker.your-subdomain.workers.dev`. |\n\n```bash\n# Add to your shell profile or ~/.openclaw/.env\nexport SEEDREAM_UPLOAD_TOKEN=\"your-token-here\"\nexport SEEDREAM_UPLOAD_WORKER_URL=\"https://your-worker.your-subdomain.workers.dev\"\n```\n\nWithout both variables, large images gracefully fall back to the data URI path (works for most cases; may hit CLI arg limits for very large multi-image batches).\n\n### VolcEngine Ark Setup\nFor AI editing features (object removal, photo restoration), ensure:\n1. You have a VolcEngine Ark account with API access\n2. The Seedream (豆包生图) model is enabled for your account\n3. Your OpenClaw configuration has valid VolcEngine API credentials\n\nSee the [official VolcEngine Ark documentation](https://www.volcengine.com/docs/82379/2375486) for detailed setup instructions.\n\n---\n\n## Core Features & Implementation\n\n### 1. Object Removal\n**Primary Tool:** Seedream Image-to-Image  \n**Fallback Tool:** OpenCV Inpainting (small scratches/lines)\n\n**Usage:**\n```bash\n# AI method (recommended) - complex scenes\nimage_generate \\\n  model=\"byted-ark-seedream-skill\" \\\n  mode=\"image-to-image\" \\\n  image=\"/path/to/photo.jpg\" \\\n  reference_strength=0.85 \\\n  prompt=\"Remove the [object description] located at [location description]. Restore the seamless texture, keep everything else exactly the same.\"\n```\n\n**OpenCV method** — simple lines/minor imperfections:\n```bash\n# Remove horizontal wire\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type wire --y 760 --thickness 10\n\n# Remove diagonal/angled line (supports any angle)\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n\n# Remove rectangular region (watermarks, logos, text)\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n\n# Remove multiple sensor dust spots in one command\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Remove multiple lines in one command\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type batch --batch tasks.json\n\n# JSON config example (tasks.json):\n# {\n#   \"operations\": [\n#     {\"type\": \"spot\", \"x\": 100, \"y\": 150, \"radius\": 8},\n#     {\"type\": \"spot\", \"x\": 200, \"y\": 300, \"radius\": 10},\n#     {\"type\": \"wire\", \"y\": 500, \"thickness\": 5},\n#     {\"type\": \"rect\", \"x\": 50, \"y\": 50, \"w\": 200, \"h\": 50, \"feather\": 10}\n#   ]\n# }\n```\n\n**Algorithm Selection:**\n- `ns` (Navier-Stokes) - Better for textures and larger regions (default for wire/line)\n- `telea` (Telea) - Faster, better for small regions (default for spot)\nUse `--algo ns` or `--algo telea` to override the default selection.\n\n**Prompt Optimization Examples:**\n- \"Remove the black power cable at the bottom of the image\" → \"Remove the thin black horizontal power cable at the bottom 20% of the image. Restore the mountain texture seamlessly, keep everything else exactly the same.\"\n- \"Remove the pedestrian in the middle\" → \"Remove the pedestrian in the center. Fill with matching background texture naturally.\"\n\n---\n\n### 2. Background Removal\n**Primary Tool:** rembg (AI)  \n**Fallback Tool:** ImageMagick (inline – solid color backgrounds)\n\n**Usage:**\n```bash\n# rembg AI method (complex backgrounds)\nrembg i input.jpg output.png\n\n# ImageMagick method (solid color backgrounds)\n./scripts/remove_bg.sh input.png output.png 20 \"#FFFFFF\"\n```\n\n---\n\n### 3. Old Photo Restoration\n**Primary Tool:** Seedream Image-to-Image\n\n**Usage:**\n```bash\nimage_generate \\\n  model=\"byted-ark-seedream-skill\" \\\n  mode=\"image-to-image\" \\\n  image=\"/path/to/old_photo.jpg\" \\\n  reference_strength=0.7 \\\n  prompt=\"Restore this old photo. Remove all scratches, dust spots, and damage. Enhance clarity and contrast. Restore natural, vivid colors while preserving the original photo's character. Do not change the composition or subjects.\"\n```\n\n---\n\n### 4. Basic Editing\n**Primary Tool:** ImageMagick + OpenCV\n\n**Common Commands:**\n```bash\n# Resize\nconvert input.jpg -resize 1920x1920\\> output.jpg\n\n# Crop\nconvert input.jpg -crop 800x600+100+50 output.jpg\n\n# Format conversion + compression\nconvert input.png -quality 85 output.webp\n\n# Color adjustment\nconvert input.jpg -brightness-contrast 10x5 output.jpg  # Brighter, higher contrast\nconvert input.jpg -modulate 100,130,100 output.jpg      # Increase saturation\nconvert input.jpg -grayscale Rec709Luma output.jpg      # Convert to B&W\n```\n\n**OpenCV Operations (inpaint.py):**\n```bash\n# Denoise (reduce noise in low-light photos)\n./scripts/inpaint.py input.jpg output.jpg --type denoise --strength 15\n\n# Sharpen (enhance edges and focus)\n./scripts/inpaint.py input.jpg output.jpg --type sharpen --strength 1.5\n\n# Brightness/contrast/gamma adjustment\n./scripts/inpaint.py input.jpg output.jpg --type adjust --brightness 15 --contrast 10 --gamma 0.9\n```\n\n### 5. Portrait Retouching\n**Primary Tool:** OpenCV (face detection + image processing)  \n**Dependencies:** `opencv-python-headless` (already required)\n\nPortrait retouching provides face-aware enhancements for portrait photography:\n- **Skin smoothing** — bilateral filter preserves edges while softening skin\n- **Red-eye removal** — detects and corrects flash red-eye\n- **Teeth whitening** — targets lower-face region, preserves surrounding\n- **Eye enhancement** — brightens and sharpens eyes\n- **Face brightness/contrast** — applies adjustments only to detected face\n- **Blemish removal** — removes small spots using inpainting\n- **Skin tone enhancement** — warm, healthy color correction\n\n```bash\n# Skin smoothing only\n./scripts/portrait.py input.jpg output.jpg --smooth 3\n\n# All enhancements (balanced)\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle preset (conservative)\n./scripts/portrait.py input.jpg output.jpg --subtle\n\n# Custom combination\n./scripts/portrait.py input.jpg output.jpg \\\n  --smooth 2 --enhance-eyes --whiten-teeth 0.3 --brightness 10\n\n# JSON output\n./scripts/portrait.py input.jpg output.jpg --all --json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--smooth` | Skin smoothing strength 1-10 |\n| `--denoise` | Denoise strength 1-30 |\n| `--red-eye` | Remove flash red-eye |\n| `--whiten-teeth` | Teeth whitening strength 0.1-0.8 |\n| `--enhance-eyes` | Brighten/sharpen eyes |\n| `--brightness` | Face brightness -100 to 100 |\n| `--contrast` | Face contrast -100 to 100 |\n| `--gamma` | Face gamma correction 0.1-3.0 |\n| `--sharpen` | Sharpening strength 0.5-3.0 |\n| `--blemish-removal` | Remove small blemishes |\n| `--skin-tone` | Warm skin tone enhancement |\n| `--all` | Apply all enhancements (balanced) |\n| `--subtle` | Conservative all enhancements |\n| `--no-auto-detect` | Skip face/eye detection |\n| `--no-exif` | Do not preserve EXIF |\n| `--json` | JSON output mode |\n\n### 6. EXIF Preservation\n**Automatic:** All write operations preserve EXIF metadata by default  \n**Tool:** `scripts/exif_utils.py` — standalone EXIF utility\n\nAll editing scripts automatically preserve EXIF metadata from input to output.\n\n```bash\n# Read EXIF from an image\n./scripts/exif_utils.py read photo.jpg\n\n# Strip EXIF from an image\n./scripts/exif_utils.py strip photo.jpg -o output.jpg\n\n# Copy EXIF from one image to another\n./scripts/exif_utils.py copy source.jpg dest.jpg\n```\n\nSupported tags: Make, Model, DateTime, Orientation, Exposure Time, F-Number, ISO, Focal Length, Lens Model, and more.\n\n---\n\n### 7. Smart Crop (Auto-Crop)\n**Primary Tool:** OpenCV saliency detection + optional GrabCut refinement  \n**Dependencies:** `opencv-python-headless` (already required)\n\nAutomatically detects the most \"interesting\" region in an image and crops to it.\nUses OpenCV's StaticSaliencyFineGrained algorithm by default, with spectral and edge-based fallbacks.\n\n```bash\n# Auto-crop to salient region with default padding\n./scripts/smart_crop.py input.jpg output.jpg\n\n# Crop to specific aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9\n\n# Crop to 4:3 with 10% margin around subject\n./scripts/smart_crop.py input.jpg output.jpg --aspect 4/3 --padding 0.1\n\n# Resize to exact dimensions after smart crop\n./scripts/smart_crop.py input.jpg output.jpg --width 800 --height 600\n\n# Use GrabCut refinement for cleaner boundaries\n./scripts/smart_crop.py input.jpg output.jpg --grabcut\n\n# Generate debug saliency map overlay\n./scripts/smart_crop.py input.jpg output.jpg --debug\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--aspect`, `-a` | Aspect ratio (e.g. `16/9`, `4/3`, `1/1`) |\n| `--width`, `-w` | Target width in pixels |\n| `--height`, `-H` | Target height in pixels |\n| `--padding`, `-p` | Margin around subject (0.0-0.5, default 0.05) |\n| `--threshold`, `-t` | Saliency threshold 0.05-0.95 (default 0.3) |\n| `--algorithm` | `auto` / `finegrained` / `spectral` / `edge` |\n| `--grabcut`, `-g` | Use GrabCut to refine crop boundary |\n| `--debug`, `-d` | Generate debug saliency map overlay |\n\n### 8. Perspective Correction\n**Primary Tool:** OpenCV (auto-detection + warpPerspective)\n\nAuto-detects document/sheet borders using edge detection + contour analysis and corrects perspective distortion. Also supports manual corner specification.\n\n```bash\n# Auto-detect and correct\n./scripts/edit.py --task perspective-correct --image doc.jpg --output flat.jpg\n\n# With manual corners (top-left, top-right, bottom-right, bottom-left)\n./scripts/edit.py --task perspective-correct --image doc.jpg --output flat.jpg \\\n  --corners \"100,50,600,50,600,800,100,800\"\n\n# Batch JSON\n./scripts/edit.py --json < tasks.json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--corners` | 4 points as CSV `x1,y1,x2,y2,x3,y3,x4,y4` (TL,TR,BR,BL). Omit for auto-detection |\n\n**Algorithm:** Adaptive threshold → contour detection → largest 4-point quadrilateral → perspective transform.\n\n---\n\n### 9. Intelligent Compression\n**Primary Tool:** OpenCV (content analysis + format-specific encoding)\n\nContent-aware image compression using entropy, edge density, and color variance analysis to auto-select the best format and quality.\n\n```bash\n# Auto-select best format and quality\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.jpg\n\n# Target file size (auto binary-searches quality)\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.jpg --target-kb 200\n\n# Force WebP with specific quality\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.webp \\\n  --format webp --quality 85\n\n# Batch JSON\n./scripts/edit.py --json < tasks.json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--target-kb` | Target output size in KB (enables binary-search for optimal quality) |\n| `--format` | Force output: `jpeg` | `png` | `webp` |\n\n**Auto-decision logic:**\n- **JPEG** — high entropy (>6.5) + dense edges → complex photographic content\n- **PNG** — low color variance (<500) + low edges → flat graphics/screenshots; or alpha channel detected\n- **Quality** — auto-selected based on entropy (65–92) unless `--target-kb` is specified\n\n---\n\n### 10. HDR / Tonemapping\n**Primary Tool:** OpenCV (multi-scale bilateral decomposition + CLAHE)\n\nHDR-style tone mapping to enhance dynamic range on single images. Uses bilateral filter decomposition to separate illumination from detail, compress the illumination layer's dynamic range, then recombine — producing natural-looking highlight/shadow recovery.\n\n```bash\n# Auto mode (default — picks best method based on image analysis)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg\n\n# Bilateral mode — detail-preserving compression (best for most photos)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode bilateral --strength 1.2\n\n# Log mode — fast global compression (good for screenshots/graphics)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode log --gamma 2.2\n\n# Shadows mode — lighten dark regions (backlit photos)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode shadows --strength 1.5\n\n# Highlight mode — compress blown highlights\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode highlight --strength 1.2\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--mode` | auto / bilateral / log / shadows / highlight (default: auto) |\n| `--strength` | Enhancement strength 0.1-2.0 (default: 1.0) |\n| `--gamma` | Gamma value for log mode (default: 2.2) |\n\n**Algorithm:** Bilateral filter decomposition — base (illumination) layer compressed with S-curve; detail layer preserved and boosted; adaptive saturation adjustment.\n\n---\n\n### 11. Scene Replacement\n**Primary Tool:** Seedream multi-reference image fusion (AI-only, no deterministic fallback)\n\nPlace a subject (portrait / pet / product) into a new scene using Seedream's\nmulti-reference image fusion. Wraps 豆包 app's \"多图融合\" + \"换场景\" feature.\n\n**Requires:** the `byted-ark-seedream-skill` (this task is AI-only; an\nOpenCV/ImageMagick fallback would produce poor results and is intentionally\nomitted).\n\n**Usage:**\n```bash\n# 1) Subject + scene image (most common)\n./scripts/edit.py --task replace-scene \\\n    --subject photo.jpg --scene cafe.png --output out.jpg\n\n# 2) Subject + text-only scene description\n./scripts/edit.py --task replace-scene \\\n    --subject pet.jpg --scene-prompt \"阳光下的草地\" --output out.jpg\n\n# 3) Product photo into lifestyle scene\n./scripts/edit.py --task replace-scene \\\n    --subject product.png --scene lifestyle.jpg --output out.jpg \\\n    --subject-type product\n\n# 4) Custom prompt override (full artistic control)\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene beach.jpg --output out.jpg \\\n    --prompt \"把人物放在黄昏海边沙滩，长发随风，光线偏暖，景深虚化\"\n\n# 5) Subject in center, close-up framing\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene studio.jpg --output out.jpg \\\n    --position center --scale close\n\n# 6) Full-body shot, subject on the right\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene beach.jpg --output out.jpg \\\n    --position right --scale full\n\n# 7) JSON batch with position/scale\n./scripts/edit.py --json < tasks.json\n```\n\n**Argument table:**\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `--subject` / `-S` | path | ✅ | — | Subject image (portrait / pet / product) |\n| `--scene` | path | ⚠️ one of | — | Target scene image |\n| `--scene-prompt` | string | ⚠️ one of | — | Target scene text description (used if no scene image) |\n| `--subject-type` | enum | ❌ | `auto` | `auto` / `portrait` / `pet` / `product`. Selects prompt template + reference_strength. |\n| `--prompt` / `-p` | string | ❌ | (from template) | Override the default prompt |\n| `--reference-strength` | float | ❌ | 0.85 (portrait/pet) / 0.90 (product) | How strongly Seedream must preserve the subject. Higher = stricter. |\n| `--watermark` | flag | ❌ | `false` | Add Seedream watermark. Default OFF (most uses are product / academic). |\n| `--position` | enum | ❌ | `center` | Horizontal subject placement: `left` / `center` / `right`. Feeds into the scene-prompt as positional hint.\n| `--scale` | enum | ❌ | `medium` | Subject framing: `close` (特写) / `medium` (中景) / `full` (全身). Feeds into the scene-prompt as framing hint.\n| `--output-format` | enum | ❌ | follow subject | `jpeg` / `png` / `webp` |\n| `--output` / `-o` | path | ❌ | auto | Output path |\n\n**Validation rules:**\n- `--subject` is required.\n- **Exactly one** of `--scene` / `--scene-prompt` is required (both → error).\n- If `--scene-prompt` is given, it must be at least 3 characters.\n- Subject image is auto-resized to 2048px max side (existing API limit helper).\n\n**Subject-type auto-detection:**\nWhen `--subject-type auto` is passed (default), the skill uses two heuristics:\n1. **Filename keyword** — `pet/cat/dog/...` → `pet`; `portrait/selfie/face/...` → `portrait`; `product/item/bottle/...` → `product`\n2. **Corner solidity check** — if all 4 corners are within 15 RGB units, classified as `product` (typical product shot on flat backdrop)\n\nIf neither heuristic matches, falls back to `portrait` (most common case).\nFor certainty, always pass `--subject-type` explicitly.\n\n**JSON batch format:**\n```json\n{\n  \"operations\": [\n    {\"task\": \"replace-scene\", \"subject\": \"p1.jpg\", \"scene\": \"office.jpg\",\n     \"output\": \"p1_office.jpg\", \"subject-type\": \"portrait\"},\n    {\"task\": \"replace-scene\", \"subject\": \"p2.jpg\", \"scene-prompt\": \"雪山日落\",\n     \"output\": \"p2_mountain.jpg\", \"subject-type\": \"portrait\"},\n    {\"task\": \"replace-scene\", \"subject\": \"shoe.png\", \"scene\": \"running_track.jpg\",\n     \"output\": \"shoe_track.jpg\", \"subject-type\": \"product\", \"reference-strength\": 0.9}\n  ]\n}\n```\n\n**JSON batch key naming:** JSON keys use **underscores** (Python identifier\nconvention): `scene_prompt`, `subject_type`, `reference_strength`, etc. The\nCLI flags use dashes (`--scene-prompt`, `--subject-type`). The skill\n**automatically normalizes** dashed JSON keys to underscored ones, so both\nwork; use whichever is more natural for your tooling.\n\n**Output:**\nThe result JSON envelope includes a `generation_time_s` field (extracted from\nSeedream's own metadata) for quota tracking.\n\n---\n\n## Unified API Interface\n\n| Parameter | Type | Default | Required | Description |\n|-----------|------|---------|----------|-------------|\n| `task` | string | - | ✅ | Task type: `remove-object` / `remove-background` / `restore` / `resize` / `crop` / `color-adjust` / `perspective-correct` / `smart-compress` / `hdr-tonemap` / `replace-scene` |\n| `image` | string | - | ✅ | Input image path |\n| `prompt` | string | \"\" | ❌ | Object description/location (required for remove-object) |\n| `tool` | string | \"auto\" | ❌ | Force specific tool: `auto` / `seedream` / `imagemagick` / `opencv` / `rembg` |\n| `output_format` | string | \"jpeg\" | ❌ | Output format: jpeg / png / webp |\n| `quality` | integer | 95 | ❌ | Output quality (0-100) |\n\n---\n\n## Intelligent Decision Flow\n\n```\nUser request → Analyze task type\n    ↓\nObject removal? → Seedream (default) → Failed? → OpenCV fallback\n    ↓\nBackground removal? → Detect background → Solid? ImageMagick : rembg\n    ↓\nOld photo restoration? → Seedream (reference_strength=0.7)\n    ↓\nBasic editing? → ImageMagick\n```\n\n---\n\n## Examples\n\n### Remove Power Cable\n```\nTask: Remove the black power cable at the bottom of the image\nParameters:\n  task: remove-object\n  image: mountain.jpg\n  prompt: \"Remove the thin black horizontal power cable at the bottom 20% of the image. Restore the mountain texture seamlessly, keep everything else exactly the same.\"\n  tool: seedream\n```\n\n### Old Photo Restoration\n```\nTask: Restore this old photo\nParameters:\n  task: restore\n  image: old_photo.jpg\n  prompt: \"Remove scratches and dust spots, enhance clarity, restore natural colors\"\n```\n\n### Background Removal\n```\nTask: Remove background from portrait photo\nParameters:\n  task: remove-background\n  image: portrait.jpg\n  tool: auto\n```\n\n### Portrait Retouching\n```bash\n# Apply all portrait enhancements\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing and eye enhancement\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n```\n\n---\n\n## Error Handling & Fallbacks\n\n1. **Seedream API failure** → surface the Seedream error verbatim; for known-geometry cases use `scripts/inpaint.py` directly (`--type spot/wire/rect`) or pass `--tool opencv` to get the inpaint.py guidance message.\n2. **Seedream skill unavailable / `--tool opencv`** → `op_remove_object` returns an actionable redirect listing common `inpaint.py` invocations.\n3. **Image too large** → Auto-resize to 2048px max side, process, output.\n4. **rembg not installed** → Auto-fallback to ImageMagick remove-bg.\n5. **Unsupported format** → Auto-convert to JPEG for processing.\n\n---\n\n## Large Image Handling Strategy\n\n- Seedream API limit: ~2048px maximum side length\n- Auto-detect image dimensions, if exceeded:\n  1. Proportionally resize to 2048px max side\n  2. Perform editing operation\n  3. Output processed image\n- Prevents \"image too large\" errors\n\n---\n\n## Skill File Structure\n\n```\nsmart-photo-editor/\n├── SKILL.md              # This file\n├── README.md             # Quick start guide\n├── scripts/\n│   ├── edit.py           # ⭐ Unified CLI entry point (all operations)\n│   ├── inpaint.py        # OpenCV wire/spot/line/rect/denoise/sharpen/adjust\n│   ├── portrait.py        # Portrait retouching (skin, eyes, teeth, etc.)\n│   ├── smart_crop.py     # Smart auto-crop based on saliency detection\n│   ├── exif_utils.py     # EXIF read/strip/copy utility\n│   └── remove_bg.sh      # Background removal wrapper\n└── examples/             # Before/after comparison examples\n```\n\n---\n\n## Unified CLI (`edit.py`)\n\nThe recommended entry point for all photo editing operations.\n\n```bash\n# Object removal (AI)\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the person in the center\" --output out.jpg\n\n# Old photo restoration\n./scripts/edit.py --task restore --image old_photo.jpg --output restored.jpg\n\n# Background removal\n./scripts/edit.py --task remove-background --image portrait.png --output no_bg.png\n\n# Resize\n./scripts/edit.py --task resize --image photo.jpg --output small.jpg --width 800\n\n# Crop\n./scripts/edit.py --task crop --image photo.jpg --output crop.jpg \\\n  --x 100 --y 100 --width 400 --height 300\n\n# Color adjustment\n./scripts/edit.py --task color-adjust --image photo.jpg --output bright.jpg \\\n  --brightness 20 --saturation 30\n\n# Batch mode (JSON)\n./scripts/edit.py --json < batch_tasks.json\n```\n\n### Unified Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--task` | string | **required** | Operation: `remove-object`, `restore`, `remove-background`, `resize`, `crop`, `color-adjust`, `perspective-correct`, `smart-compress`, `hdr-tonemap` |\n| `--image` / `-i` | string | **required** | Input image path |\n| `--output` / `-o` | string | auto | Output path (default: `{input}.{task}{ext}`) |\n| `--prompt` / `-p` | string | - | Description for AI operations |\n| `--tool` / `-t` | string | `auto` | Force tool: `auto`, `seedream`, `opencv`, `imagemagick`, `rembg` |\n| `--width` / `-w` | int | - | Target width (resize/crop) |\n| `--height` / `-H` | int | - | Target height (resize/crop) |\n| `--max-dim` | int | - | Max dimension, maintains aspect (resize) |\n| `--x`, `--y` | int | - | Offset for crop |\n| `--brightness` | float | - | Brightness: -100 to 100 |\n| `--contrast` | float | - | Contrast: -100 to 100 |\n| `--saturation` | float | - | Saturation: -1 to 1 |\n| `--grayscale` | flag | false | Convert to grayscale |\n| `--corners` | string | - | Perspective corners: `x1,y1,x2,y2,x3,y3,x4,y4` (TL,TR,BR,BL) |\n| `--target-kb` | int | - | Target file size in KB (smart-compress quality search) |\n| `--format` | string | - | Output format: `jpeg` \\| `png` \\| `webp` |\n| `--mode` | string | auto | HDR tonemap mode: auto / bilateral / log / shadows / highlight |\n| `--strength` | float | 1.0 | Enhancement strength 0.1-2.0 (hdr-tonemap) |\n| `--gamma` | float | 2.2 | Gamma value for log mode (hdr-tonemap) |\n| `--quality` | int | auto | Output quality 1-100 (jpeg/webp; ignored when `--target-kb` is set) |\n| `--position` | string | - | Horizontal placement for `replace-scene`: `left` / `center` / `right` |\n| `--scale` | string | - | Framing for `replace-scene`: `close` / `medium` / `full` |\n| `--subject` / `-S` | string | - | Subject image path (required for `replace-scene`) |\n| `--scene` | string | - | Scene image path (one of `--scene` or `--scene-prompt` for `replace-scene`) |\n| `--scene-prompt` | string | - | Scene text description (one of `--scene` or `--scene-prompt` for `replace-scene`) |\n| `--subject-type` | string | `auto` | Subject type for `replace-scene`: `auto` / `portrait` / `pet` / `product` |\n| `--reference-strength` | float | 0.85 | How strongly Seedream preserves the subject |\n| `--watermark` | flag | false | Add Seedream watermark (default OFF) |\n| `--json` | flag | false | Emit JSON result envelope on stdout. Combine with `--batch` (or piped stdin) for JSON batch input. |\n| `--batch` / `-b` | string | - | JSON file for batch operations |\n\n### JSON Batch Format\n\n```json\n{\n  \"operations\": [\n    {\"task\": \"remove-object\", \"image\": \"a.jpg\", \"prompt\": \"Remove the person\", \"output\": \"a_out.jpg\"},\n    {\"task\": \"restore\", \"image\": \"b.jpg\", \"output\": \"b_out.jpg\"},\n    {\"task\": \"resize\", \"image\": \"c.jpg\", \"output\": \"c_small.jpg\", \"width\": 800}\n  ]\n}\n```\n\n---\n\n## Changelog\n\n### 1.5.0 — 2026-07-19\n\n**New `replace-scene` parameters**\n- `--position {left,center,right}` — controls horizontal placement of the subject in the generated scene. Feeds into the scene-prompt as a positional hint so Seedream places the subject accordingly.\n- `--scale {close,medium,full}` — controls subject framing (特写/中景/全身). Feeds into the scene-prompt as a framing hint.\n\n**R2 large-file upload for Seedream reference images**\n- When a reference image exceeds 1.5 MB, the skill can upload to Cloudflare R2 and pass the public URL to Seedream instead of embedding a base64 data URI.\n- Requires self-deployed Cloudflare R2 Worker + `SEEDREAM_UPLOAD_TOKEN` and `SEEDREAM_UPLOAD_WORKER_URL` env vars.\n- Without R2 configured, large images gracefully fall back to base64 data URI.\n\n### 1.4.0 — 2026-07-14\n\n**New feature: `replace-scene` task**\nAdds a new AI-driven task that places a subject (portrait / pet / product) into\na new scene using Seedream's multi-reference image fusion. Wraps 豆包 app's\n\"多图融合\" + \"换场景\" feature.\n- New `--subject` (alias of `--image` for this task) + mutually-exclusive\n  `--scene` (image) or `--scene-prompt` (text) input pair.\n- `--subject-type {auto,portrait,pet,product}` selects a per-type prompt\n  template and reference_strength. `auto` uses filename keyword + corner\n  solidity heuristics.\n- `--watermark` defaults to OFF (most uses are product / academic).\n- New `_call_seedream(reference_images=...)` parameter — passes a JSON array\n  of data URIs to Seedream (which accepts up to 14 reference images).\n- Subject image is auto-resized to 2048px max side; temp files are cleaned up.\n- Returns `info.generation_time_s` extracted from Seedream's metadata for\n  quota tracking.\n\n**Bug fixes (incidental, surfaced by v1.4.0 testing)**\n- `process_batch` now normalizes dashed JSON keys (`scene-prompt` →\n  `scene_prompt`, `target-kb` → `target_kb`, `subject-type` → `subject_type`,\n  `no-maintain-aspect` → `no_maintain_aspect`) before unpacking into\n  `process(**op)`. Previously these were silently dropped into the trailing\n  `**kwargs` and the real parameter received its default — a very confusing\n  failure mode (especially for `target-kb` where the result was a wildly\n  different file size than requested).\n- `process()` now translates `no_maintain_aspect=True` (from JSON batch) to\n  `maintain_aspect=False` (the inverted semantics the `op_resize` function\n  expects), mirroring the same translation `main()` does for the CLI.\n\n**Docs**\n- New section 11 \"Scene Replacement\" with 6 worked examples, full argument\n  table, validation rules, auto-detection logic, and JSON batch format.\n- Updated Tool Selection Policy + Per-task defaults tables to include\n  `replace-scene`.\n- Updated Unified API Interface task list.\n\n### 1.3.4 — 2026-07-14\n\n**ImageMagick argument fix**\n- `op_resize` / `op_crop` / `op_color_adjust` / `op_remove_background` (ImageMagick fallback): all ImageMagick CLI arguments are now passed as separate list elements instead of single space-joined strings. Previously ImageMagick would reject commands like `-resize 800x800>` because the flag and value were concatenated into one string.\n\n**HDR bilateral saturation fix**\n- `_tonemap_bilateral` no longer performs a pseudo-HSV operation directly on BGR channels (which corrupted colors). Now uses proper `cv2.cvtColor(BGR→HSV)` → boost saturation → `cv2.cvtColor(HSV→BGR)`.\n\n**Background removal fallback fix**\n- `remove_bg.sh` ImageMagick fallback: corrected `matte` floodfill coordinates (was passing RGB values as coordinates; now uses `0,0`). Removed erroneous `-alpha extract` which turned output into a pure alpha mask.\n- `edit.py` ImageMagick fallback: replaced `-trim` (which merely cropped edges) with `-transparent <detected-bg-color>` so the result is actually a transparent-background image.\n\n**Runtime robustness**\n- `op_remove_background` now probes both `$PATH` and the team venv (`venv-clawd/bin/rembg`) for `rembg`, matching Laoguo's actual deployment environment.\n- `_call_seedream` guards against `shutil.copyfile(local, output_path)` when source and destination are the same file (would truncate to zero bytes).\n- `_save_with_quality` now derives the actual output format from the file extension, preventing OpenCV warnings when `--format` and `--output` disagree (e.g. `--output foo.webp --format png`).\n\n**CLI**\n- Added `--no-maintain-aspect` flag for `resize` task to allow non-proportional stretching.\n\n### 1.3.3 — 2026-06-13\n\n**Tool selection policy**\n- Codified the routing policy (see \"Tool Selection Policy\" near the top of this file): Seedream first for semantic / generative edits, deterministic tools first for mechanical edits.\n- `op_remove_object` no longer keyword-sniffs the prompt for \"wire / cable / line / spot / dust / scratch\" and silently routes to a stub. `--tool auto` now picks Seedream when available; the OpenCV branch surfaces an actionable redirect to `scripts/inpaint.py` for known-geometry cases.\n- The redirect message also lists the most common `inpaint.py` invocations (`--type spot`, `--type wire`, `--type rect`) so users have a clear next step instead of a guess.\n\n### 1.3.2 — 2026-06-13\n\n**Bug fixes**\n- `op_resize` / `op_crop` / `op_color_adjust` no longer raise `TypeError: got an unexpected keyword argument 'mode'`. The CLI's `--mode` flag is now only forwarded for `hdr-tonemap`. (Was reported as \"numpy 2.x compat issue\"; root cause was kwargs leakage.)\n- `smart-compress --target-kb` no longer crashes with `No such file or directory: foo.q55.tmp`. The binary-search probe file now uses the format's real extension (`.jpg/.png/.webp`) so OpenCV can pick a codec.\n- `--quality` is now an actual CLI flag, declared in argparse and forwarded into `op_smart_compress` (was documented but unrecognized).\n- `--json` on a single-operation invocation now emits a JSON envelope on stdout instead of blocking on stdin. Batch input is still accepted via `--batch FILE` or piped stdin.\n- Markdown code fence around the AI-method / OpenCV-method examples is correctly paired (was rendered with broken nesting).\n- `compatibility` frontmatter key moved under `metadata.compatibility` (was rejected by the OpenClaw skill validator as an unknown top-level key).\n- `_tonemap_shadows` annotation corrected from `np.float32` to `np.ndarray`.\n\n**Seedream bridge rewrite**\nThe previous integration referenced a non-existent `bin/generate.sh` and a non-existent Python module. `_call_seedream` now invokes `node scripts/generate.js` with `--prompt`, `--mode image-to-image`, `--reference_images <data-URI JSON array>`, `--reference_strength`, and `--optimize false`, parses the JSON envelope from stdout, locates the first `download_success` image, and stages its `local_path` to the caller's `output_path`. Local file paths are encoded as `data:image/<type>;base64,<...>` data URIs because Seedream's validator only accepts HTTP URLs or data URIs. Verified end-to-end with a real ARK API call (200×200 input → 2048×2048 generated output, ~30 s).\n\n**Docs**\n- Added \"Python Interpreter\" section: all scripts hard-shebang the team venv (`~/.openclaw/venv-clawd/bin/python`); running them under system Python will spuriously report `piexif/exif/rembg` as missing.\n- `--quality` and `--json` table entries clarified.\n\nFile v1.5.1:README.md\n\n# Smart Photo Editor - Quick Start Guide\n\nAI-powered photo editing and restoration skill for OpenClaw.\n\n## Quick Start\n\n### ⭐ Recommended: Unified CLI (`edit.py`)\n```bash\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the power cable\" --output out.jpg\n```\n\n### Remove Object from Photo\n```\n\"Use smart-photo-editor to remove the power cable from this mountain photo\"\n```\n→ Automatically uses Seedream AI for complex scenes\n\n### Restore Old Photo\n```\n\"Use smart-photo-editor to restore this old photo\"\n```\n→ Removes scratches, enhances clarity, restores colors\n\n### Remove Background\n```\n\"Use smart-photo-editor to remove the background from this portrait\"\n```\n→ Uses rembg (if installed) or falls back to ImageMagick\n\n### Remove Diagonal/Angled Lines (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n```\n\n### Remove Watermark/Logo Region (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n```\n\n### Remove Multiple Spots/Lines (Batch Mode)\n```bash\n# Multiple spots in one command\n./scripts/inpaint.py input.jpg output.jpg --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Multiple lines in one command\n./scripts/inpaint.py input.jpg output.jpg --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py input.jpg output.jpg --type batch --batch tasks.json\n```\n\n### Resize for API Compatibility\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type resize --max-dim 2048\n```\n\n### Portrait Retouching\n```bash\n# All enhancements at once\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing + eye brightening\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n\n# Face brightness + contrast adjustment\n./scripts/portrait.py input.jpg output.jpg --brightness 10 --contrast 15\n```\n\n### EXIF Utilities\n```bash\n./scripts/exif_utils.py read photo.jpg        # Read EXIF tags\n./scripts/exif_utils.py strip photo.jpg -o out.jpg  # Remove EXIF\n./scripts/exif_utils.py copy src.jpg dst.jpg  # Copy EXIF to another image\n```\n\n### Smart Auto-Crop\n```bash\n./scripts/smart_crop.py input.jpg output.jpg               # Auto-detect salient region\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9 # Crop to aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --debug      # Generate debug overlay\n```\n\n### Additional OpenCV Operations (denoise / sharpen / adjust)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type denoise --strength 15\n./scripts/inpaint.py input.jpg output.jpg --type sharpen --strength 1.5\n./scripts/inpaint.py input.jpg output.jpg --type adjust --brightness 15 --contrast 10 --gamma 0.9\n```\n\n## Features\n\n| Feature | Best Tool | Quality |\n|---------|-----------|---------|\n| Object removal | Seedream AI | Excellent |\n| Old photo restoration | Seedream AI | Excellent |\n| Background removal | rembg AI | Excellent |\n| Solid background removal | ImageMagick | Good (fast) |\n| Wire/line removal | OpenCV | Good (fast) |\n| Sensor dust removal | OpenCV | Good (fast) |\n| Batch multi-region | OpenCV | Good (fast) |\n| Portrait retouching | OpenCV | Good |\n| Skin smoothing | OpenCV bilateral | Good |\n| Smart auto-crop | OpenCV saliency | Good |\n| Denoise / sharpen / adjust | OpenCV | Good |\n| Resize/crop/compress | ImageMagick | Excellent |\n| Color adjustment | ImageMagick | Excellent |\n| EXIF preservation | piexif/exif | — |\n\n## Skill File Structure\n\n```\n~/.openclaw/skills/smart-photo-editor/\n├── SKILL.md              # Full documentation\n├── README.md             # This file\n├── scripts/\n│   ├── edit.py           # ⭐ Unified CLI (all operations)\n│   ├── inpaint.py        # OpenCV wire/spot/line/rect/denoise/sharpen/adjust\n│   ├── portrait.py       # Portrait retouching (skin, eyes, teeth)\n│   ├── smart_crop.py     # Smart auto-crop based on saliency detection\n│   ├── exif_utils.py     # EXIF read/strip/copy utility\n│   └── remove_bg.sh      # Background removal wrapper\n└── examples/             # Before/after comparison examples (add your own)\n```\n\n## Tips\n\n1. **Large images** are automatically handled - no more \"image too large\" errors\n2. **Chinese prompts work** - the skill automatically translates to optimized English\n3. **Automatic fallback** - if Seedream fails, OpenCV will be tried for simple cases\n4. **EXIF preserved** - all editing scripts preserve camera metadata automatically\n5. **Face auto-detection** - portrait retouching automatically finds faces for targeted edits\n6. **Smart crop** - automatically finds the most interesting region in any image\n\n## Install Optional rembg\n\nFor better AI background removal:\n```bash\nsource ~/.openclaw/venv-clawd/bin/activate\npip install rembg\n```\n\nFile v1.5.1:_meta.json\n\n{\n  \"ownerId\": \"kn7b21fme4bx0xwpm700dj5ehh82zrgq\",\n  \"slug\": \"smart-photo-editor\",\n  \"version\": \"1.5.1\",\n  \"publishedAt\": 1784884499218\n}\n\nFile v1.5.1:skill-card.md\n\n## Description: <br>\nAI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[guoxh](https://clawhub.ai/user/guoxh) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to edit, retouch, restore, crop, compress, and remove objects or backgrounds from photos through AI-assisted and deterministic image-processing workflows. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Some AI edits send images to external AI services. <br>\nMitigation: Avoid highly sensitive photos unless external processing is acceptable for the use case. <br>\nRisk: Outputs preserve EXIF metadata by default, which can expose camera, timestamp, device, or location-related details. <br>\nMitigation: Strip EXIF metadata before sharing outputs when those details matter. <br>\nRisk: Large reference image handling can use a user-configured Cloudflare R2 worker. <br>\nMitigation: Use only a trusted R2 worker and token configuration, or leave R2 disabled and accept the documented data-URI fallback limits. <br>\n\n\n## Reference(s): <br>\n- [Smart Photo Editor on ClawHub](https://clawhub.ai/guoxh/skills/smart-photo-editor) <br>\n- [VolcEngine Ark Seedream setup documentation](https://www.volcengine.com/docs/82379/2375486) <br>\n- [Cloudflare R2 documentation](https://developers.cloudflare.com/r2/) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Guidance, Shell commands, Configuration, Files] <br>\n**Output Format:** [Markdown with inline bash code blocks, file paths, and optional JSON status from bundled scripts] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Can produce edited image files; some AI edits may use external services and optional large-file upload configuration.] <br>\n\n## Skill Version(s): <br>\n1.5.1 (source: server evidence and _meta.json) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.5.0: 10 files, 64102 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (86796b), scripts/exif_utils.py (13253b), scripts/inpaint.py (21020b), scripts/portrait.py (28801b), scripts/remove_bg.sh (2903b), scripts/smart_crop.py (19750b), skill-card.md (2782b), SKILL.md (41534b)\n\nFile v1.5.0:SKILL.md\n\n---\nname: smart-photo-editor\nlicense: MIT\ndescription: |\n  AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nmetadata:\n  author: Team\n  version: \"1.5.0\"\n  category: ai/image-editing\n  compatibility: Requires Node.js 18+ and network access to VolcEngine Ark API (with Seedream model enabled) for AI features.\n---\n\n# Smart Photo Editor Skill\n\nAI-powered photo editing and restoration skill for OpenClaw. Unifies Seedream (AI edits), ImageMagick (basic edits), and OpenCV (programmatic fixes) into one intuitive workflow.\n\n## Overview\n\nAll-in-one intelligent photo editing skill - automatically selects the best tool for each image processing task.\n\n✨ **Key Advantages:**\n- ✅ **Smart Tool Selection** - Automatically chooses Seedream / ImageMagick / OpenCV based on task\n- ✅ **Unified Interface** - All operations use the same calling pattern\n- ✅ **Bilingual Support** - Optimized prompts for both Chinese and English contexts\n- ✅ **Automatic Fallback** - Switches to backup tools if primary tool fails\n- ✅ **Large Image Auto-Handling** - Avoids \"image too large\" API errors\n\n## Feature Availability\n\nThis skill provides two tiers of functionality:\n\n### ✅ Works out of the box (no extra dependencies)\n\nThese features only require ImageMagick and/or OpenCV (both widely available on Linux/macOS):\n\n- **Resize / Crop / Smart-crop** — dimension changes, aspect-ratio-preserving scaling\n- **Color adjustment** — brightness, contrast, saturation, grayscale\n- **Perspective correction** — 4-point skew/warp correction\n- **Smart compression** — quality targeting, binary-search for target file size\n- **HDR tonemapping** — log/bilateral/shadow/highlight recovery\n- **Background removal (basic)** — solid-color background removal via ImageMagick\n- **Geometric inpainting** — wire/line/rect removal with known coordinates (`inpaint.py`)\n\n### 🔒 Requires Seedream skill (AI features)\n\nThese features require the `byted-ark-seedream-skill` (VolcEngine Ark Agent Plan, managed skill):\n\n- **Object removal (natural language)** — remove objects described in text (people, vehicles, watermarks)\n- **Old photo restoration** — AI scratch/dust/fading repair\n- **Scene replacement (`replace-scene`)** — put subject into a new scene via multi-reference fusion\n- **Background removal (AI)** — rembg-based, or Seedream-based for complex edges\n\n> **Note:** The `byted-ark-seedream-skill` is an OpenClaw managed skill that requires a VolcEngine Ark account with the Seedream model enabled. Install with `openclaw skills install byted-ark-seedream-skill`.\n\n---\n\n## Trigger Conditions\n\nActivates automatically when users mention keywords like:\n- photo editing, edit image, retouch, smart photo edit\n- remove object, delete object, erase, remove person, remove watermark, remove logo, 去除, 消除\n- remove background, background removal, cutout, 抠图, 换背景\n- restore, fix, old photo restoration, repair, 修复老照片, 老照片修复\n- portrait retouching, portrait edit, smooth skin, whiten teeth, enhance eyes, remove blemish, red eye, 美颜, 人像精修, 红眼\n- replace scene, change scene, put subject in, 换场景, 多图融合\n- color adjustment, color correction, color grading, brightness, 调色, 色彩调整\n- crop, resize, compress, auto crop, smart crop, 裁剪, 自动裁剪, 智能裁剪\n- perspective, fix skew, flatten, perspective correct, 透视矫正, 视角矫正\n- hdr, tonemap, highlight recovery, shadow recovery, 高动态, 阴影增强\n- sharpen, denoise, 锐化, 降噪\n\n---\n\n## Tool Selection Policy\n\nThe skill mixes three classes of tool. Picking the right one for each task is\nwhat makes the unified entry-point useful, so the routing is explicit:\n\n**Use Seedream first for semantic / generative edits.**\n- Object removal in complex scenes (people, vehicles, watermarks, signs)\n- Old-photo restoration (scratches, fading, color loss)\n- Background replacement / scene swap\n- Subjective enhancement: “make this look better / natural / cinematic”\n- Edits where the model must infer missing visual content\n- Natural-language requests, especially in Chinese\n\nFor these, Seedream is the value-add. OpenCV/ImageMagick can’t compete on\nquality, and a deterministic tool can’t “invent” plausible content.\n\n**Use deterministic tools first for mechanical edits.**\n- Resize, crop, format conversion\n- Compression / quality targeting\n- Brightness, contrast, saturation, gamma adjustments\n- Geometric inpainting when coordinates are known (wires, dust spots,\n  exact rectangles — call `inpaint.py` directly)\n- Batch operations where reproducibility matters\n\nFor these, Seedream would be slower, costlier, and less predictable.\n\n**Encoded policy (auto mode):**\n```text\nsemantic edit / restoration / object removal       → Seedream first; deterministic fallback\nmechanical edit / resize / crop / compress / color → deterministic tools first\nuser explicitly asks for AI / natural restoration  → Seedream\nuser explicitly forces a tool with --tool ...      → honored verbatim\n```\n\n**Per-task defaults (`--tool auto`):**\n\n| Task | Default | Notes |\n|------|---------|-------|\n| `remove-object` | **Seedream** | OpenCV branch only fires when Seedream is unavailable; redirects to `inpaint.py` for known-geometry cases |\n| `restore` | **Seedream** | Seedream-only operation by design |\n| `remove-background` | **rembg** | ImageMagick fallback for solid-color backgrounds when rembg is missing |\n| `resize` / `crop` / `color-adjust` | **OpenCV/ImageMagick** | Deterministic, instant, free |\n| `smart-compress` | **OpenCV** | Content-aware quality + format selection |\n| `perspective-correct` | **OpenCV** | Document/whiteboard correction |\n| `hdr-tonemap` | **OpenCV** | All four modes (auto / bilateral / log / shadows) are deterministic |\n| `replace-scene` | **Seedream** | AI-only; no deterministic fallback (would produce poor results). If Seedream is unavailable, returns error directing user to install the Seedream skill. |\n\nOverride with `--tool seedream | opencv | imagemagick | rembg`.\n\n---\n\n## Installation & Dependencies\n\n### Standard Installation Path\n`~/.openclaw/skills/smart-photo-editor/`\n\n### Python Interpreter\nAll Python scripts (`scripts/*.py`) use a portable `#!/usr/bin/env python3` shebang.\n\nYou can run them directly:\n\n```bash\n./scripts/edit.py --help\n```\n\nOr explicitly with your Python of choice (e.g. a virtualenv where you have\ninstalled the dependencies below):\n\n```bash\npython3 scripts/edit.py --help\n```\n\n**Make sure the Python interpreter you use has the required dependencies**\n(OpenCV, Pillow, NumPy). Optional deps (`piexif`, `exif`, `rembg`) add extra\nfeatures; the skill will gracefully skip those features if they are missing.\n\n```bash\n# Sanity check — required deps\\python3 -c \"import cv2, numpy, PIL; print('core deps ok')\"\n\n# Sanity check — full deps (includes optional rembg/piexif/exif)\npython3 -c \"import cv2, numpy, PIL, piexif, exif, rembg; print('all deps ok')\"\n```\n\n### Required & Optional Dependencies\n| Dependency | Required | Purpose | Installation |\n|------------|----------|---------|--------------|\n| **byted-ark-seedream-skill** | ✅ Required | AI object removal, old photo restoration, image-to-image editing | Requires VolcEngine Ark API access. Follow [official setup guide](https://www.volcengine.com/docs/82379/2375486) to enable Seedream model access |\n| **imagemagick** | ✅ Required | Basic image editing (resize, crop, format conversion, color adjustments) | `sudo apt install imagemagick` (Debian/Ubuntu) or `brew install imagemagick` (macOS) |\n| **opencv-python-headless** | ✅ Required | Wire removal, spot removal, image resizing | `pip install opencv-python-headless` |\n| **rembg** | ⚠️ Optional | AI-powered background removal (better results for complex scenes) | `pip install rembg` |\n| **piexif** | ⚠️ Optional | EXIF metadata preservation during edits | `pip install piexif` |\n| **exif** | ⚠️ Optional | Extended EXIF tag reading | `pip install exif` |\n\n### Install Optional Dependencies\n```bash\nsource ~/.openclaw/venv-clawd/bin/activate\npip install rembg piexif exif\n```\n\n### Cloudflare R2 Upload (Large Reference Images)\n\nWhen a reference image (subject or scene image) exceeds **1.5 MB**, the skill can upload it to Cloudflare R2 instead of embedding it as a base64 data URI. This avoids hitting Seedream API payload size limits.\n\n**R2 is optional.** Without configuration, large images fall back to base64 data URI (which may fail for very large files due to CLI argument limits).\n\n**To enable R2 upload, deploy your own Cloudflare Worker:**\n\n1. Create a Cloudflare R2 bucket and a Worker that accepts PUT requests (see the [Cloudflare R2 documentation](https://developers.cloudflare.com/r2/))\n2. Set the following environment variables:\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `SEEDREAM_UPLOAD_TOKEN` | ✅ Yes | Bearer token for your R2 upload worker. |\n| `SEEDREAM_UPLOAD_WORKER_URL` | ✅ Yes | Your worker URL, e.g. `https://your-worker.your-subdomain.workers.dev`. |\n\n```bash\n# Add to your shell profile or ~/.openclaw/.env\nexport SEEDREAM_UPLOAD_TOKEN=\"your-token-here\"\nexport SEEDREAM_UPLOAD_WORKER_URL=\"https://your-worker.your-subdomain.workers.dev\"\n```\n\nWithout both variables, large images gracefully fall back to the data URI path (works for most cases; may hit CLI arg limits for very large multi-image batches).\n\n### VolcEngine Ark Setup\nFor AI editing features (object removal, photo restoration), ensure:\n1. You have a VolcEngine Ark account with API access\n2. The Seedream (豆包生图) model is enabled for your account\n3. Your OpenClaw configuration has valid VolcEngine API credentials\n\nSee the [official VolcEngine Ark documentation](https://www.volcengine.com/docs/82379/2375486) for detailed setup instructions.\n\n---\n\n## Core Features & Implementation\n\n### 1. Object Removal\n**Primary Tool:** Seedream Image-to-Image  \n**Fallback Tool:** OpenCV Inpainting (small scratches/lines)\n\n**Usage:**\n```bash\n# AI method (recommended) - complex scenes\nimage_generate \\\n  model=\"byted-ark-seedream-skill\" \\\n  mode=\"image-to-image\" \\\n  image=\"/path/to/photo.jpg\" \\\n  reference_strength=0.85 \\\n  prompt=\"Remove the [object description] located at [location description]. Restore the seamless texture, keep everything else exactly the same.\"\n```\n\n**OpenCV method** — simple lines/minor imperfections:\n```bash\n# Remove horizontal wire\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type wire --y 760 --thickness 10\n\n# Remove diagonal/angled line (supports any angle)\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n\n# Remove rectangular region (watermarks, logos, text)\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n\n# Remove multiple sensor dust spots in one command\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Remove multiple lines in one command\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py /path/to/photo.jpg /path/to/output.jpg \\\n  --type batch --batch tasks.json\n\n# JSON config example (tasks.json):\n# {\n#   \"operations\": [\n#     {\"type\": \"spot\", \"x\": 100, \"y\": 150, \"radius\": 8},\n#     {\"type\": \"spot\", \"x\": 200, \"y\": 300, \"radius\": 10},\n#     {\"type\": \"wire\", \"y\": 500, \"thickness\": 5},\n#     {\"type\": \"rect\", \"x\": 50, \"y\": 50, \"w\": 200, \"h\": 50, \"feather\": 10}\n#   ]\n# }\n```\n\n**Algorithm Selection:**\n- `ns` (Navier-Stokes) - Better for textures and larger regions (default for wire/line)\n- `telea` (Telea) - Faster, better for small regions (default for spot)\nUse `--algo ns` or `--algo telea` to override the default selection.\n\n**Prompt Optimization Examples:**\n- \"Remove the black power cable at the bottom of the image\" → \"Remove the thin black horizontal power cable at the bottom 20% of the image. Restore the mountain texture seamlessly, keep everything else exactly the same.\"\n- \"Remove the pedestrian in the middle\" → \"Remove the pedestrian in the center. Fill with matching background texture naturally.\"\n\n---\n\n### 2. Background Removal\n**Primary Tool:** rembg (AI)  \n**Fallback Tool:** ImageMagick (inline – solid color backgrounds)\n\n**Usage:**\n```bash\n# rembg AI method (complex backgrounds)\nrembg i input.jpg output.png\n\n# ImageMagick method (solid color backgrounds)\n./scripts/remove_bg.sh input.png output.png 20 \"#FFFFFF\"\n```\n\n---\n\n### 3. Old Photo Restoration\n**Primary Tool:** Seedream Image-to-Image\n\n**Usage:**\n```bash\nimage_generate \\\n  model=\"byted-ark-seedream-skill\" \\\n  mode=\"image-to-image\" \\\n  image=\"/path/to/old_photo.jpg\" \\\n  reference_strength=0.7 \\\n  prompt=\"Restore this old photo. Remove all scratches, dust spots, and damage. Enhance clarity and contrast. Restore natural, vivid colors while preserving the original photo's character. Do not change the composition or subjects.\"\n```\n\n---\n\n### 4. Basic Editing\n**Primary Tool:** ImageMagick + OpenCV\n\n**Common Commands:**\n```bash\n# Resize\nconvert input.jpg -resize 1920x1920\\> output.jpg\n\n# Crop\nconvert input.jpg -crop 800x600+100+50 output.jpg\n\n# Format conversion + compression\nconvert input.png -quality 85 output.webp\n\n# Color adjustment\nconvert input.jpg -brightness-contrast 10x5 output.jpg  # Brighter, higher contrast\nconvert input.jpg -modulate 100,130,100 output.jpg      # Increase saturation\nconvert input.jpg -grayscale Rec709Luma output.jpg      # Convert to B&W\n```\n\n**OpenCV Operations (inpaint.py):**\n```bash\n# Denoise (reduce noise in low-light photos)\n./scripts/inpaint.py input.jpg output.jpg --type denoise --strength 15\n\n# Sharpen (enhance edges and focus)\n./scripts/inpaint.py input.jpg output.jpg --type sharpen --strength 1.5\n\n# Brightness/contrast/gamma adjustment\n./scripts/inpaint.py input.jpg output.jpg --type adjust --brightness 15 --contrast 10 --gamma 0.9\n```\n\n### 5. Portrait Retouching\n**Primary Tool:** OpenCV (face detection + image processing)  \n**Dependencies:** `opencv-python-headless` (already required)\n\nPortrait retouching provides face-aware enhancements for portrait photography:\n- **Skin smoothing** — bilateral filter preserves edges while softening skin\n- **Red-eye removal** — detects and corrects flash red-eye\n- **Teeth whitening** — targets lower-face region, preserves surrounding\n- **Eye enhancement** — brightens and sharpens eyes\n- **Face brightness/contrast** — applies adjustments only to detected face\n- **Blemish removal** — removes small spots using inpainting\n- **Skin tone enhancement** — warm, healthy color correction\n\n```bash\n# Skin smoothing only\n./scripts/portrait.py input.jpg output.jpg --smooth 3\n\n# All enhancements (balanced)\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle preset (conservative)\n./scripts/portrait.py input.jpg output.jpg --subtle\n\n# Custom combination\n./scripts/portrait.py input.jpg output.jpg \\\n  --smooth 2 --enhance-eyes --whiten-teeth 0.3 --brightness 10\n\n# JSON output\n./scripts/portrait.py input.jpg output.jpg --all --json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--smooth` | Skin smoothing strength 1-10 |\n| `--denoise` | Denoise strength 1-30 |\n| `--red-eye` | Remove flash red-eye |\n| `--whiten-teeth` | Teeth whitening strength 0.1-0.8 |\n| `--enhance-eyes` | Brighten/sharpen eyes |\n| `--brightness` | Face brightness -100 to 100 |\n| `--contrast` | Face contrast -100 to 100 |\n| `--gamma` | Face gamma correction 0.1-3.0 |\n| `--sharpen` | Sharpening strength 0.5-3.0 |\n| `--blemish-removal` | Remove small blemishes |\n| `--skin-tone` | Warm skin tone enhancement |\n| `--all` | Apply all enhancements (balanced) |\n| `--subtle` | Conservative all enhancements |\n| `--no-auto-detect` | Skip face/eye detection |\n| `--no-exif` | Do not preserve EXIF |\n| `--json` | JSON output mode |\n\n### 6. EXIF Preservation\n**Automatic:** All write operations preserve EXIF metadata by default  \n**Tool:** `scripts/exif_utils.py` — standalone EXIF utility\n\nAll editing scripts automatically preserve EXIF metadata from input to output.\n\n```bash\n# Read EXIF from an image\n./scripts/exif_utils.py read photo.jpg\n\n# Strip EXIF from an image\n./scripts/exif_utils.py strip photo.jpg -o output.jpg\n\n# Copy EXIF from one image to another\n./scripts/exif_utils.py copy source.jpg dest.jpg\n```\n\nSupported tags: Make, Model, DateTime, Orientation, Exposure Time, F-Number, ISO, Focal Length, Lens Model, and more.\n\n---\n\n### 7. Smart Crop (Auto-Crop)\n**Primary Tool:** OpenCV saliency detection + optional GrabCut refinement  \n**Dependencies:** `opencv-python-headless` (already required)\n\nAutomatically detects the most \"interesting\" region in an image and crops to it.\nUses OpenCV's StaticSaliencyFineGrained algorithm by default, with spectral and edge-based fallbacks.\n\n```bash\n# Auto-crop to salient region with default padding\n./scripts/smart_crop.py input.jpg output.jpg\n\n# Crop to specific aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9\n\n# Crop to 4:3 with 10% margin around subject\n./scripts/smart_crop.py input.jpg output.jpg --aspect 4/3 --padding 0.1\n\n# Resize to exact dimensions after smart crop\n./scripts/smart_crop.py input.jpg output.jpg --width 800 --height 600\n\n# Use GrabCut refinement for cleaner boundaries\n./scripts/smart_crop.py input.jpg output.jpg --grabcut\n\n# Generate debug saliency map overlay\n./scripts/smart_crop.py input.jpg output.jpg --debug\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--aspect`, `-a` | Aspect ratio (e.g. `16/9`, `4/3`, `1/1`) |\n| `--width`, `-w` | Target width in pixels |\n| `--height`, `-H` | Target height in pixels |\n| `--padding`, `-p` | Margin around subject (0.0-0.5, default 0.05) |\n| `--threshold`, `-t` | Saliency threshold 0.05-0.95 (default 0.3) |\n| `--algorithm` | `auto` / `finegrained` / `spectral` / `edge` |\n| `--grabcut`, `-g` | Use GrabCut to refine crop boundary |\n| `--debug`, `-d` | Generate debug saliency map overlay |\n\n### 8. Perspective Correction\n**Primary Tool:** OpenCV (auto-detection + warpPerspective)\n\nAuto-detects document/sheet borders using edge detection + contour analysis and corrects perspective distortion. Also supports manual corner specification.\n\n```bash\n# Auto-detect and correct\n./scripts/edit.py --task perspective-correct --image doc.jpg --output flat.jpg\n\n# With manual corners (top-left, top-right, bottom-right, bottom-left)\n./scripts/edit.py --task perspective-correct --image doc.jpg --output flat.jpg \\\n  --corners \"100,50,600,50,600,800,100,800\"\n\n# Batch JSON\n./scripts/edit.py --json < tasks.json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--corners` | 4 points as CSV `x1,y1,x2,y2,x3,y3,x4,y4` (TL,TR,BR,BL). Omit for auto-detection |\n\n**Algorithm:** Adaptive threshold → contour detection → largest 4-point quadrilateral → perspective transform.\n\n---\n\n### 9. Intelligent Compression\n**Primary Tool:** OpenCV (content analysis + format-specific encoding)\n\nContent-aware image compression using entropy, edge density, and color variance analysis to auto-select the best format and quality.\n\n```bash\n# Auto-select best format and quality\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.jpg\n\n# Target file size (auto binary-searches quality)\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.jpg --target-kb 200\n\n# Force WebP with specific quality\n./scripts/edit.py --task smart-compress --image photo.jpg --output optimized.webp \\\n  --format webp --quality 85\n\n# Batch JSON\n./scripts/edit.py --json < tasks.json\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--target-kb` | Target output size in KB (enables binary-search for optimal quality) |\n| `--format` | Force output: `jpeg` | `png` | `webp` |\n\n**Auto-decision logic:**\n- **JPEG** — high entropy (>6.5) + dense edges → complex photographic content\n- **PNG** — low color variance (<500) + low edges → flat graphics/screenshots; or alpha channel detected\n- **Quality** — auto-selected based on entropy (65–92) unless `--target-kb` is specified\n\n---\n\n### 10. HDR / Tonemapping\n**Primary Tool:** OpenCV (multi-scale bilateral decomposition + CLAHE)\n\nHDR-style tone mapping to enhance dynamic range on single images. Uses bilateral filter decomposition to separate illumination from detail, compress the illumination layer's dynamic range, then recombine — producing natural-looking highlight/shadow recovery.\n\n```bash\n# Auto mode (default — picks best method based on image analysis)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg\n\n# Bilateral mode — detail-preserving compression (best for most photos)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode bilateral --strength 1.2\n\n# Log mode — fast global compression (good for screenshots/graphics)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode log --gamma 2.2\n\n# Shadows mode — lighten dark regions (backlit photos)\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode shadows --strength 1.5\n\n# Highlight mode — compress blown highlights\n./scripts/edit.py --task hdr-tonemap --image photo.jpg --output hdr_enhanced.jpg --mode highlight --strength 1.2\n```\n\n| Parameter | Description |\n|-----------|-------------|\n| `--mode` | auto / bilateral / log / shadows / highlight (default: auto) |\n| `--strength` | Enhancement strength 0.1-2.0 (default: 1.0) |\n| `--gamma` | Gamma value for log mode (default: 2.2) |\n\n**Algorithm:** Bilateral filter decomposition — base (illumination) layer compressed with S-curve; detail layer preserved and boosted; adaptive saturation adjustment.\n\n---\n\n### 11. Scene Replacement\n**Primary Tool:** Seedream multi-reference image fusion (AI-only, no deterministic fallback)\n\nPlace a subject (portrait / pet / product) into a new scene using Seedream's\nmulti-reference image fusion. Wraps 豆包 app's \"多图融合\" + \"换场景\" feature.\n\n**Requires:** the `byted-ark-seedream-skill` (this task is AI-only; an\nOpenCV/ImageMagick fallback would produce poor results and is intentionally\nomitted).\n\n**Usage:**\n```bash\n# 1) Subject + scene image (most common)\n./scripts/edit.py --task replace-scene \\\n    --subject photo.jpg --scene cafe.png --output out.jpg\n\n# 2) Subject + text-only scene description\n./scripts/edit.py --task replace-scene \\\n    --subject pet.jpg --scene-prompt \"阳光下的草地\" --output out.jpg\n\n# 3) Product photo into lifestyle scene\n./scripts/edit.py --task replace-scene \\\n    --subject product.png --scene lifestyle.jpg --output out.jpg \\\n    --subject-type product\n\n# 4) Custom prompt override (full artistic control)\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene beach.jpg --output out.jpg \\\n    --prompt \"把人物放在黄昏海边沙滩，长发随风，光线偏暖，景深虚化\"\n\n# 5) Subject in center, close-up framing\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene studio.jpg --output out.jpg \\\n    --position center --scale close\n\n# 6) Full-body shot, subject on the right\n./scripts/edit.py --task replace-scene \\\n    --subject portrait.jpg --scene beach.jpg --output out.jpg \\\n    --position right --scale full\n\n# 7) JSON batch with position/scale\n./scripts/edit.py --json < tasks.json\n```\n\n**Argument table:**\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `--subject` / `-S` | path | ✅ | — | Subject image (portrait / pet / product) |\n| `--scene` | path | ⚠️ one of | — | Target scene image |\n| `--scene-prompt` | string | ⚠️ one of | — | Target scene text description (used if no scene image) |\n| `--subject-type` | enum | ❌ | `auto` | `auto` / `portrait` / `pet` / `product`. Selects prompt template + reference_strength. |\n| `--prompt` / `-p` | string | ❌ | (from template) | Override the default prompt |\n| `--reference-strength` | float | ❌ | 0.85 (portrait/pet) / 0.90 (product) | How strongly Seedream must preserve the subject. Higher = stricter. |\n| `--watermark` | flag | ❌ | `false` | Add Seedream watermark. Default OFF (most uses are product / academic). |\n| `--position` | enum | ❌ | `center` | Horizontal subject placement: `left` / `center` / `right`. Feeds into the scene-prompt as positional hint.\n| `--scale` | enum | ❌ | `medium` | Subject framing: `close` (特写) / `medium` (中景) / `full` (全身). Feeds into the scene-prompt as framing hint.\n| `--output-format` | enum | ❌ | follow subject | `jpeg` / `png` / `webp` |\n| `--output` / `-o` | path | ❌ | auto | Output path |\n\n**Validation rules:**\n- `--subject` is required.\n- **Exactly one** of `--scene` / `--scene-prompt` is required (both → error).\n- If `--scene-prompt` is given, it must be at least 3 characters.\n- Subject image is auto-resized to 2048px max side (existing API limit helper).\n\n**Subject-type auto-detection:**\nWhen `--subject-type auto` is passed (default), the skill uses two heuristics:\n1. **Filename keyword** — `pet/cat/dog/...` → `pet`; `portrait/selfie/face/...` → `portrait`; `product/item/bottle/...` → `product`\n2. **Corner solidity check** — if all 4 corners are within 15 RGB units, classified as `product` (typical product shot on flat backdrop)\n\nIf neither heuristic matches, falls back to `portrait` (most common case).\nFor certainty, always pass `--subject-type` explicitly.\n\n**JSON batch format:**\n```json\n{\n  \"operations\": [\n    {\"task\": \"replace-scene\", \"subject\": \"p1.jpg\", \"scene\": \"office.jpg\",\n     \"output\": \"p1_office.jpg\", \"subject-type\": \"portrait\"},\n    {\"task\": \"replace-scene\", \"subject\": \"p2.jpg\", \"scene-prompt\": \"雪山日落\",\n     \"output\": \"p2_mountain.jpg\", \"subject-type\": \"portrait\"},\n    {\"task\": \"replace-scene\", \"subject\": \"shoe.png\", \"scene\": \"running_track.jpg\",\n     \"output\": \"shoe_track.jpg\", \"subject-type\": \"product\", \"reference-strength\": 0.9}\n  ]\n}\n```\n\n**JSON batch key naming:** JSON keys use **underscores** (Python identifier\nconvention): `scene_prompt`, `subject_type`, `reference_strength`, etc. The\nCLI flags use dashes (`--scene-prompt`, `--subject-type`). The skill\n**automatically normalizes** dashed JSON keys to underscored ones, so both\nwork; use whichever is more natural for your tooling.\n\n**Output:**\nThe result JSON envelope includes a `generation_time_s` field (extracted from\nSeedream's own metadata) for quota tracking.\n\n---\n\n## Unified API Interface\n\n| Parameter | Type | Default | Required | Description |\n|-----------|------|---------|----------|-------------|\n| `task` | string | - | ✅ | Task type: `remove-object` / `remove-background` / `restore` / `resize` / `crop` / `color-adjust` / `perspective-correct` / `smart-compress` / `hdr-tonemap` / `replace-scene` |\n| `image` | string | - | ✅ | Input image path |\n| `prompt` | string | \"\" | ❌ | Object description/location (required for remove-object) |\n| `tool` | string | \"auto\" | ❌ | Force specific tool: `auto` / `seedream` / `imagemagick` / `opencv` / `rembg` |\n| `output_format` | string | \"jpeg\" | ❌ | Output format: jpeg / png / webp |\n| `quality` | integer | 95 | ❌ | Output quality (0-100) |\n\n---\n\n## Intelligent Decision Flow\n\n```\nUser request → Analyze task type\n    ↓\nObject removal? → Seedream (default) → Failed? → OpenCV fallback\n    ↓\nBackground removal? → Detect background → Solid? ImageMagick : rembg\n    ↓\nOld photo restoration? → Seedream (reference_strength=0.7)\n    ↓\nBasic editing? → ImageMagick\n```\n\n---\n\n## Examples\n\n### Remove Power Cable\n```\nTask: Remove the black power cable at the bottom of the image\nParameters:\n  task: remove-object\n  image: mountain.jpg\n  prompt: \"Remove the thin black horizontal power cable at the bottom 20% of the image. Restore the mountain texture seamlessly, keep everything else exactly the same.\"\n  tool: seedream\n```\n\n### Old Photo Restoration\n```\nTask: Restore this old photo\nParameters:\n  task: restore\n  image: old_photo.jpg\n  prompt: \"Remove scratches and dust spots, enhance clarity, restore natural colors\"\n```\n\n### Background Removal\n```\nTask: Remove background from portrait photo\nParameters:\n  task: remove-background\n  image: portrait.jpg\n  tool: auto\n```\n\n### Portrait Retouching\n```bash\n# Apply all portrait enhancements\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing and eye enhancement\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n```\n\n---\n\n## Error Handling & Fallbacks\n\n1. **Seedream API failure** → surface the Seedream error verbatim; for known-geometry cases use `scripts/inpaint.py` directly (`--type spot/wire/rect`) or pass `--tool opencv` to get the inpaint.py guidance message.\n2. **Seedream skill unavailable / `--tool opencv`** → `op_remove_object` returns an actionable redirect listing common `inpaint.py` invocations.\n3. **Image too large** → Auto-resize to 2048px max side, process, output.\n4. **rembg not installed** → Auto-fallback to ImageMagick remove-bg.\n5. **Unsupported format** → Auto-convert to JPEG for processing.\n\n---\n\n## Large Image Handling Strategy\n\n- Seedream API limit: ~2048px maximum side length\n- Auto-detect image dimensions, if exceeded:\n  1. Proportionally resize to 2048px max side\n  2. Perform editing operation\n  3. Output processed image\n- Prevents \"image too large\" errors\n\n---\n\n## Skill File Structure\n\n```\nsmart-photo-editor/\n├── SKILL.md              # This file\n├── README.md             # Quick start guide\n├── scripts/\n│   ├── edit.py           # ⭐ Unified CLI entry point (all operations)\n│   ├── inpaint.py        # OpenCV wire/spot/line/rect/denoise/sharpen/adjust\n│   ├── portrait.py        # Portrait retouching (skin, eyes, teeth, etc.)\n│   ├── smart_crop.py     # Smart auto-crop based on saliency detection\n│   ├── exif_utils.py     # EXIF read/strip/copy utility\n│   └── remove_bg.sh      # Background removal wrapper\n└── examples/             # Before/after comparison examples\n```\n\n---\n\n## Unified CLI (`edit.py`)\n\nThe recommended entry point for all photo editing operations.\n\n```bash\n# Object removal (AI)\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the person in the center\" --output out.jpg\n\n# Old photo restoration\n./scripts/edit.py --task restore --image old_photo.jpg --output restored.jpg\n\n# Background removal\n./scripts/edit.py --task remove-background --image portrait.png --output no_bg.png\n\n# Resize\n./scripts/edit.py --task resize --image photo.jpg --output small.jpg --width 800\n\n# Crop\n./scripts/edit.py --task crop --image photo.jpg --output crop.jpg \\\n  --x 100 --y 100 --width 400 --height 300\n\n# Color adjustment\n./scripts/edit.py --task color-adjust --image photo.jpg --output bright.jpg \\\n  --brightness 20 --saturation 30\n\n# Batch mode (JSON)\n./scripts/edit.py --json < batch_tasks.json\n```\n\n### Unified Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--task` | string | **required** | Operation: `remove-object`, `restore`, `remove-background`, `resize`, `crop`, `color-adjust`, `perspective-correct`, `smart-compress`, `hdr-tonemap` |\n| `--image` / `-i` | string | **required** | Input image path |\n| `--output` / `-o` | string | auto | Output path (default: `{input}.{task}{ext}`) |\n| `--prompt` / `-p` | string | - | Description for AI operations |\n| `--tool` / `-t` | string | `auto` | Force tool: `auto`, `seedream`, `opencv`, `imagemagick`, `rembg` |\n| `--width` / `-w` | int | - | Target width (resize/crop) |\n| `--height` / `-H` | int | - | Target height (resize/crop) |\n| `--max-dim` | int | - | Max dimension, maintains aspect (resize) |\n| `--x`, `--y` | int | - | Offset for crop |\n| `--brightness` | float | - | Brightness: -100 to 100 |\n| `--contrast` | float | - | Contrast: -100 to 100 |\n| `--saturation` | float | - | Saturation: -1 to 1 |\n| `--grayscale` | flag | false | Convert to grayscale |\n| `--corners` | string | - | Perspective corners: `x1,y1,x2,y2,x3,y3,x4,y4` (TL,TR,BR,BL) |\n| `--target-kb` | int | - | Target file size in KB (smart-compress quality search) |\n| `--format` | string | - | Output format: `jpeg` \\| `png` \\| `webp` |\n| `--mode` | string | auto | HDR tonemap mode: auto / bilateral / log / shadows / highlight |\n| `--strength` | float | 1.0 | Enhancement strength 0.1-2.0 (hdr-tonemap) |\n| `--gamma` | float | 2.2 | Gamma value for log mode (hdr-tonemap) |\n| `--quality` | int | auto | Output quality 1-100 (jpeg/webp; ignored when `--target-kb` is set) |\n| `--position` | string | - | Horizontal placement for `replace-scene`: `left` / `center` / `right` |\n| `--scale` | string | - | Framing for `replace-scene`: `close` / `medium` / `full` |\n| `--subject` / `-S` | string | - | Subject image path (required for `replace-scene`) |\n| `--scene` | string | - | Scene image path (one of `--scene` or `--scene-prompt` for `replace-scene`) |\n| `--scene-prompt` | string | - | Scene text description (one of `--scene` or `--scene-prompt` for `replace-scene`) |\n| `--subject-type` | string | `auto` | Subject type for `replace-scene`: `auto` / `portrait` / `pet` / `product` |\n| `--reference-strength` | float | 0.85 | How strongly Seedream preserves the subject |\n| `--watermark` | flag | false | Add Seedream watermark (default OFF) |\n| `--json` | flag | false | Emit JSON result envelope on stdout. Combine with `--batch` (or piped stdin) for JSON batch input. |\n| `--batch` / `-b` | string | - | JSON file for batch operations |\n\n### JSON Batch Format\n\n```json\n{\n  \"operations\": [\n    {\"task\": \"remove-object\", \"image\": \"a.jpg\", \"prompt\": \"Remove the person\", \"output\": \"a_out.jpg\"},\n    {\"task\": \"restore\", \"image\": \"b.jpg\", \"output\": \"b_out.jpg\"},\n    {\"task\": \"resize\", \"image\": \"c.jpg\", \"output\": \"c_small.jpg\", \"width\": 800}\n  ]\n}\n```\n\n---\n\n## Changelog\n\n### 1.5.0 — 2026-07-19\n\n**New `replace-scene` parameters**\n- `--position {left,center,right}` — controls horizontal placement of the subject in the generated scene. Feeds into the scene-prompt as a positional hint so Seedream places the subject accordingly.\n- `--scale {close,medium,full}` — controls subject framing (特写/中景/全身). Feeds into the scene-prompt as a framing hint.\n\n**R2 large-file upload for Seedream reference images**\n- When a reference image exceeds 1.5 MB, the skill can upload to Cloudflare R2 and pass the public URL to Seedream instead of embedding a base64 data URI.\n- Requires self-deployed Cloudflare R2 Worker + `SEEDREAM_UPLOAD_TOKEN` and `SEEDREAM_UPLOAD_WORKER_URL` env vars.\n- Without R2 configured, large images gracefully fall back to base64 data URI.\n\n### 1.4.0 — 2026-07-14\n\n**New feature: `replace-scene` task**\nAdds a new AI-driven task that places a subject (portrait / pet / product) into\na new scene using Seedream's multi-reference image fusion. Wraps 豆包 app's\n\"多图融合\" + \"换场景\" feature.\n- New `--subject` (alias of `--image` for this task) + mutually-exclusive\n  `--scene` (image) or `--scene-prompt` (text) input pair.\n- `--subject-type {auto,portrait,pet,product}` selects a per-type prompt\n  template and reference_strength. `auto` uses filename keyword + corner\n  solidity heuristics.\n- `--watermark` defaults to OFF (most uses are product / academic).\n- New `_call_seedream(reference_images=...)` parameter — passes a JSON array\n  of data URIs to Seedream (which accepts up to 14 reference images).\n- Subject image is auto-resized to 2048px max side; temp files are cleaned up.\n- Returns `info.generation_time_s` extracted from Seedream's metadata for\n  quota tracking.\n\n**Bug fixes (incidental, surfaced by v1.4.0 testing)**\n- `process_batch` now normalizes dashed JSON keys (`scene-prompt` →\n  `scene_prompt`, `target-kb` → `target_kb`, `subject-type` → `subject_type`,\n  `no-maintain-aspect` → `no_maintain_aspect`) before unpacking into\n  `process(**op)`. Previously these were silently dropped into the trailing\n  `**kwargs` and the real parameter received its default — a very confusing\n  failure mode (especially for `target-kb` where the result was a wildly\n  different file size than requested).\n- `process()` now translates `no_maintain_aspect=True` (from JSON batch) to\n  `maintain_aspect=False` (the inverted semantics the `op_resize` function\n  expects), mirroring the same translation `main()` does for the CLI.\n\n**Docs**\n- New section 11 \"Scene Replacement\" with 6 worked examples, full argument\n  table, validation rules, auto-detection logic, and JSON batch format.\n- Updated Tool Selection Policy + Per-task defaults tables to include\n  `replace-scene`.\n- Updated Unified API Interface task list.\n\n### 1.3.4 — 2026-07-14\n\n**ImageMagick argument fix**\n- `op_resize` / `op_crop` / `op_color_adjust` / `op_remove_background` (ImageMagick fallback): all ImageMagick CLI arguments are now passed as separate list elements instead of single space-joined strings. Previously ImageMagick would reject commands like `-resize 800x800>` because the flag and value were concatenated into one string.\n\n**HDR bilateral saturation fix**\n- `_tonemap_bilateral` no longer performs a pseudo-HSV operation directly on BGR channels (which corrupted colors). Now uses proper `cv2.cvtColor(BGR→HSV)` → boost saturation → `cv2.cvtColor(HSV→BGR)`.\n\n**Background removal fallback fix**\n- `remove_bg.sh` ImageMagick fallback: corrected `matte` floodfill coordinates (was passing RGB values as coordinates; now uses `0,0`). Removed erroneous `-alpha extract` which turned output into a pure alpha mask.\n- `edit.py` ImageMagick fallback: replaced `-trim` (which merely cropped edges) with `-transparent <detected-bg-color>` so the result is actually a transparent-background image.\n\n**Runtime robustness**\n- `op_remove_background` now probes both `$PATH` and the team venv (`venv-clawd/bin/rembg`) for `rembg`, matching Laoguo's actual deployment environment.\n- `_call_seedream` guards against `shutil.copyfile(local, output_path)` when source and destination are the same file (would truncate to zero bytes).\n- `_save_with_quality` now derives the actual output format from the file extension, preventing OpenCV warnings when `--format` and `--output` disagree (e.g. `--output foo.webp --format png`).\n\n**CLI**\n- Added `--no-maintain-aspect` flag for `resize` task to allow non-proportional stretching.\n\n### 1.3.3 — 2026-06-13\n\n**Tool selection policy**\n- Codified the routing policy (see \"Tool Selection Policy\" near the top of this file): Seedream first for semantic / generative edits, deterministic tools first for mechanical edits.\n- `op_remove_object` no longer keyword-sniffs the prompt for \"wire / cable / line / spot / dust / scratch\" and silently routes to a stub. `--tool auto` now picks Seedream when available; the OpenCV branch surfaces an actionable redirect to `scripts/inpaint.py` for known-geometry cases.\n- The redirect message also lists the most common `inpaint.py` invocations (`--type spot`, `--type wire`, `--type rect`) so users have a clear next step instead of a guess.\n\n### 1.3.2 — 2026-06-13\n\n**Bug fixes**\n- `op_resize` / `op_crop` / `op_color_adjust` no longer raise `TypeError: got an unexpected keyword argument 'mode'`. The CLI's `--mode` flag is now only forwarded for `hdr-tonemap`. (Was reported as \"numpy 2.x compat issue\"; root cause was kwargs leakage.)\n- `smart-compress --target-kb` no longer crashes with `No such file or directory: foo.q55.tmp`. The binary-search probe file now uses the format's real extension (`.jpg/.png/.webp`) so OpenCV can pick a codec.\n- `--quality` is now an actual CLI flag, declared in argparse and forwarded into `op_smart_compress` (was documented but unrecognized).\n- `--json` on a single-operation invocation now emits a JSON envelope on stdout instead of blocking on stdin. Batch input is still accepted via `--batch FILE` or piped stdin.\n- Markdown code fence around the AI-method / OpenCV-method examples is correctly paired (was rendered with broken nesting).\n- `compatibility` frontmatter key moved under `metadata.compatibility` (was rejected by the OpenClaw skill validator as an unknown top-level key).\n- `_tonemap_shadows` annotation corrected from `np.float32` to `np.ndarray`.\n\n**Seedream bridge rewrite**\nThe previous integration referenced a non-existent `bin/generate.sh` and a non-existent Python module. `_call_seedream` now invokes `node scripts/generate.js` with `--prompt`, `--mode image-to-image`, `--reference_images <data-URI JSON array>`, `--reference_strength`, and `--optimize false`, parses the JSON envelope from stdout, locates the first `download_success` image, and stages its `local_path` to the caller's `output_path`. Local file paths are encoded as `data:image/<type>;base64,<...>` data URIs because Seedream's validator only accepts HTTP URLs or data URIs. Verified end-to-end with a real ARK API call (200×200 input → 2048×2048 generated output, ~30 s).\n\n**Docs**\n- Added \"Python Interpreter\" section: all scripts hard-shebang the team venv (`~/.openclaw/venv-clawd/bin/python`); running them under system Python will spuriously report `piexif/exif/rembg` as missing.\n- `--quality` and `--json` table entries clarified.\n\nFile v1.5.0:README.md\n\n# Smart Photo Editor - Quick Start Guide\n\nAI-powered photo editing and restoration skill for OpenClaw.\n\n## Quick Start\n\n### ⭐ Recommended: Unified CLI (`edit.py`)\n```bash\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the power cable\" --output out.jpg\n```\n\n### Remove Object from Photo\n```\n\"Use smart-photo-editor to remove the power cable from this mountain photo\"\n```\n→ Automatically uses Seedream AI for complex scenes\n\n### Restore Old Photo\n```\n\"Use smart-photo-editor to restore this old photo\"\n```\n→ Removes scratches, enhances clarity, restores colors\n\n### Remove Background\n```\n\"Use smart-photo-editor to remove the background from this portrait\"\n```\n→ Uses rembg (if installed) or falls back to ImageMagick\n\n### Remove Diagonal/Angled Lines (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n```\n\n### Remove Watermark/Logo Region (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n```\n\n### Remove Multiple Spots/Lines (Batch Mode)\n```bash\n# Multiple spots in one command\n./scripts/inpaint.py input.jpg output.jpg --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Multiple lines in one command\n./scripts/inpaint.py input.jpg output.jpg --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py input.jpg output.jpg --type batch --batch tasks.json\n```\n\n### Resize for API Compatibility\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type resize --max-dim 2048\n```\n\n### Portrait Retouching\n```bash\n# All enhancements at once\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing + eye brightening\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n\n# Face brightness + contrast adjustment\n./scripts/portrait.py input.jpg output.jpg --brightness 10 --contrast 15\n```\n\n### EXIF Utilities\n```bash\n./scripts/exif_utils.py read photo.jpg        # Read EXIF tags\n./scripts/exif_utils.py strip photo.jpg -o out.jpg  # Remove EXIF\n./scripts/exif_utils.py copy src.jpg dst.jpg  # Copy EXIF to another image\n```\n\n### Smart Auto-Crop\n```bash\n./scripts/smart_crop.py input.jpg output.jpg               # Auto-detect salient region\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9 # Crop to aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --debug      # Generate debug overlay\n```\n\n### Additional OpenCV Operations (de\n\nArchive v1.4.2: 10 files, 64030 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (86796b), scripts/exif_utils.py (13253b), scripts/inpaint.py (21020b), scripts/portrait.py (28801b), scripts/remove_bg.sh (2903b), scripts/smart_crop.py (19750b), skill-card.md (2532b), SKILL.md (41534b)\n\nArchive v1.4.1: 10 files, 61214 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (83117b), scripts/exif_utils.py (13276b), scripts/inpaint.py (21043b), scripts/portrait.py (28824b), scripts/remove_bg.sh (2838b), scripts/smart_crop.py (19773b), skill-card.md (2247b), SKILL.md (36464b)\n\nArchive v1.4.0: 10 files, 60963 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (83117b), scripts/exif_utils.py (13276b), scripts/inpaint.py (21043b), scripts/portrait.py (28824b), scripts/remove_bg.sh (2838b), scripts/smart_crop.py (19773b), skill-card.md (2436b), SKILL.md (35858b)\n\nArchive v1.3.3: 10 files, 52062 bytes\n\nFiles: _meta.json (137b), README.md (4888b), scripts/edit.py (62025b), scripts/exif_utils.py (13276b), scripts/inpaint.py (21043b), scripts/portrait.py (28824b), scripts/remove_bg.sh (2780b), scripts/smart_crop.py (19773b), skill-card.md (2332b), SKILL.md (27724b)\n\nArchive v1.3.0: 10 files, 40517 bytes\n\nFiles: README.md (4888b), scripts/edit.py (32513b), scripts/exif_utils.py (13276b), scripts/inpaint.py (21043b), scripts/portrait.py (28824b), scripts/remove_bg.sh (2780b), scripts/smart_crop.py (19773b), skill-card.md (2208b), SKILL.md (17073b), _meta.json (137b)\n\nArchive v1.1.0: 6 files, 11767 bytes\n\nFiles: README.md (2751b), scripts/inpaint.py (16328b), scripts/remove_bg.sh (2041b), skill-card.md (2023b), SKILL.md (9564b), _meta.json (137b)\n\nArchive v1.0.3: 6 files, 8243 bytes\n\nFiles: README.md (2241b), scripts/inpaint.py (3506b), scripts/remove_bg.sh (2041b), skill-card.md (2144b), SKILL.md (8148b), _meta.json (137b)","readmeExcerpt":"Skill: Smart Photo Editor Owner: guoxh Summary: AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. Tags: ai:1.0.0, editing:1.0.0, imagemagick:1.0.0, latest:1.5.2, object-removal:1.0.0, opencv:1.0.0, photo:1.0.0, restoration:1.0.0 Version history: v1.5.2 | 2026-07-24T09:21:21.128Z | auto No changes detected in this version. - Version numbe","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"semantic edit / restoration / object removal       → Seedream first; deterministic fallback\nmechanical edit / resize / crop / compress / color → deterministic tools first\nuser explicitly asks for AI / natural restoration  → Seedream\nuser explicitly forces a tool with --tool ...      → honored verbatim"},{"language":"bash","snippet":"./scripts/edit.py --help"},{"language":"bash","snippet":"python3 scripts/edit.py --help"},{"language":"bash","snippet":"# Sanity check — required deps\\python3 -c \"import cv2, numpy, PIL; print('core deps ok')\"\n\n# Sanity check — full deps (includes optional rembg/piexif/exif)\npython3 -c \"import cv2, numpy, PIL, piexif, exif, rembg; print('all deps ok')\""},{"language":"bash","snippet":"source ~/.openclaw/venv-clawd/bin/activate\npip install rembg piexif exif"},{"language":"bash","snippet":"# Add to your shell profile or ~/.openclaw/.env\nexport SEEDREAM_UPLOAD_TOKEN=\"your-token-here\"\nexport SEEDREAM_UPLOAD_WORKER_URL=\"https://your-worker.your-subdomain.workers.dev\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: smart-photo-editor\nlicense: MIT\ndescription: |\n  AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nmetadata:\n  author: Team\n  version: \"1.5.1\"\n  category: ai/image-editing\n  compatibility: Requires Node.js 18+ and network access to VolcEngine Ark API (with Seedream model enabled) for AI features.\n---\n\n# Smart Photo Editor Skill\n\nAI-powered photo editing and restoration skill for OpenClaw. Unifies Seedream (AI edits), ImageMagick (basic edits), and OpenCV (programmatic fixes) into one intuitive workflow.\n\n## Overview\n\nAll-in-one intelligent photo editing skill - automatically selects the best tool for each image processing task.\n\n✨ **Key Advantages:**\n- ✅ **Smart Tool Selection** - Automatically chooses Seedream / ImageMagick / OpenCV based on task\n- ✅ **Unified Interface** - All operations use the same calling pattern\n- ✅ **Bilingual Support** - Optimized prompts for both Chinese and English contexts\n- ✅ **Automatic Fallback** - Switches to backup tools if primary tool fails\n- ✅ **Large Image Auto-Handling** - Avoids \"image too large\" API errors\n\n## Feature Availability\n\nThis skill provides two tiers of functionality:\n\n### ✅ Works out of the box (no extra dependencies)\n\nThese features only require ImageMagick and/or OpenCV (both widely available on Linux/macOS):\n\n- **Resize / Crop / Smart-crop** — dimension changes, aspect-ratio-preserving scaling\n- **Color adjustment** — brightness, contrast, saturation, grayscale\n- **Perspective correction** — 4-point skew/warp correction\n- **Smart compression** — quality targeting, binary-search for target file size\n- **HDR tonemapping** — log/bilateral/shadow/highlight recovery\n- **Background removal (basic)** — solid-color background removal via ImageMagick\n- **Geometric inpainting** — wire/line/rect removal with known coordinates (`inpaint.py`)\n\n### 🔒 Requires Seedream skill (AI features)\n\nThese features require the `byted-ark-seedream-skill` (VolcEngine Ark Agent Plan, managed skill):\n\n- **Object removal (natural language)** — remove objects described in text (people, vehicles, watermarks)\n- **Old photo restoration** — AI scratch/dust/fading repair\n- **Scene replacement (`replace-scene`)** — put subject into a new scene via multi-reference fusion\n- **Background removal (AI)** — rembg-based, or Seedream-based for complex edges\n\n> **Note:** The `byted-ark-seedream-skill` is an OpenClaw managed skill that requires a VolcEngine Ark account with the Seedream model enabled. Install with `openclaw skills install byted-ark-seedream-skill`.\n\n---\n\n## Trigger Conditions\n\nActivates automatically when users mention keywords like:\n- photo editing, edit image, retouch, smart photo edit\n- remove object, delete object, erase, remove person, remove watermark, remove logo, 去除, 消除\n- remove background, background removal, cutout, 抠图, 换背景\n- restore, fix, old photo restoration, repair, 修复老照片, 老照片修复\n- portrait retouching, portrait edit, s"},{"path":"README.md","content":"# Smart Photo Editor - Quick Start Guide\n\nAI-powered photo editing and restoration skill for OpenClaw.\n\n## Quick Start\n\n### ⭐ Recommended: Unified CLI (`edit.py`)\n```bash\n./scripts/edit.py --task remove-object --image photo.jpg \\\n  --prompt \"Remove the power cable\" --output out.jpg\n```\n\n### Remove Object from Photo\n```\n\"Use smart-photo-editor to remove the power cable from this mountain photo\"\n```\n→ Automatically uses Seedream AI for complex scenes\n\n### Restore Old Photo\n```\n\"Use smart-photo-editor to restore this old photo\"\n```\n→ Removes scratches, enhances clarity, restores colors\n\n### Remove Background\n```\n\"Use smart-photo-editor to remove the background from this portrait\"\n```\n→ Uses rembg (if installed) or falls back to ImageMagick\n\n### Remove Diagonal/Angled Lines (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type line --x1 100 --y1 200 --x2 500 --y2 400 --thickness 3\n```\n\n### Remove Watermark/Logo Region (OpenCV)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type rect --x 50 --y 50 --w 400 --h 80 --feather 5\n```\n\n### Remove Multiple Spots/Lines (Batch Mode)\n```bash\n# Multiple spots in one command\n./scripts/inpaint.py input.jpg output.jpg --type spots --spots \"100,150,8;200,300,10;50,400,6\"\n\n# Multiple lines in one command\n./scripts/inpaint.py input.jpg output.jpg --type lines --lines \"0,100,800,100,3;100,200,500,400,5\"\n\n# Batch processing from JSON config\n./scripts/inpaint.py input.jpg output.jpg --type batch --batch tasks.json\n```\n\n### Resize for API Compatibility\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type resize --max-dim 2048\n```\n\n### Portrait Retouching\n```bash\n# All enhancements at once\n./scripts/portrait.py input.jpg output.jpg --all\n\n# Subtle skin smoothing + eye brightening\n./scripts/portrait.py input.jpg output.jpg --smooth 2 --enhance-eyes\n\n# Face brightness + contrast adjustment\n./scripts/portrait.py input.jpg output.jpg --brightness 10 --contrast 15\n```\n\n### EXIF Utilities\n```bash\n./scripts/exif_utils.py read photo.jpg        # Read EXIF tags\n./scripts/exif_utils.py strip photo.jpg -o out.jpg  # Remove EXIF\n./scripts/exif_utils.py copy src.jpg dst.jpg  # Copy EXIF to another image\n```\n\n### Smart Auto-Crop\n```bash\n./scripts/smart_crop.py input.jpg output.jpg               # Auto-detect salient region\n./scripts/smart_crop.py input.jpg output.jpg --aspect 16/9 # Crop to aspect ratio\n./scripts/smart_crop.py input.jpg output.jpg --debug      # Generate debug overlay\n```\n\n### Additional OpenCV Operations (denoise / sharpen / adjust)\n```bash\n./scripts/inpaint.py input.jpg output.jpg --type denoise --strength 15\n./scripts/inpaint.py input.jpg output.jpg --type sharpen --strength 1.5\n./scripts/inpaint.py input.jpg output.jpg --type adjust --brightness 15 --contrast 10 --gamma 0.9\n```\n\n## Features\n\n| Feature | Best Tool | Quality |\n|---------|-----------|---------|\n| Object removal | Seedream AI | Excellent |\n| Old photo restoration | Seedream AI | Excellent |\n| Background removal | rembg AI | Excellent"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b21fme4bx0xwpm700dj5ehh82zrgq\",\n  \"slug\": \"smart-photo-editor\",\n  \"version\": \"1.5.2\",\n  \"publishedAt\": 1784884881128\n}"},{"path":"skill-card.md","content":"## Description:\n\nAI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[guoxh](https://clawhub.ai/user/guoxh)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to select and run photo-editing workflows, including deterministic resizing, cropping, color adjustment, background removal, object removal, restoration, scene replacement, and portrait retouching.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Selected photos and metadata may be processed by external services for AI editing features.\n\nMitigation: Strip EXIF and location metadata before sensitive cloud AI edits, and use local deterministic tools when external processing is not acceptable.\n\nRisk: Large reference images may be sent through a user-configured Cloudflare R2 worker when upload support is enabled.\n\nMitigation: Enable R2 upload only with a trusted worker and token, and review worker access controls before use.\n\nRisk: Unpinned Python dependencies or optional image tools can change behavior across environments.\n\nMitigation: Pin dependencies in the deployment environment and test critical edits before batch use.\n\nRisk: Image editing commands write output files and can overwrite important files if paths are chosen poorly.\n\nMitigation: Use distinct output paths and keep backups of source images before running destructive or batch operations.\n\n## Reference(s):\n\n- [Smart Photo Editor on ClawHub](https://clawhub.ai/guoxh/skills/smart-photo-editor)\n- [VolcEngine Ark Seedream setup guide](https://www.volcengine.com/docs/82379/2375486)\n- [Cloudflare R2 documentation](https://developers.cloudflare.com/r2/)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands, CLI arguments, and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce edited image files through local scripts and optional external AI or upload services when configured.]\n\n## Skill Version(s):\n\n1.5.2 (source: server release metadata; artifact metadata reports 1.5.1)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. Skill: Smart Photo Editor Owner: guoxh Summary: AI-powered photo editing and restoration skill - smart object removal, background removal, old photo restoration, and basic edits. Tags: ai:1.0.0, editing:1.0.0, imagemagick:1.0.0, latest:1.5.2, object-removal:1.0.0, opencv:1.0.0, photo:1.0.0, restoration:1.0.0 Version history: v1.5.2 | 2026-07-24T09:21:21.128Z | auto No changes detected in this version. - Version numbe","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1583,"uniquenessScore":47,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T10:18:26.872Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T13:32:38.426Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}