房产热销稿 · 图文生成器
把「参考案例」的版式基因 + 「当日素材」的成交事实,熔炼成一套可直接发朋友圈/客户群的热销图文:配图(高清 + 手机版)+ 转发配文。
核心价值在两个字:真与净。
真:房号可辨、现场实拍,成交证据立得住。
净:人脸、时间、姓名、房号尾段全部脱敏,不泄露客户隐私、不给竞品留把柄。
快速开始(30 秒看懂)
解决什么问题:房产项目天天有成交,要把成交凭证、政策海报、案场实拍做成一条能直接发朋友圈的图文。手工做要逐张打码、拼版、写字,半小时起步。本技能把它压成一次对话。
你只需准备两个文件夹:
| 文件夹 | 放什么 |
|---|---|
| 参考案例 | 项目以往发出的热销成品图 + 配套转发配文(教它学版式与语气) |
| 今日素材 | 本次的刷卡单/转账截图、政策海报、现场人气照、房源贴 |
然后说一句话:
按热销稿技能生成今天的热销图文。
参考案例文件夹:<你的路径>
热销素材文件夹:<你的路径>
项目名称:<楼盘名>
VIP 电话:<电话>
脱敏要求:人脸模糊、时间模糊、姓名打码、房号只保留前半段
你会拿到:两张配图(高清 + 手机版)+ 一段转发配文,人脸、时间、姓名、房号尾段已自动脱敏。
三件事做不到就等于白做:
- 人脸必须人工复核,机器只给候选
- 坐标必须用绝对刻度标定,不要目视估算
- 交付前必须逐区放大自检
详细流程见下文。
一、铁律(违反即返工)
| # | 铁律 | 原因 |
|---|---|---|
| 1 | 不硬编码任何项目信息 | 楼盘名、路径、房源、电话、日期每次启动都问询确认 |
| 2 | 人脸必须真人复核 | 自动检测必误检(墙面贴纸/椅背/屏幕文字)且漏检侧脸背影,机器给候选,人给结论 |
| 3 | 坐标必须用绝对刻度标定 | 目视缩放图估坐标会整体偏位 300~400px,这是实践中最大的坑 |
| 4 | 证件类文字用「模糊+像素化」双层 | 单层模糊块太小仍可辨认(6px 块 + 高斯 = 依然能读) |
| 5 | 贴纸不许压住房号 | 房号是成交真实性的证据,压住 = 自毁卖点 |
| 6 | 不叠加暖色滤镜 | 暖化 + 奶油底 + 提饱和 = 三重叠加,白纸焗成旧报纸 |
| 7 | 交付前逐区裁剪自检 | 缩略图看不出残留,必须放大到原尺寸逐块看 |
二、启动参数确认(必须用 AskUserQuestion)
开始任何操作前,先确认以下参数。严禁沿用上次的路径与项目信息。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
| 参考案例文件夹 | 文本 | 无 | 以往热销稿图片 + 配套配文的目录 |
| 热销素材文件夹 | 文本 | 无 | 本次待处理的素材目录 |
| 输出目录 | 文本 | 素材同级 今日热销_YYYYMMDD |
交付物落地位置 |
| 项目/楼盘名称 | 文本 | 无 | 用于缎带、大字、配文 |
| VIP 电话 | 文本 | 无 | 配文末尾挂载 |
| 脱敏范围 | 多选 | 人脸+时间+房号+姓名 | 可加:账号、车位号、全套 |
| 房号打码规则 | 单选 | 保留前半段 | 保留前半段 / 全遮 / 不打码 |
> 若用户说"按之前那样",仍要复述一遍参数请他确认,不能静默沿用。
三、工作流
Step 0 · 环境自检(一次搞定)
python "<skill_dir>/scripts/hotpic_env.py"
该脚本自动完成:检查并安装 numpy / opencv-python / pillow → 扫描可用中文字体 → 校验 YuNet 模型 → 输出环境报告。
关键环境坑(务必知道):
| 坑 | 现象 | 解法 |
|---|---|---|
| opencv 5.x 是空壳 | cv2.CascadeClassifier、cv2.data 缺失或行为异常 |
pip install "opencv-python==4.11.0.86" --force-reinstall --no-deps;若 5.x 有 FaceDetectorYN 也可直接用 |
| mediapipe 偷换依赖 | 装 mediapipe 会把 opencv 降成 5.0 空壳 | 装完 mediapipe 后重装 opencv 4.11 |
| Chrome headless 静默失败 | --screenshot 无输出、命令被转发给已开浏览器 |
首选方案本就是 PIL 直绘,不依赖浏览器。若坚持用 Chrome 截图,需加独立 --user-data-dir 并接受其不稳定 |
| shell 缺基础命令 | 部分 Windows 环境下 ls / mkdir / tail / dirname 不可用 |
所有文件操作统一用 Python 完成,不写 shell 管道 |
| 中文路径 | 部分库/浏览器加载失败 | 素材先复制到纯英文路径(如 work/web/r1.jpg)再处理 |
| 中文字体 | 系统字体名不确定 | 扫 C:\Windows\Fonts,默认使用 STHUPO.TTF(华文琥珀),缺失时自动降级到扫描到的第一个中文字体 |
Step 1 · 侦察参考案例 + 清点素材
- 逐个 Read 参考案例图片,提取版式基因:
- 分栏结构(参考案例为三栏拼贴:刷卡单实拍 / 官方政策海报 / 现场人气实景)
- 文字样式(橙红+亮黄描边大字压在图上)
- 印章与贴纸位置 - Read 参考案例配文,提取语气基因:emoji 分行、数字用变体(6️⃣🥁🎊)、末尾 VIP LINE
- 递归列出素材目录,输出清单
- 逐张 Read 素材,识别每张的用途:
| 素材类型 | 典型内容 | 版面角色 |
|---|---|---|
| 刷卡单/转账截图 | 成交凭证 | 左栏(证真) |
| 官方政策/特惠海报 | 优惠信息 | 中栏(承接) |
| 现场人气照 | 案场实景 | 右栏(氛围) |
| 房源贴/户型图 | 在售房源 | 通栏底图(盘点) |
> 素材与配文命名建议保持项目习惯:刷卡单N.jpg、本月销售政策.jpg、本周特惠房源.jpg、现场人气N.jpg;参考案例配文为 热销朋友圈转发配文.txt。
Step 2 · 人脸检测(机器给候选)
python "<skill_dir>/scripts/hotpic_faces.py" --src "<素材目录>" --out "<工作目录>/face_out" --images "现场人气1.jpg,现场人气2.jpg"
双检测器联合召回:YuNet(onnx,主)+ Haar 三分类器(补充:正脸/alt2/侧脸),IoU 合并去重。
产出三份东西,必须全部用 Read 工具亲眼看:
| 产物 | 用途 |
|---|---|
preview_*.jpg |
带红框的检测预览 |
sheet_*.jpg |
每个框单独裁出排成"检查表",逐格判定真脸/误检 |
grid_*.jpg |
绝对坐标标尺网格,用来读准确坐标 |
boxes.json |
检测框坐标(机器候选,需人工增删) |
人工复核要点(这一步不能省):
- 删掉误检:墙面贴纸、椅背、屏幕文字、宣传物料上的人像
- 补上漏检:侧脸、低头、背影、被遮挡、远景小脸
- 最终产出人工确认后的头部框列表,写进 _mask.json 的 faces
Step 3 · 坐标标定(全部字段)
需要标定的区域:
A. 人脸区(现场人气照)
用 grid_*.jpg 读数,框略大于头部(外扩 15~25%)。
B. 刷卡单敏感字段
逐张打开素材,用 hotpic_grid.py 生成绝对坐标网格(网格标签标注的是原图坐标,不是裁切局部坐标):
python "<skill_dir>/scripts/hotpic_grid.py" --src "<素材目录>" --name "刷卡单1.jpg" --crop "0,0,2644,700" --step 100
需要标定的字段清单:
| 字段 | 位置 | 处理方式 |
|---|---|---|
| 顶部状态栏时间 | 手机截图顶部 | 模糊 |
| 交易日期·时间 | 单据中上部 | 模糊 |
| 打印/下载日期时间 | 单据页脚 | 模糊 |
| 付款人姓名 | "付款人"行 | 模糊 + 像素化 |
| 客户全名 | 户名/姓名栏 | 模糊 + 像素化 |
| 标题内嵌姓名 | 如「*某某向…转账」 | 模糊 + 像素化 |
| 房号 | 红色手写/打印房号 | 只马赛克右侧 45%~65%,保留前半段 |
| 斜纹水印 | 满屏 "已核验" 类 | LUT 淡化 |
坐标标定方法论(本项目踩坑后的最佳实践):
- 绝对坐标网格:网格标签必须标原图绝对坐标。用局部坐标读数是偏位的元凶。
- 投影法测文字边界(比目视准得多):
python bw = (gray < 150).astype(np.uint8) # 二值化 rows = np.where(bw[:, x1:x2].sum(axis=1) > 3)[0] # 行投影 → y 段 cols = np.where(bw[y1:y2, :].sum(axis=0) > 0)[0] # 列投影 → x 段 - 红字房号自动检测(不靠手填):
python hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) m = cv2.inRange(hsv, (0, 55, 55), (26, 255, 255)) | cv2.inRange(hsv, (158, 55, 55), (180, 255, 255)) m = cv2.morphologyEx(m, cv2.MORPH_CLOSE, np.ones((9, 131), np.uint8)) # 水平长核连接同行字符 # 过滤:面积 ≥ 1500、宽 ≥ 150、宽高比 > 1.8、位置约束 0.10<cx<0.78 / 0.30<cy<0.90(排除印章)
> 色相阈值要放宽到 26:不同单据红字会偏橙,阈值太窄会漏检。
C. 版面元素坐标
- 海报内卡片位置:HSV 橙色掩码 + 列投影找空白列 → 得到左右列分界与行中心
- 贴纸安全区:确认避开房号红字带
Step 4 · 脱敏处理
把 Step 3 的坐标写进 _mask.json(格式见 scripts/_mask.template.json),然后:
python "<skill_dir>/scripts/hotpic_mask.py" --config "<工作目录>/_mask.json"
内置四种武器:
| 函数 | 用途 | 原理 |
|---|---|---|
obliterate() |
时间、大块区域 | 缩小到 1/11 → 放大 → 高斯模糊,保留底色质感 |
pixelate() |
姓名(必须不可辨认) | 降到 1/14 分辨率 → NEAREST 放大,块状马赛克 |
find_red_bands() |
房号自动定位 | HSV 红/橙色掩码 + 水平长核闭运算 + 形状与位置过滤 |
dewatermark() |
斜纹水印淡化 | LUT 压缩亮部(>200 向白靠拢 25%),不动暗部文字 |
姓名类字段必须「先 obliterate 打底 + 再 pixelate 覆盖」双层,单层会残留笔画轮廓。
房号部分打码:obliterate() 只作用于右半段,split = x + w*0.45;若用连通域掩码方式,则 keep[:, :split] = False 后 dilate 51px 再合成。
兜底机制:红字检测失败时(色相超阈值、无连通域)自动启用 red_fallback 手填区域,并在日志打印"兜底遮房号",便于发现标定问题。
⚠ 房号自动检测的三重安全约束(实测踩坑后的加固,别绕过):
1. room_auto 默认 false,只有单据/交易截图才设 true
2. 图片配了 faces(即现场照)时,强制跳过房号检测 —— 否则照片里的横幅、红椅等大色块会被当成房号糊掉(实测复现过)
3. 检测结果再按尺寸合理性过滤:高度 > 图高 25%、面积 > 全图 8% 的红色区块自动剔除(房号是细长文字带,不是大色块)
缺图告警:若素材文件名与 aliases 不匹配,排版阶段会打印醒目的 [缺图!] 并在末尾汇总清单。看到这个提示要立刻回头补 aliases,别让成图带着空格子出门。
验证闭环(必须做):每次跑完,逐字段裁剪原尺寸放大 Read 一遍,确认无残留再进下一步。典型残留:框偏右露出最后一个字、框偏矮露出姓氏下半、页脚日期末尾数字漏出。
Step 5 · 排版渲染(PIL 直绘)
坐标写进 _layout.json(格式见 scripts/_layout.template.json),然后:
python "<skill_dir>/scripts/hotpic_compose.py" --config "<工作目录>/_layout.json"
内置版式骨架(参考案例风格的标准化):
┌──────────────────────────────────────────────┐
│ 红色渐变缎带 + 金色描边大字(顶部 h≈152) │
├────────────┬──────────────┬──────────────────┤
│ 刷卡单实拍 │ 官方政策海报 │ 现场人气实景 │ ← 三栏拼贴
│ (证真) │ (承接) │ (氛围) │
├────────────┴──────────────┴──────────────────┤
│ 通栏房源贴(盘点在售房源)+「已售」胶囊贴纸 │ ← 图2 专属
└──────────────────────────────────────────────┘
可复用组件(hotpic_compose.py 内置):
| 组件 | 效果 | 关键参数 |
|---|---|---|
ribbon() |
红色横向渐变缎带 + 顶部金色高光 + 两端八角星 | 文字、字号 |
sticker() |
爆炸多边形贴纸(带模糊投影 + 白描边) | 中心、半径、文字、底色 |
stamp() |
旋转双环「已成交」红章 | 中心、大小、角度 |
sold_tag() |
红色胶囊「已售」标签(投影 + 白边 + 倾斜) | 中心、宽高、角度 |
sparkles() |
八角星火点缀(金色/白色交替) | 坐标列表 |
cover() |
等比裁剪填充(不变形) | 目标框 + 锚点 (0.5, 0.5) |
vivid() |
只提饱和/对比,不动色相 | sat 1.06 / con 1.05 |
配色规范(照抄,别自己发明):
| 用途 | 色值 |
|---|---|
| 画布底色 | (255, 252, 247) 中性暖白 —— 不要用奶油黄 |
| 缎带主体 | 横向渐变 (206,22,26) → (246,92,42) |
| 缎带文字 | 亮黄 (255,238,130) + 深红描边 (140,18,0) |
| 大字 | 亮金 (255,216,40) + 深棕描边 (140,30,0) |
| 贴纸 | 橙 (255,96,0) / 红 (212,24,24) + 白描边 |
| 印章 | 正红 (214,28,28) |
画面发黄的三重元凶(务必避开):
1. warm() 暖化函数(R×1.14 / B×0.86)—— 最猛的一层
2. 画布底色用奶油黄 (255,214,140)
3. ImageEnhance.Color(1.10) 再提饱和
三者叠加,白纸都会变成旧报纸。正确做法:删掉暖化,底色中性暖白,只做 vivid(1.06, 1.05)。
版面排布的硬约束:
- 贴纸/印章/大字之间不许互相遮挡,也不许压住房号
- 排版后用坐标网格叠加检查一遍,确认每个元素落在预期位置
- 通栏海报的 cover 比例要算对:PS = 目标高 / 原图高,元素坐标按 PS 换算再加 y 偏移
Step 6 · 输出交付
hotpic_compose.py 自动产出三件套:
| 产物 | 规格 | 用途 |
|---|---|---|
热销图N_MMDD.jpg |
2160 宽,quality 95 | 存档、大屏 |
热销图N_手机版.jpg |
1080 宽,quality 92 | 发群发圈用这版 |
热销朋友圈转发配文.txt |
纯文本 | 直接复制 |
> 为什么要手机版:2160 宽、1.3~1.5MB 的高清图在部分查看器(手机相册、微信预览)会加载不全或只渲染一截。发出去一律用 1080 版(330~430KB)。
配文写法(照参考案例语气):
🥁周日热销 ‼️ 一日三单
🎊 恭喜成为 #<项目名> 业主
🏠 <楼栋> 双栋齐开
🅿️ 房车位同购 一步到位
🔥 现场人气爆棚 好房递减中
☎ 𝙫𝙞𝙥 𝙡𝙞𝙣𝙚:<电话>
要点:
- emoji 分行,一行一个信息点
- 数字用 emoji 变体增强节奏(6️⃣ 🥁 🎊)
- 房源/优惠类配文用 ✅ 列点,与图上政策海报呼应
- 若图上贴了「已售」标签,配文补一句"部分已售,好楼层越挑越少"形成闭环
- 末尾固定挂 VIP LINE
Step 7 · 交付自检(不可跳过)
逐项核对,缺一不可:
- [ ] 每张人脸的框都人工确认过(无漏检侧脸、无误检墙面贴纸)
- [ ] 人脸模糊强度适中(看得出是人,认不出是谁)
- [ ] 所有时间字段(状态栏/交易时间/页脚日期)不可读
- [ ] 所有姓名(付款人/户名/标题内嵌)不可辨认
- [ ] 房号保留前半段、右半段打码
- [ ] 没有遮挡住房号、没有文字互相压盖
- [ ] 画面无偏黄、无偏色
- [ ] 高清版 + 手机版都已生成,配文已写好
- [ ] 目录内无临时检查文件残留(
_chk_*、grid_*等)
最后用 present_files 交付,并在回复中说明脱敏处理清单(做了什么、做了什么没做),让用户对"哪些隐私已隐去"心里有数。
四、常见回修场景(用户反馈 → 定位方向)
| 用户说 | 大概率原因 | 修法 |
|---|---|---|
| "画面不够热烈" | 缺色块/贴纸/印章,纯白底太平 | 加缎带 + 爆炸贴纸 + 已成交章 + 星火 |
| "图二房源没显示完全" | 横版海报硬塞进矮格子被裁 | 加高画布,让通栏海报完整展示 |
| "文字互相遮住了" | 元素坐标重叠 | 重排坐标,用网格验证 |
| "整体偏黄" | 暖化 + 奶油底 + 提饱和三重叠加 | 见 Step 5 偏黄章节 |
| "XX 没看到吗?不知道打码?" | 该字段不在初始脱敏清单里 | 立即承认疏漏,全量重扫同类字段(如"付款人"漏了,就把所有含姓名的字段全扫一遍) |
| "某处还要打码" | 新增脱敏需求 | 标定坐标 → 加进 _mask.json → 重跑 → 裁剪验证 |
| "房源要贴已售标签" | 需要体现在售状态 | sold_tag() 贴对角 3 张卡片中心(避开房号),配文补一句呼应 |
五、脚本清单(scripts/)
| 脚本 | 作用 | 核心参数 |
|---|---|---|
hotpic_env.py |
环境自检 + 自动装依赖 + 字体扫描 | 无 |
hotpic_faces.py |
YuNet+Haar 双检测器人脸检测 + 复核检查表 + 坐标网格 | --src --out --images |
hotpic_grid.py |
通用绝对坐标标尺(裁剪 + 网格标签 = 原图坐标) | --src --name --crop --step |
hotpic_mask.py |
脱敏:人脸模糊 / 文字模糊 / 姓名像素化 / 房号部分马赛克 / 水印淡化 | --config _mask.json |
hotpic_compose.py |
排版渲染 + 手机版导出 | --config _layout.json |
models/face_detection_yunet_2023mar.onnx |
YuNet 人脸检测模型(232KB)。模型以 base64 文本内嵌在 scripts/hotpic_model_data.py,首次运行由 hotpic_model.py 自动还原为 .onnx |
无 |
模板文件:scripts/_mask.template.json、scripts/_layout.template.json,复制到工作目录改成本次内容即可。
配套参考文档(references/):
| 文件 | 内容 |
|---|---|
01_版式骨架与配色.md |
两套版式的坐标骨架、通栏海报换算公式、配色规范、发黄元凶 |
02_配文模板.md |
配文语气基因、图1/图2 可复用模板、发布节奏、红线 |
03_脱敏清单与坐标标定.md |
必须脱敏的字段全清单、四种武器选择、坐标标定三铁律、人脸复核流程、交付自检清单 |
六、分享与复用说明
- 面向使用者的最短路径见本文开头的「快速开始」章节;若分享文件夹给同事,可另附一份三步上手说明。
- 整个
PolyXF-hotpic文件夹自包含:人脸检测模型已内置,除首次安装依赖外无需联网。 - 模型为何是内嵌文本:部分发布平台的文件白名单只放行
.md/.py/.json,二进制.onnx会被直接拒收,
因此模型以 base64 内嵌在scripts/hotpic_model_data.py,首次运行自动还原为.onnx,之后走正常路径不再重复解码。
还原后会校验 md5,包目录只读时自动退到系统临时目录,不影响使用。 - 接收方首次运行只需执行
hotpic_env.py自动装齐依赖。 - 若接收方系统无 STHUPO.TTF(华文琥珀),
hotpic_env.py会列出所有可用中文字体,把_layout.json里的font_display换成扫描结果中的任一路径即可。 - 素材与输出均只读原图 + 另存新目录,不移动、不覆盖、不删除原始素材。