-
2025-07-13: 🔥 The training code has been updated. The code now supports multi-scale training.
-
2025-07-13: 🔥 Update the low-VRAM version of the Gradio demo, which It currently requires 25GB of VRAM to run. Looking forward to more efficient, lower-memory solutions from the community.
-
2025-07-08: 🔥 ComfyUI Node is supported! You can now build an workflow based on FLUX-Text for editing posters. It is definitely worth trying to set up a workflow to automatically enhance product image service information and service scope. Meanwhile, utilizing the first and last frames enables the creation of video data with text effects. Thanks to the
community work, FLUX-Text was run on 8GB VRAM.
-
2025-07-03: 🔥 We have released our
pre-trained checkpoints on Hugging Face! You can now try out FLUX-Text with the official weights.
-
2025-06-26: ⭐️ Inference and evaluate code are released. Once we have ensured that everything is functioning correctly, the new model will be merged into this repository.
We recommend using Python 3.10 and PyTorch with CUDA support. To set up the environment:
1# Create a new conda environment
2conda create -n flux_text python=3.10
3conda activate flux_text
4
5# Install other dependencies
6pip install -r requirements.txt
7pip install flash_attn --no-build-isolation
8pip install Pillow==9.5.0
FLUX-Text is an open-source version of the scene text editing model. FLUX-Text can be used for editing posters, emotions, and more. The table below displays the list of text editing models we currently offer, along with their foundational information.
1import numpy as np
2from PIL import Image
3import torch
4import yaml
5
6from src.flux.condition import Condition
7from src.flux.generate_fill import generate_fill
8from src.train.model import OminiModelFIll
9from safetensors.torch import load_file
10
11config_path = ""
12lora_path = ""
13with open(config_path, "r") as f:
14 config = yaml.safe_load(f)
15model = OminiModelFIll(
16 flux_pipe_id=config["flux_path"],
17 lora_config=config["train"]["lora_config"],
18 device=f"cuda",
19 dtype=getattr(torch, config["dtype"]),
20 optimizer_config=config["train"]["optimizer"],
21 model_config=config.get("model", {}),
22 gradient_checkpointing=True,
23 byt5_encoder_config=None,
24 )
25
26state_dict = load_file(lora_path)
27state_dict_new = {x.replace('lora_A', 'lora_A.default').replace('lora_B', 'lora_B.default').replace('transformer.', ''): v for x, v in state_dict.items()}
28model.transformer.load_state_dict(state_dict_new, strict=False)
29pipe = model.flux_pipe
30
31prompt = "lepto college of education, the written materials on the picture: LESOTHO , COLLEGE OF , RE BONA LESELI LESEL , EDUCATION ."
32hint = Image.open("assets/hint.png").resize((512, 512)).convert('RGB')
33img = Image.open("assets/hint_imgs.jpg").resize((512, 512))
34condition_img = Image.open("assets/hint_imgs_word.png").resize((512, 512)).convert('RGB')
35hint = np.array(hint) / 255
36condition_img = np.array(condition_img)
37condition_img = (255 - condition_img) / 255
38condition_img = [condition_img, hint, img]
39position_delta = [0, 0]
40condition = Condition(
41 condition_type='word_fill',
42 condition=condition_img,
43 position_delta=position_delta,
44 )
45generator = torch.Generator(device="cuda")
46res = generate_fill(
47 pipe,
48 prompt=prompt,
49 conditions=[condition],
50 height=512,
51 width=512,
52 generator=generator,
53 model_config=config.get("model", {}),
54 default_lora=True,
55)
56res.images[0].save('flux_fill.png')
You can upload the glyph image and mask image to edit text region. Or you can use manual edit to obtain glyph image and mask image.
first, download the model weight and config in
HuggingFace
1json_paths = [
2 ['dataset/Anyword/data_text_recog_glyph/Art/data-info.json', 'AnyWord-3M/ocr_data/Art/imgs/'],
3 ['dataset/Anyword/data_text_recog_glyph/COCO_Text/data-info.json', 'AnyWord-3M/ocr_data/COCO_Text/imgs/'],
4 ['dataset/Anyword/data_text_recog_glyph/icdar2017rctw/data-info.json', 'AnyWord-3M/ocr_data/icdar2017rctw/imgs'],
5 ['dataset/Anyword/data_text_recog_glyph/LSVT/data-info.json', 'AnyWord-3M/ocr_data/LSVT/imgs'],
6 ['dataset/Anyword/data_text_recog_glyph/mlt2019/data-info.json', 'AnyWord-3M/ocr_data/mlt2019/imgs/'],
7 ['dataset/Anyword/data_text_recog_glyph/MTWI2018/data-info.json', 'AnyWord-3M/ocr_data/MTWI2018/imgs'],
8 ['dataset/Anyword/data_text_recog_glyph/ReCTS/data-info.json', 'AnyWord-3M/ocr_data/ReCTS/imgs'],
9 ['dataset/Anyword/data_text_recog_glyph/laion/data_v1.1-info.json', 'AnyWord-3M/laion/imgs'],
10 ['dataset/Anyword/data_text_recog_glyph/wukong_1of5/data_v1.1-info.json', 'AnyWord-3M/wukong_1of5/imgs'],
11 ['dataset/Anyword/data_text_recog_glyph/wukong_2of5/data_v1.1-info.json', 'AnyWord-3M/wukong_2of5/imgs'],
12 ['dataset/Anyword/data_text_recog_glyph/wukong_3of5/data_v1.1-info.json', 'AnyWord-3M/wukong_3of5/imgs'],
13 ['dataset/Anyword/data_text_recog_glyph/wukong_4of5/data_v1.1-info.json', 'AnyWord-3M/wukong_4of5/imgs'],
14 ['dataset/Anyword/data_text_recog_glyph/wukong_5of5/data_v1.1-info.json', 'AnyWord-3M/wukong_5of5/imgs'],
15 ]
-
Download the ODM weights in
HuggingFace and change
odm_loss/modelpath in the
config file.
-
(Optional) Download the pretrained weight in
HuggingFace and change
reuse_lora_path in the
config file.
-
Run the training scripts. With 48GB of VRAM, you can train at 512×512 resolution with a batch size of 2 in LoRA rank 8.
For
Anytext-benchmark, please set the
config_path,
model_path,
json_path,
output_dir in the
eval/gen_imgs_anytext.sh and generate the text editing results.
1bash eval/eval_ocr.sh
2bash eval/eval_fid.sh
3bash eval/eval_lpips.sh
Our work is primarily based on
OminiControl,
AnyText,
Open-Sora,
Phantom. We are sincerely grateful for their excellent works.
If you find our paper and code helpful for your research, please consider starring our repository ⭐ and citing our work ✏️.
1@misc{lan2025fluxtext,
2 title={FLUX-Text: A Simple and Advanced Diffusion Transformer Baseline for Scene Text Editing},
3 author={Rui Lan and Yancheng Bai and Xu Duan and Mingxing Li and Lei Sun and Xiangxiang Chu},
4 year={2025},
5 eprint={2505.03329},
6 archivePrefix={arXiv},
7 primaryClass={cs.CV}
8}