OpenClaw技能开发为Qwen3.5-9B定制图片水印插件1. 为什么需要这个技能上个月我整理摄影作品集时遇到一个痛点手动给几百张照片添加版权水印不仅耗时还很难保证样式统一。更麻烦的是有些照片需要根据内容调整水印位置——比如风景照适合右下角而人像特写可能需要左下角避免遮挡面部。当时我就在想既然OpenClaw能操控本地文件Qwen3.5-9B又能理解图片内容为什么不开发一个智能水印插件这个想法最终落地成了一个完整的技能包现在分享我的开发历程。2. 技术方案设计2.1 核心工作流整个技能的执行链路是这样的接收输入用户通过飞书/Web控制台上传图片或指定本地文件夹路径内容分析调用Qwen3.5-9B识别图片主体和关键区域水印生成根据分析结果动态计算水印位置、透明度和尺寸文件输出保存带水印的新图片保留原始EXIF信息2.2 关键技术点开发过程中有几个关键决策模型选择测试发现Qwen3.5-9B在识别可标注区域如天空、纯色背景时准确率足够且4bit量化版本在消费级显卡上就能运行水印算法使用Pillow库的Image.composite()实现alpha混合比直接绘制文本更抗压缩缓存机制对同一文件夹的批量处理会缓存模型分析结果减少Token消耗3. 开发实战记录3.1 环境准备首先确保基础环境就位# 安装技能开发工具包 clawhub install openclaw/devkit # 创建技能骨架 clawhub create watermark-generator --templateimage-processor这会生成标准目录结构watermark-generator/ ├── package.json ├── configs/ # 技能配置 ├── src/ │ ├── index.ts # 主逻辑 │ └── models/ # 模型交互 └── tests/ # 测试用例3.2 核心代码实现重点看模型交互部分。我们需要让Qwen3.5-9B返回JSON格式的分析结果// src/models/analyzer.ts interface AnalysisResult { mainSubject: { position: left | right | center; sizeRatio: number; }; watermarkZones: Array{ x: number; y: number; width: number; height: number; confidence: number; }; } export async function analyzeImage(imagePath: string): PromiseAnalysisResult { const prompt 你是一个专业摄影师。请分析该图片并返回JSON { mainSubject: { position: 主体水平位置, sizeRatio: 主体占比 }, watermarkZones: [ { x: 左上角X比例, y: 左上角Y比例, width: 宽度比例, height: 高度比例, confidence: 置信度 } ] }; const response await openclaw.models.query({ provider: qwen, model: qwen3-9b, messages: [ { role: user, content: [ { type: text, text: prompt }, { type: image_url, image_url: { url: file://${imagePath} } } ] } ], response_format: { type: json_object } }); return JSON.parse(response.choices[0].message.content); }3.3 水印位置算法根据模型输出计算最佳水印位置// src/utils/placement.ts export function calculatePlacement( imageWidth: number, imageHeight: number, analysis: AnalysisResult ): { x: number; y: number; opacity: number } { // 优先选择模型推荐区域 if (analysis.watermarkZones.length 0) { const bestZone analysis.watermarkZones.reduce((prev, curr) curr.confidence prev.confidence ? curr : prev ); return { x: Math.floor(bestZone.x * imageWidth), y: Math.floor(bestZone.y * imageHeight), opacity: 0.6 }; } // 默认逻辑根据主体位置选择对角区域 const padding Math.min(imageWidth, imageHeight) * 0.05; return { x: analysis.mainSubject.position left ? imageWidth - padding : padding, y: imageHeight - padding, opacity: 0.8 }; }4. 踩坑与解决方案4.1 模型响应格式问题最初直接让模型返回文本描述再通过正则提取信息发现格式很不稳定。后来改用OpenAI兼容的response_format参数强制JSON输出可靠性大幅提升。4.2 批量处理的内存泄漏连续处理100图片时Node.js进程会崩溃。通过以下方法解决使用sharp替代Pillow处理图片给模型调用添加间隔延迟定期手动调用GC虽然不推荐但确实有效4.3 跨平台路径问题Windows和macOS的文件路径格式不同最终统一使用path.posix处理内部路径再用file://协议头传递给模型。5. 发布到ClawHub完成开发后发布流程比想象中简单# 登录ClawHub账号 clawhub login # 构建技能包 clawhub build # 发布到仓库 clawhub publish --public发布时需要填写技能名称watermark-ai兼容的OpenClaw版本所需模型依赖声明需要Qwen3.5-9B或兼容模型6. 实际使用效果现在我的工作流变成这样把待处理图片拖到指定文件夹对OpenClaw说给这些照片加上我的署名水印去喝杯咖啡回来就能看到处理好的/output文件夹典型处理速度单张图片约12秒含模型分析水印生成批量100张约8分钟得益于缓存优化7. 扩展思路这个技能还有很大优化空间样式模板允许用户上传PSD模板替代简单文字水印智能文案让模型根据图片内容生成水印文字如摄于杭州西湖EXIF保护检测到GPS信息时自动降低水印透明度避免隐私泄露不过目前版本已经满足我的核心需求——用自动化守护创作版权而不是被工具绑架时间。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。