'''Part of the implementation is borrowed and modified from TextDiffuser, publicly available at https://github.com/microsoft/unilm/blob/master/textdiffuser/inference.py'''import osimport jsonimport randomfrom tqdm import tqdmimport argparseimport numpy as npfrom packaging import versionfrom termcolor import coloredfrom PIL import Imagefrom datasets import disable_cachingimport torchimport torch.utils.checkpointfrom torchvision import transformsfrom accelerate.utils import set_seedfrom diffusers import AutoencoderKL, DDPMScheduler, UNet2DConditionModelfrom diffusers.utils import check_min_versionfrom diffusers.utils.import_utils import is_xformers_availablefrom transformers import CLIPTextModel, CLIPTokenizerfrom util import filter_segmentation_maskfrom model.text_segmenter.unet import UNetdisable_caching()check_min_version("0.15.0.dev0")PLACE_HOLDER = '*'def parse_args():parser = argparse.ArgumentParser(description="Simple example of a training script.")parser.add_argument("--pretrained_model_name_or_path",type=str,default='runwayml/stable-diffusion-v1-5', # no need to modify thishelp="Path to pretrained model or model identifier from huggingface.co/models. Please do not modify this.",)parser.add_argument("--revision",type=str,default=None,required=False,help="Revision of pretrained model identifier from huggingface.co/models.",)parser.add_argument("--mode",type=str,default="text-to-image-with-template",choices=["text-to-image-with-template"],help="Three modes can be used.",)parser.add_argument("--output_dir",type=str,default="./textdiffuser_laion_generated/",help="output path",)parser.add_argument("--seed",type=int,default=100,help="A seed for reproducible training.")parser.add_argument("--classifier_free_scale",type=float,default=9.0, # following stable diffusion (https://github.com/CompVis/stable-diffusion)help="Classifier free scale following https://arxiv.org/abs/2207.12598.",)parser.add_argument("--model_path",type=str,default='textdiffuser-ckpt/diffusion_backbone',help='path of model')parser.add_argument("--character_segmenter_path",type=str,default='textdiffuser-ckpt/text_segmenter.pth',help="checkpoint of character-level segmenter")parser.add_argument("--enable_xformers_memory_efficient_attention",action="store_true",default=True,help="Whether or not to use xformers.")parser.add_argument("--sample_steps",type=int,default=20,help="Diffusion steps for sampling.")parser.add_argument("--vis_num",type=int,default=4,help="Number of images to be sample. Please decrease it when encountering out of memory error.")parser.add_argument("--a_prompt",type=str,default='best quality, extremely detailed',help="additional prompt")parser.add_argument("--n_prompt",type=str,default='longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, watermark',help="negative prompt")parser.add_argument("--glyph_dir",type=str,default='/data/vdb/yuxiang.tyx/AIGC/data/laion_word/glyph_laion',help="path of glyph images from anytext evaluation dataset")parser.add_argument("--json_path",type=str,default='/data/vdb/yuxiang.tyx/AIGC/data/laion_word/test1k.json',help="json path for evaluation dataset")args = parser.parse_args()print(f'{colored("[√]", "green")} Arguments are loaded.')return argsdef load_json(file_path: str):with open(file_path, 'r', encoding='utf8') as f:content = json.load(f)return contentdef load_data(input_path):content = load_json(input_path)d = []count = 0for gt in content['data_list']:info = {}info['img_name'] = gt['img_name']info['caption'] = gt['caption']if PLACE_HOLDER in info['caption']:count += 1info['caption'] = info['caption'].replace(PLACE_HOLDER, " ")if 'annotations' in gt:polygons = []texts = []pos = []for annotation in gt['annotations']:if len(annotation['polygon']) == 0:continueif annotation['valid'] is False:continuepolygons.append(annotation['polygon'])texts.append(annotation['text'])pos.append(annotation['pos'])info['polygons'] = [np.array(i) for i in polygons]info['texts'] = textsinfo['pos'] = posd.append(info)print(f'{input_path} loaded, imgs={len(d)}')if count > 0:print(f"Found {count} image's caption contain placeholder: {PLACE_HOLDER}, change to ' '...")return ddef get_item(data_list, item):item_dict = {}cur_item = data_list[item]item_dict['img_name'] = cur_item['img_name']item_dict['caption'] = cur_item['caption']return item_dictdef main():args = parse_args()seed = args.seed if args.seed is not None else random.randint(0, 1000000)set_seed(seed)if os.path.exists(args.output_dir) is not True:os.makedirs(args.output_dir)# Load scheduler, tokenizer and models.tokenizer = CLIPTokenizer.from_pretrained(args.pretrained_model_name_or_path, subfolder="tokenizer", revision=args.revision)text_encoder = CLIPTextModel.from_pretrained(args.pretrained_model_name_or_path, subfolder="text_encoder", revision=args.revision).cuda()vae = AutoencoderKL.from_pretrained(args.pretrained_model_name_or_path, subfolder="vae", revision=args.revision).cuda()unet = UNet2DConditionModel.from_pretrained(args.model_path, subfolder="unet", revision=None).cuda()# load character-level segmentersegmenter = UNet(3, 96, True).cuda()segmenter = torch.nn.DataParallel(segmenter)segmenter.load_state_dict(torch.load(args.character_segmenter_path))segmenter.eval()# Freeze vae and text_encodervae.requires_grad_(False)text_encoder.requires_grad_(False)if args.enable_xformers_memory_efficient_attention:if is_xformers_available():import xformersxformers_version = version.parse(xformers.__version__)if xformers_version == version.parse("0.0.16"):print("xFormers 0.0.16 cannot be used for training in some GPUs. If you observe problems during training, please update xFormers to at least 0.0.17. See https://huggingface.co/docs/diffusers/main/en/optimization/xformers for more details.")unet.enable_xformers_memory_efficient_attention()else:raise ValueError("xformers is not available. Make sure it is installed correctly")# setup schedulersscheduler = DDPMScheduler.from_pretrained(args.pretrained_model_name_or_path, subfolder="scheduler")scheduler.set_timesteps(args.sample_steps)sample_num = args.vis_num# inference loopdata_list = load_data(args.json_path)for i in tqdm(range(len(data_list)), desc='generator'):item_dict = get_item(data_list, i)p = item_dict['img_name']img_name = item_dict['img_name'].split('.')[0] + '_3.jpg'if os.path.exists(os.path.join(args.output_dir, img_name)):continueinput_image_path = os.path.join(args.glyph_dir, p)prompt = item_dict['caption']template_image = Image.open(input_image_path).resize((256, 256)).convert('RGB')noise = torch.randn((sample_num, 4, 64, 64)).to("cuda") # (b, 4, 64, 64)input = noise # (b, 4, 64, 64)captions = [prompt + ', ' + args.a_prompt] * sample_numcaptions_nocond = [args.n_prompt] * sample_num# encode text promptsinputs = tokenizer(captions, max_length=tokenizer.model_max_length, padding="max_length", truncation=True, return_tensors="pt").input_ids.cuda() # (b, 77)encoder_hidden_states = text_encoder(inputs)[0].cuda() # (b, 77, 768)inputs_nocond = tokenizer(captions_nocond, max_length=tokenizer.model_max_length, padding="max_length", truncation=True, return_tensors="pt").input_ids.cuda() # (b, 77)encoder_hidden_states_nocond = text_encoder(inputs_nocond)[0].cuda() # (b, 77, 768)if args.mode == 'text-to-image-with-template':to_tensor = transforms.ToTensor()image_tensor = to_tensor(template_image).unsqueeze(0).cuda().sub_(0.5).div_(0.5) # (b, 3, 256, 256)with torch.no_grad():segmentation_mask = segmenter(image_tensor) # (b, 96, 256, 256)segmentation_mask = segmentation_mask.max(1)[1].squeeze(0) # (256, 256)segmentation_mask = filter_segmentation_mask(segmentation_mask) # (256, 256)segmentation_mask = torch.nn.functional.interpolate(segmentation_mask.unsqueeze(0).unsqueeze(0).float(), size=(256, 256), mode='nearest') # (b, 1, 256, 256)segmentation_mask = segmentation_mask.squeeze(1).repeat(sample_num, 1, 1).long().to('cuda') # (b, 1, 256, 256)feature_mask = torch.ones(sample_num, 1, 64, 64).to('cuda') # (b, 1, 64, 64)masked_image = torch.zeros(sample_num, 3, 512, 512).to('cuda') # (b, 3, 512, 512)masked_feature = vae.encode(masked_image).latent_dist.sample() # (b, 4, 64, 64)masked_feature = masked_feature * vae.config.scaling_factor # (b, 4, 64, 64)# diffusion processintermediate_images = []for t in tqdm(scheduler.timesteps):with torch.no_grad():noise_pred_cond = unet(sample=input, timestep=t, encoder_hidden_states=encoder_hidden_states, segmentation_mask=segmentation_mask, feature_mask=feature_mask, masked_feature=masked_feature).sample # b, 4, 64, 64noise_pred_uncond = unet(sample=input, timestep=t, encoder_hidden_states=encoder_hidden_states_nocond, segmentation_mask=segmentation_mask, feature_mask=feature_mask, masked_feature=masked_feature).sample # b, 4, 64, 64noisy_residual = noise_pred_uncond + args.classifier_free_scale * (noise_pred_cond - noise_pred_uncond) # b, 4, 64, 64prev_noisy_sample = scheduler.step(noisy_residual, t, input).prev_sampleinput = prev_noisy_sampleintermediate_images.append(prev_noisy_sample)# decode and visualizationinput = 1 / vae.config.scaling_factor * inputsample_images = vae.decode(input.float(), return_dict=False)[0] # (b, 3, 512, 512)# save pred_imgpred_image_list = []for image in sample_images.float():image = (image / 2 + 0.5).clamp(0, 1).unsqueeze(0)image = image.cpu().permute(0, 2, 3, 1).numpy()[0]image = Image.fromarray((image * 255).round().astype("uint8")).convert('RGB')pred_image_list.append(image)for idx, img in enumerate(pred_image_list):img_name = item_dict['img_name'].split('.')[0]+f'_{idx}' + '.jpg'img.save(os.path.join(args.output_dir, img_name))if __name__ == "__main__":main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。