宣传照批处理(调色·打码·Logo)
对机构宣传照片执行固定三步流水线:暖色调色 → 人脸贴纸打码 → logo 水印。使用 scripts/process.py 完成全部处理,不要手写一次性代码。
使用场景
- 医院/机构宣传素材批量处理(文件夹批量或单张)
- 用户说「调暖色」「打码(人脸贴纸)」「放 logo」的任意组合
前置条件
- 依赖自动安装:脚本首次运行若检测到缺少 opencv/pillow/numpy,会自动安装一次(联网)。装好之后后续运行跳过。无需手动 pip。
- 若你拿到的是「离线版」(skill 目录里带
wheels/),则无需联网、从本地安装。 - 精简分发版 zip(<10MB)不含
wheels/,首跑需联网装一次依赖。 - Python 环境:使用托管 venv
C:\Users\Administrator\.workbuddy\binaries\python\envs\default\Scripts\python.exe - 贴纸:必须由用户提供 PNG(建议带透明通道),用户说「会指定贴纸」即指此参数。未提供时用
--skip-sticker跳过并提醒用户。 - logo:用户提供 PNG(建议带透明通道)。未提供时用
--skip-logo跳过。
标准命令
# 批量处理整个文件夹(三个步骤全开)
<C:\Users\Administrator\.workbuddy\binaries\python\envs\default\Scripts\python.exe> \
<本skill目录>\scripts\process.py \
"D:\素材文件夹" \
--sticker "贴纸.png" --logo "logo.png" --out "D:\素材文件夹_已处理" \
--logo-pos top-left --json
# 只调色 + 打码,不加 logo
... process.py 输入目录 --sticker 贴纸.png --skip-logo --json
常用参数:
| 参数 | 默认 | 说明 |
|---|---|---|
--style |
warm | 调色预设:warm暖阳 / cool清冷 / vivid鲜艳 / soft柔和 / fresh清新 / cinematic电影感 / mono黑白 / bright提亮。用 --list-styles 查看全部 |
--warm-strength/--strength |
1.0 | 调色强度 0~2;兼容旧名 --warm-strength。嫌不够浓调到 1.3~1.5 |
--no-harmonize |
- | 关闭批次色彩统一(默认开启:同批图自动对齐曝光与冷暖) |
--harmonize-strength |
0.8 | 批次统一强度 0~1,1=完全对齐到批次基准;过强可能抹掉合理差异 |
--sticker-top |
0.34 | 打码区向上包头发比例(相对人脸高);头发露出来就加大到 0.45 |
--sticker-bottom |
0.20 | 打码区向下包下巴/脖子比例;下巴露出来就加大到 0.30 |
--sticker-side |
0.08 | 打码区左右扩展比例;脸侧露出来就加大 |
--sticker-scale |
1.0 | 贴纸整体微调倍数;1.0≈贴合脸,偏大调小、偏小调大 |
--min-face |
48 | 忽略过小人脸(远景小人误检多时调大) |
--staff-colors |
FFFFFF,F7F7F7 | 命中即不打码(白大褂/制服);追加机构制服色值 |
--staff-color-tol |
42 | 服装色命中容差(RGB 欧氏距离) |
--skip-region |
- | 不打码的固定矩形 x,y,w,h(像素,可重复),用于前台机位 |
--mode |
full | review=全打码+标ID供复核;finalize=按 --unmask 定点解除 |
--review-json |
- | finalize 用的复核 JSON 路径 |
--unmask |
- | finalize 指定解打 ID,格式 图A.jpg:3,5;图B.jpg:1 |
--logo-pos |
top-left | logo 位置四角可选 |
--logo-scale |
0.16 | logo 宽 / 图宽 |
--skip-grade / --skip-sticker / --skip-logo |
- | 跳过对应步骤 |
调色预设(多场景适配,不再只有暖色)
内置 8 套预设,按场景选 --style,强度用 --strength 微调。先跑 python process.py --list-styles 查看清单。
| 预设 | 适配场景 | 效果 |
|---|---|---|
warm(默认) |
医疗/人文宣传 | 暖阳、饱和、有对比、不发灰发白 |
cool |
诊所/实验室 | 清冷洁净感 |
vivid |
海报/广告 | 鲜艳通透、冲击力强 |
soft |
母婴/舒缓 | 柔和奶油、低对比 |
fresh |
日系/明亮 | 清新、低饱和、提亮 |
cinematic |
纪录片/品牌片 | 青橙电影感、黑位抬升 |
mono |
纪实 | 黑白 |
bright |
暗房/阴天补救 | 整体提亮 |
不同场景可分批跑:如前台/大厅用 warm、手术室用 cool、海报用 vivid。
python process.py 素材目录 --style cool --strength 1.2 --sticker 贴纸.png --logo logo.png --out 输出目录
批次色彩统一(同批图色调一致,默认开启)
同一批原图往往曝光/色温不一致,逐张套同一预设仍会显脏。脚本在套用风格之前先做一次批次统一:
- 曝光对齐:以整批平均亮度的中位数为目标,对每张图做限幅乘性缩放,消除过亮/过暗;
- 冷暖对齐:把每张图 R、B 通道均值比例缩放向批次基准靠拢(保留局部色彩,只统一整体偏色)。
统一后再套你选的 --style,整批成片色调一致且合理。统计里 color.harmonized=true 表示已做统一。
# 默认即开启;如某批图本就该有明暗差异,可关掉
python process.py 素材目录 --style warm --out 输出目录
python process.py 素材目录 --style warm --no-harmonize --out 输出目录
# 统一强度可调(1=完全对齐到批次基准)
python process.py 素材目录 --style warm --harmonize-strength 1.0 --out 输出目录
⚠️ 单张图或 --harmonize-strength=1 可能抹掉合理的明暗/氛围差异,一般保持默认 0.8 即可。
执行规则(必须遵守)
- 顺序固定:先调色、再检测人脸打码、最后放 logo。脚本内已按此顺序实现。
- 不展示成图:处理对象含人脸,禁止在对话中展示处理结果图。只用
--json输出的统计验证:
-faces_detected/stickers_applied:人脸检出数与实际贴纸数应一致(不一致说明有人脸小于--min-face被跳过,需调小该值重跑)。
-color.style记录所用预设;color.warm_shift仅对暖/冷类有意义(>0 更暖、<0 更冷);其他风格看rb_ratio_after与主观核验。 - 漏检兜底:若某张图
faces_detected=0但画面明显有人(根据场景判断),提醒用户该图需人工确认,不要静默通过。 - 贴纸盖不全:默认已用 cover 模式铺满「扩展打码区」(上包头发、下包下巴、两侧略包)。仍露脸时按部位调大:
--sticker-top(头发)、--sticker-bottom(下巴)、--sticker-side(脸侧);整体偏大/偏小调--sticker-scale;误检小脸干扰时调大--min-face。 - 输出目录默认写到输入旁;批量任务时建议显式
--out到独立目录,避免混入原始文件。
角色分级:只打患者,跳过前台/医护
默认对所有检测到的人脸打码。开启「只打患者」需满足:提供 --sticker 且用下面任一机制把前台/医护标记为不打码。
- 服装颜色(常用):
--staff-colors FFFFFF,F7F7F7(默认近白,命中白大褂/护士服/浅色制服 → 不打码)。
若机构前台/医护着特定颜色制服,把色值加进去,如--staff-colors FFFFFF,40E0D0(青色洗手衣)。 - 固定区域(前台固定机位):
--skip-region x,y,w,h(像素,基于原图),可重复多次。前台总在画面同一位置时最稳。 - 命中以上任一条件 → 该人脸不打码;其余一律视为患者并打码。
# 只打患者:白大褂医护不打 + 前台固定区域不打
... process.py 素材目录 --sticker 贴纸.png --logo logo.png \
--staff-colors FFFFFF,F7F7F7 --skip-region 0,300,500,400 --json
⚠️ 医疗隐私风险提示:自动角色判断是「启发式」——靠服装颜色和固定区域,不是真的人脸身份识别,会误判:
- 穿白衣服的患者可能被误判为医护 → 漏打码(隐私泄露风险);
- 着便装的医护/前台可能仍被打码。
因此 --json 统计里务必核对 staff_skipped 与 patients_masked,并对成图做一次人工抽检。
如有可靠的角色清单,优先用 --skip-region 圈定前台机位,比纯颜色更稳。
复核模式(推荐用于医疗素材,先全打码再定点解除)
为彻底规避「患者被误放」风险,采用「先全打码、人工确认、再定点解除」两步流程:
第 1 步 review:所有人脸先盖住(有贴纸用贴纸,否则灰块),再给每张脸标 #ID 并生成缩略预览图 + review.json(含每个 ID 的原图坐标)。人脸已遮挡,预览可安全查看。
python process.py 素材目录 --sticker 贴纸.png --mode review --out 输出目录
用户看预览,按身体/位置/衣服辨认出医护/前台,回:「图A.jpg 的 #3、#5 是医生,图B.jpg 的 #1 是前台」。
第 2 步 finalize:只解打你指定的 ID,其余患者照打。
python process.py 素材目录 --sticker 贴纸.png --logo logo.png \
--mode finalize --review-json 输出目录/review.json \
--unmask "图A.jpg:3,5;图B.jpg:1" --out 输出目录
finalize 会用 review.json 里的坐标作为 skip-region 重新跑完整流水线(调色+只打患者+logo),ID 与坐标由同图同参数检测保证一致。
候选确认模式(复核量 = 医护数,最省事)
把自动识别从「全量复核」压缩为「只复核候选」:自动跑角色判断后,只把疑似医护的脸拼成一张确认表,患者全被打码、无需看。
第 1 步 candidates:自动检测+分类,输出 candidates.jpg(确认表,每张疑似医护脸带 图名 #ID 标签)+ candidates.json。
python process.py 素材目录 --mode candidates --out 输出目录
你扫一眼确认表:是医护/前台的保留;是患者(被误判)的记下来。
第 2 步 finalize:用 --from-candidates 直接读候选表解打全部候选,--exclude 剔除你确认的误判患者。
python process.py 素材目录 --sticker 贴纸.png --logo logo.png \
--mode finalize --from-candidates 输出目录/candidates.json \
--exclude "图A.jpg:2" --out 输出目录
复核量从「照片×人脸」降到「医护人数」,且不漏打患者(默认全打码,只有确认的候选才解)。
技术要点(维护者备忘)
- 调色用 RGB+HSV 管线,禁用 PIL 的 LAB 模式(非标准:中性色 a/b=0 而非 128,偏色计算会错)。
- 暖白平衡带高光保护:纯白区域偏移权重趋零,防止过曝发白;饱和度提升防发灰。
- 人脸检测用 YuNet(
cv2.FaceDetectorYN)。模型(232KB)以 base64 内嵌于scripts/yunet_model.py,首次运行解码到本地缓存(~/.cache/promo-photo-pipeline/),离线可用且打包不含被拦截的.onnx文件。OpenCV 5.x 已移除CascadeClassifier,不要再退回 Haar。 - OpenCV 依赖用
opencv-python-headless即可(无需 GUI 模块)。 - 验证一律看
--json统计(faces/stickers/warm_shift),不展示含人脸成图。