当前位置: 首页 > news >正文

AnyText2 在图片里玩文字而且还是所想即所得

AnyText2 在图片里玩文字而且还是所想即所得

flyfish

AnyText2 是一个超厉害的「图片文字编辑器」,能像玩「文字积木」一样随意控制图片里的文字,而且生成的文字超级逼真。

它能做什么?

  1. 在图片里生成指定文字,想写啥写啥

    • 比如你想做一张奶茶店海报,用 AnyText2 输入“第二杯半价”,选一个手写体字体,再调个粉色渐变颜色,文字就能“长”到海报背景里,连阴影和光线都和背景融为一体,看起来就像真实拍的照片一样自然。
  2. 修改现有图片里的文字

    • 比如拍了一张街景图,想把路边“整顿”的牌子改成“正常营业”,用 AnyText2 圈出文字区域,直接输入新内容,还能提取原图的字体和颜色,一键替换,完全看不出修改痕迹。

AnyText2是一种全新的方法,可在自然场景图像生成与编辑中实现对多语言文本属性的精准控制。我包含两个主要组件:
首先,WriteNet+AttnX架构,将文本渲染能力注入预训练的文本到图像(T2I)模型中。与前身AnyText相比,新方法不仅提升了图像真实感,还使推理速度提高了19.8%。
其次,从场景图像中提取字体和颜色的技术,并开发了文本嵌入模块(Text Embedding Module),将这些文本属性作为条件分别编码。作为AnyText的扩展,该方法允许为每行文本定制属性,使中文和英文的文本准确率分别提升了3.3%和9.3%。

技术架构与创新点

(1)WriteNet+AttnX架构:文本渲染能力的深度融合
  • 核心思路:在预训练的T2I模型(如Stable Diffusion)中插入自定义模块,使其具备文本渲染能力。
  • 技术突破
    • 图像真实感提升:通过优化文本与背景的融合算法(如阴影、透视、光照一致性),使生成的文本更贴近真实场景中的物理呈现;
    • 推理速度优化:采用轻量化注意力机制(AttnX)和层间特征复用技术,在不损失画质的前提下,推理速度较AnyText提升19.8%,更适合实时编辑场景。
(2)文本嵌入模块:多属性解耦与条件编码
  • 功能定位:从图像中提取文本的字体、颜色、大小、倾斜角度等属性,并将其编码为独立的条件向量,输入T2I模型以控制生成过程。
  • 关键技术
    • 字体与颜色提取:基于卷积神经网络(CNN)的图像特征解析器,可从复杂场景中分离文本区域并识别字体类型(如宋体、Times New Roman)和颜色值;
    • 属性解耦编码:通过独立的嵌入空间(Embedding Space)将字体、颜色等属性与文本内容分离,支持每行文本独立设置属性(如标题用粗体红色,正文用常规黑色);
    • 多语言适配:针对中文字符的高复杂性,设计了基于字形特征的嵌入层,使中文文本准确率提升3.3%,英文提升9.3%(通过OCR验证)。

在这里插入图片描述

AnyText2 处理和修改提示词(prompt)

两处重要代码

代码1

def modify_prompt(self, prompt):# 1. 处理引号:将中文引号替换为英文引号prompt = prompt.replace('“', '"')prompt = prompt.replace('”', '"')# 2. 提取双引号内的文本内容p = '"(.*?)"'  # 正则表达式:匹配双引号内的任意字符(非贪婪模式)strs = re.findall(p, prompt)  # 获取所有匹配结果# 3. 处理无引号的情况:若没有引号内容,默认添加一个空格作为占位if len(strs) == 0:strs = [' ']else:# 4. 将引号内的原始文本替换为占位符PLACE_HOLDERfor s in strs:prompt = prompt.replace(f'"{s}"', f'{PLACE_HOLDER}', 1)# 5. 检测是否包含中文if self.is_chinese(prompt):# 若翻译模型未初始化,直接返回if self.trans_pipe is None:return None, Noneold_prompt = prompt# 6. 调用翻译模型将中文提示词转为英文# 注意:翻译前添加句号,翻译后移除,可能是为了适配翻译模型的输入格式prompt = self.trans_pipe(input=prompt + ' .')['translation'][:-1]# 7. 确保占位符周围有空格,保持格式一致性prompt = prompt.replace(f'{PLACE_HOLDER}', f' {PLACE_HOLDER} ')print(f'Translate: {old_prompt} --> {prompt}')# 8. 返回处理后的提示词和被替换的原始文本列表return prompt, strsdef is_chinese(self, text):# 清理文本:移除特殊字符、空格等(checker._clean_text是内部方法)text = checker._clean_text(text)# 遍历每个字符,检查是否有中文字符for char in text:cp = ord(char)  # 获取字符的Unicode码点# _is_chinese_char是内部方法,判断是否为中文字符(如0x4E00-0x9FFF范围)if checker._is_chinese_char(cp):return Truereturn False

