AI生成图片文字乱码怎么解决的

文章导读
AI 生成的图片里文字乱码,先不要急着改提示词。它通常只出在四个环节里的一个:模型自己在“画字”、后端用代码往图上叠字、提示词或返回结果在传输过程中被编码破坏,或者展示端字体没有加载。判断清楚属于哪一层,再决定改哪一处;否则容易在提示词里反复加“请正确书写中文”,结果越改越乱。下面按真实排查顺序走一遍。
📋 目录
  1. Ⅰ AI先定位在哪一层
  2. Ⅱ AI:先看这四个位置
  3. Ⅲ AI:按可能性从高到低排除
  4. Ⅳ AI:改完怎么确认真的解决了
A A

AI 生成的图片里文字乱码,先不要急着改提示词。它通常只出在四个环节里的一个:模型自己在“画字”、后端用代码往图上叠字、提示词或返回结果在传输过程中被编码破坏,或者展示端字体没有加载。判断清楚属于哪一层,再决定改哪一处;否则容易在提示词里反复加“请正确书写中文”,结果越改越乱。下面按真实排查顺序走一遍。

图片里的文字乱码,先分层:方块或豆腐块多是字体缺字形,问号、菱形、Ã 这类连续怪符号多是编码不对,笔画扭曲但结构像字的才是模型在“画字”。可以先查后处理叠字这条线的字体路径和 UTF-8 编码,再决定要不要换成“生成无字底图 + 后处理排版”。模型对中文长文本的渲染能力有限,换字体解决不了这一层。

AI先定位在哪一层

同一个“乱码”,落在不同层,处理动作完全不同。可以把出图放大后按下面这张清单对号入座,这一步用不了一分钟,但能省掉后面无数次试错。

  • 字形缺失(排版合成层):出现方块、豆腐块或统一的替代符号。判断依据是所有中文都长一个样、英文和数字却正常。问题在字体本身没有中文字形。
  • 编码错乱(请求传输层):出现问号、菱形,或 ä½ 这类连续怪符号,英文数字也可能被一起打乱。判断依据是图片文字编码和代码文件的字符集对不上。
  • 伪汉字(模型生成层):笔画扭曲、结构像字但不是字、多一笔少一笔。判断依据是放大看没有真正的横竖撇捺,只有轮廓。
  • 压字或被裁(排版合成层):文字形态正常,但溢出画布、两行叠在一起或被裁掉半边。判断依据是字形没问题,只是坐标和字号算错了。

这条顺序的实际意义是:字形缺失和编码错乱都还能靠改代码解决,伪汉字靠改提示词基本修不好,得换方案。先分清,再动手。

AI:先看这四个位置

下面四个位置按“先看哪里最省时间”排列,命令可以直接复制,路径和单元名需要换成你自己的。

1. 日志:实际发出去的提示词和字体路径

看日志是为了确认“你以为发出去的”和“真的发出去的”是不是同一个东西。在服务机上执行:

AI生成图片文字乱码怎么解决的
journalctl -u image-api -n 300 --no-pager | grep -Ei 'prompt|font|text'
# 跑在容器里时
docker logs --tail 300 image-api 2>&1 | grep -Ei 'prompt|font'

重点看两件事:提示词里的中文是不是完整的、font 打印出来的是不是你配置的那个路径。如果日志里提示词已经是问号或转义串,问题在传输层,后面的字体排查可以先放下。

2. 命令输出:字体和产物本身

这一步确认字体文件真的存在、真的包含中文字形,以及输出图片的格式对不对:

fc-list :lang=zh | head -n 20
ls -l /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc
file ./out.png
identify -verbose ./out.png | head -n 20

fc-list :lang=zh 输出为空,说明这台机器上根本没有可用的中文字体,后面写什么路径都没用。容器镜像尤其容易缺,基础镜像经常不带任何中文字体。

3. 配置项:字体、编码、画布

需要逐个核对的键通常就这几个:字体文件路径(font_path 或 font_family)、字号、画布宽高、文字区域坐标、输出编码(charset 或 encoding)、请求超时。字体项要写绝对路径,不要写字体名全靠系统去猜。配置文件里如果出现中文,先确认文件本身是 UTF-8 而不是 GBK。