代码2

# img_prompt 是对图像整体的描述(如"木质桌面背景")
# text_prompt 是需要添加/编辑的文本内容(如'"新品:生椰拿铁",颜色用棕色')
img_prompt, _ = self.modify_prompt(img_prompt)
text_prompt, texts = self.modify_prompt(text_prompt)# 2. 错误检查:若翻译失败且无有效文本,返回错误信息
if (img_prompt is None or text_prompt is None) and texts is None:return None, -1, "You have input Chinese prompt but the translator is not loaded!", ""# 3. 统计需要处理的文本行数(引号内的文本片段数量)
n_lines = len(texts)# 4. 根据模式选择处理方式
if mode in ['text-generation', 'gen']:# 文本生成模式:创建空白图像作为基础edit_image = np.zeros((h, w, 3))elif mode in ['text-editing', 'edit']:# 文本编辑模式:需要参考图像和文本位置信息if draw_pos is None or ori_image is None:return None, -1, "Reference image and position image are needed for text editing!", ""# 5. 加载参考图像(ori_image):支持多种格式if isinstance(ori_image, str):# 从路径加载图像(BGR转RGB)ori_image = cv2.imread(ori_image)[..., ::-1]assert ori_image is not None, f"Can't read ori_image image from{ori_image}!"elif isinstance(ori_image, torch.Tensor):# 从PyTorch张量转换ori_image = ori_image.cpu().numpy()else:# 直接使用NumPy数组assert isinstance(ori_image, np.ndarray), f'Unknown format of ori_image: {type(ori_image)}'# 6. 预处理参考图像edit_image = ori_image.clip(1, 255)  # 限制像素值范围,避免掩码处理问题edit_image = check_channels(edit_image)  # 确保图像是RGB三通道edit_image = resize_image(edit_image, max_length=1024)  # 调整图像大小(长边不超过1024,且尺寸为64的倍数)h, w = edit_image.shape[:2]  # 更新图像尺寸,用于后续处理

Image Prompt(图像提示词)Text Prompt(文字提示词) 的处理

AnyText2实现了“图像场景由翻译后的英文提示词驱动,文本内容由原始多语言文本控制”的协同机制,既保证了T2I模型的兼容性,又实现了多语言文本属性的精准定制。

一、核心处理函数:modify_prompt 的作用

1. 格式统一:中英文引号标准化
prompt = prompt.replace('“', '"').replace('”', '"')  # 统一为英文双引号
  • 作用:确保输入的提示词(无论是中文还是英文)中的引号格式一致,便于后续正则表达式匹配。
2. 提取双引号内文本:分离内容与属性
strs = re.findall('"(.*?)"', prompt)  # 提取所有带引号的文本
for s in strs:prompt = prompt.replace(f'"{s}"', f'{PLACE_HOLDER}', 1)  # 替换为占位符*
  • 关键逻辑
    • Text Prompt专用:假设输入为'"Hello","世界"',则strs = ["Hello", "世界"]prompt变为"*", "*"
    • Image Prompt可能包含描述性文本:若Image Prompt"木质桌面,上面有写着"新品"的标牌",则提取["新品"]prompt变为"木质桌面,上面有写着*的标牌"
3. 中文翻译:适配英文T2I模型
if self.is_chinese(prompt):prompt = self.trans_pipe(input=prompt + ' .')['translation'][:-1]  # 翻译为英文prompt = prompt.replace(f'{PLACE_HOLDER}', f' {PLACE_HOLDER} ')  # 确保占位符前后有空格
  • 触发条件:当检测到中文(包括占位符外的字符)时,调用翻译模型(如nlp_csanmt_translation_zh2en)。
  • 示例
    • 中文Image Prompt"一只猫举着写有"你好"的牌子" → 翻译为英文"A cat holds a sign with * on it"
    • 中文Text Prompt'"你好","世界"' → 翻译为'"*", "*"'(保留占位符,仅翻译外围描述)。

二、双Prompt协同处理:img_prompt vs text_prompt

1. 输入示例

假设用户输入:

  • Image Prompt"咖啡馆场景,木质桌面,柔和灯光"(中文)
  • Text Prompt'"Special Offer","买一送一"'(中英文混合)
2. 处理流程
Step 1:分别调用modify_prompt
  • 处理img_prompt(中文)

    • 无引号文本 → strs = [' '](默认占位)。
    • 检测到中文 → 翻译为英文:"coffee shop scene, wooden table, soft lighting"
    • 输出:img_prompt = "coffee shop scene, wooden table, soft lighting", strs = [' '](无实际文本)。
  • 处理text_prompt(含引号)

    • 提取strs = ["Special Offer", "买一送一"]
    • 替换为"*", "*"prompt = "*", "*"
    • 检测到中文("买一送一")→ 翻译外围描述(但此处prompt中无外围中文,故不翻译)。
    • 输出:text_prompt = "*", "*", strs = ["Special Offer", "买一送一"]
Step 2:生成/编辑图像的前置准备
  • 模式判断

    • 若为gen(生成模式):创建空白图像edit_image = np.zeros((h, w, 3))
    • 若为edit(编辑模式):加载参考图像并预处理(如调整尺寸、通道检查)。
  • 文本位置处理

    • 通过draw_pos(位置掩码)确定文本区域,例如用户提供的掩码图像会被分割为多个区域,对应texts中的每行文本(n_lines = len(strs) = 2)。