AI生成图片文字乱码怎么解决的

4. 面板字段:平台上实际生效的参数

在生成平台的任务详情页或参数面板里,能看到这次任务实际用的提示词、负面提示词、宽高、seed、模型版本和文字区域设置。常见情况是面板上填了中文,但请求体在序列化时被转义或截断,面板显示的只是一份“原样记录”。面板上关于模型版本、并发额度、是否支持固定 seed 这类会变的信息,请以该平台控制台的模型列表页和用量页为准,本文不写具体数值。

AI:按可能性从高到低排除

排在前面的成因出现频率更高,建议按顺序排除,每一条都配一个能立刻执行的动作。

  1. 后处理用了默认字体。Pillow 里 ImageFont.load_default() 这类写法只带基础字形,画中文就是方块。确认动作:把代码里构造字体的那几行和实际 font 参数打印出来看。处理:显式指定 truetype 字体文件路径。
  2. 编码不统一。确认动作:执行 python3 -c "import sys,locale;print(sys.getdefaultencoding(), locale.getpreferredencoding())",再把接口返回存成文件用 python3 -m json.tool resp.json 看中文是否完好。处理:脚本文件存成 UTF-8,HTTP 响应带 charset=utf-8,数据库连接也统一 UTF-8。
  3. 直接让模型画中文长文本。确认动作:把提示词里的文字要求去掉,只留画面描述重出一次,看文字区域还有没有伪汉字。处理:改成生成无字底图,再用确定字体在后处理阶段叠字,这是目前最稳的做法。
  4. 字号和坐标算错。确认动作:把画布宽高临时放大一倍、字号调小一档重出,看是否还压字。处理:用 draw.textbbox 按实际文本量出宽高再定位,不要写死坐标。
  5. 展示端没加载字体。确认动作:把图片下载到本地,用系统看图工具打开。本地正常、页面异常,就是前端字体或字符集的问题,与生成流程无关。

容易踩的坑:把叠字用的字体路径写在代码里,同时又在部署环境里改了一次字体目录,线上跑的是旧路径,本地却一切正常。改动字体后务必在目标环境执行一次 fc-list :lang=zh 和 ls -l 核对,不要只信本地结果。

AI:改完怎么确认真的解决了

确认方式不是“看起来好了”,而是用同一组输入重跑并对比。下面这段可以直接复制执行,替换脚本名和文案即可:

AI生成图片文字乱码怎么解决的
# 三条不同长度、中英混合的文案,覆盖边界情况
python3 -c "
from PIL import Image, ImageDraw, ImageFont
FONT='/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc'
font=ImageFont.truetype(FONT,48)
for i,t in enumerate(['限时上新','SHOP NOW','满300减50 第二件半价']):
    img=Image.new('RGB',(720,140),'white'); d=ImageDraw.Draw(img)
    box=d.textbbox((24,24),t,font=font)
    d.text((24,24),t,font=font,fill='black')
    img.save(f'check_{i}.png')
    print(i,t,box)
"
ls -l check_*.png

把 check_0.png 到 check_2.png 逐张打开看:字形完整、没有方块、没有溢出,才算这一步通过。textbbox 打印出来的右边界如果超过图片宽度,说明字号还需要往下调。

稳定判断建议留出观察时间:至少覆盖长短不同的几条文案、中英文两种内容,再观察一到两天内的真实任务。只验一张图很容易刚好碰上那条能渲染的短文案,从而误判为已经修好。同时在任务详情页核对一次实际生效的字体参数和模型版本,确保线上和本地一致。

回滚要提前准备好,改配置前先备份:

cp -a config.yaml "config.yaml.bak.$(date +%F_%H%M)"
# 确认没解决问题时,改回上一份并重启
ls -t config.yaml.bak.* | head -n 1
cp -a "$(ls -t config.yaml.bak.* | head -n 1)" config.yaml
systemctl restart image-api

如果这次换的是镜像或模型版本,回滚就是把镜像 tag 和模型版本一起退回去,tag 的具体命名规则需要结合你们的发布流程确认。回滚后同样用上面那段渲染脚本再跑一遍,确认文字恢复正常,不要只看服务有没有起来。