Step 3:构建模型输入条件
  • 核心参数

    • info['glyphs']:存储文本的字形信息(基于字体渲染)。
    • info['positions']:文本在图像中的位置掩码。
    • info['colors']:文本颜色(支持RGB值,如text_colors="255,0,0 0,255,0"对应两行文本的颜色)。
  • 翻译后的提示词拼接

    cond = self.model.get_learned_conditioning(c_crossattn=[[img_prompt + ', ' + a_prompt] * img_count,  # 图像描述 + 质量提示[text_prompt] * img_count  # 处理后的文本提示(含占位符)]
    )
    
    • 最终传递给模型的文本提示为:"*, *"(英文),但实际生成时会结合strs中的原始文本("Special Offer""买一送一")的字形、位置和颜色信息。

三、关键技术点:占位符的「分离-翻译-还原」机制

1. 为什么需要占位符?
  • 避免翻译干扰:带引号的文本通常是需要保留的具体内容(如品牌名、标语),不应被翻译。
  • 属性解耦:将文本内容(如“买一送一”)与图像描述(如“咖啡馆场景”)分离,便于后续单独控制文本的字体、颜色等属性。
2. 占位符的生命周期
# 输入阶段(用户输入)
text_prompt = '"中文文本", "English Text"'# modify_prompt处理后
text_prompt = "*", "*"  # 占位符替换
texts = ["中文文本", "English Text"]  # 保存原始内容# 模型生成阶段(内部处理)
# 用占位符生成英文提示词,确保T2I模型理解布局和属性
prompt_for_model = "write * in red font on a wooden table"# 输出阶段(结果拼接)
input_prompt = prompt_for_model.replace('*', f'"{text}"', 1)  # 还原为原始文本
# 最终输出提示词:"write "中文文本" in red font on a wooden table"

四、多语言场景下的特殊处理

1. 纯中文场景
  • 输入
    • img_prompt"书店场景,书架上有写着"畅销书籍"的标签"
    • text_prompt'"小说专区"'
  • 处理流程
    1. img_prompt提取["畅销书籍"],翻译为"bookstore scene, bookshelf with * label"
    2. text_prompt提取["小说专区"],替换为"*",因无外围中文不翻译。
    3. 模型生成时,结合中文文本的字形(通过draw_glyph渲染)和翻译后的场景描述,生成包含中文文本的图像。
2. 中英文混合场景
  • 输入
    • img_prompt"A restaurant with a sign saying "今日特价""(英文中夹杂中文)
    • text_prompt'"Lunch Set", "¥50"'
  • 处理流程
    1. img_prompt检测到中文"今日特价",提取并翻译外围英文描述,最终为"A restaurant with a sign saying *"
    2. text_prompt无中文,直接保留'"Lunch Set", "¥50"',替换为"*, *"
    3. 模型生成时,img_prompt中的*对应"今日特价"(中文),text_prompt中的*对应英文和符号,分别渲染为对应语言的文本。

五、代码如何保证文本属性的精准控制?

1. 字体与颜色的独立编码
info['colors'] = [np.array([int(p) for p in s.split(',')]) for s in text_colors.split()]
font_paths = glyline_font_path.split()  # 支持每行单独指定字体路径
  • 机制:通过text_colorsglyline_font_path参数,为每行文本(对应texts中的元素)独立设置颜色和字体,与modify_prompt提取的文本内容一一对应。
2. 位置与布局的精准匹配
pos_imgs = self.separate_pos_imgs(pos_imgs, sort_priority)  # 按优先级排序文本区域
poly, pos_img = self.find_polygon(input_pos)  # 获取文本区域的多边形轮廓
  • 作用:根据用户提供的draw_pos(如掩码图像),将文本内容精准定位到图像的指定区域,确保生成的文本位置与提示词一致。

脉络

阶段Image Prompt 处理Text Prompt 处理
格式清洗统一引号,无引号则默认占位[' ']提取引号内文本,替换为*
语言检测若含中文则翻译为英文(保留*若含中文则翻译外围描述(引号内文本不翻译)
模型输入拼接英文场景描述(如"coffee shop, ..."传递含*的提示词(如"write * in red"
内容还原无(纯描述性文本)生成前用原始文本(texts)替换*
属性控制通过a_prompt调整图像质量(如"4k, HD"通过text_colorsfont_paths控制文本样式

在这里插入图片描述

http://www.xdnf.cn/news/558991.html

相关文章:

  • V2X协议|如何做到“车联万物”?【无线通信小百科】
  • Hutool 常用工具类实战指南
  • selenium——基础知识
  • 数据一致性校验算法
  • 创建与管理MySQL数据库
  • Google精准狙击OpenAI Codex,发布AI编程助手Jules!
  • Fluent Bit持久化配置指南:保障日志不丢失的关键策略
  • Elasticsearch高级面试题汇总及答案
  • AMBA三种总线详解并比较
  • 元宇宙赋能广州文化传承,激发新活力​
  • C语言学习之内存函数
  • AI练习:毛发旋转效果
  • 再议AOI算法
  • 通过强化学习让大模型自适应开启思考模式
  • 101个α因子#9
  • C++(3)
  • idea如何让文件夹分层显示,而不是圆点分割
  • Python训练营打卡 Day31
  • 模板引擎:FreeMarker
  • 基于pyttsx3的文字转语音实现
  • 输出字母在字符串中位置索引
  • 超强吸水宠物垫行业2025数据分析报告
  • 从计算机组成原理寻址方式参悟指针的本质
  • cpu的x86架构跟ARM架构的区别介绍
  • SpringBoot整合LangChain4J
  • 深入探讨 Java 中的函数式编程
  • 9-社区动态(Stack布局)
  • 探秘大数据架构:解锁高效数据处理的密码
  • SpringBoot3+Vue3(1)-后端 请求头校验,jwt退出登录,mybaits实现数据库用户校验
  • 拦截指定注解(FeignClient),补偿重试