使用Dino+SAM+Stable diffusion 自动进行图片的修改

SAM 是Mata发布的“Segment Anything Model”可以准确识别和提取图像中的对象。 它可以分割任何的图片,但是如果需要分割特定的物体,则需要需要点、框的特定提示才能准确分割图像。 所以本文将介绍一种称为 Grounding Dino 的技术来自动生成 SAM 进行分割所需的框。

除了分割以外,我们还可以通过将 SAM 与 Grounding Dino 和 Stable Diffusion 相结合,获得高度准确图像分割结果,并且对分割后的图像进行细微的更改。

下面就是我们需要的所有的包:

 `%cd /content
 
 !git clone https://github.com/IDEA-Research/Grounded-Segment-Anything
 
 %cd /content/Grounded-Segment-Anything 
 !pip install -q-r requirements.txt
 %cd /content/Grounded-Segment-Anything/GroundingDINO
 !pip install -q .
 %cd /content/Grounded-Segment-Anything/segment_anything
 !pip install -q .
 %cd /content/Grounded-Segment-Anything

导入必要的包:

 importos, sys
 
 sys.path.append(os.path.join(os.getcwd(), "GroundingDINO"))
 
 importargparse
 importcopy
 
 fromIPython.displayimportdisplay
 fromPILimportImage, ImageDraw, ImageFont
 fromtorchvision.opsimportbox_convert
 
 # Grounding DINO
 importGroundingDINO.groundingdino.datasets.transformsasT
 fromGroundingDINO.groundingdino.modelsimportbuild_model
 fromGroundingDINO.groundingdino.utilimportbox_ops
 fromGroundingDINO.groundingdino.util.slconfigimportSLConfig
 fromGroundingDINO.groundingdino.util.utilsimportclean_state_dict, get_phrases_from_posmap
 fromGroundingDINO.groundingdino.util.inferenceimportannotate, load_image, predict
 
 importsupervisionassv
 
 # segment anything
 fromsegment_anythingimportbuild_sam, SamPredictor
 importcv2
 importnumpyasnp
 importmatplotlib.pyplotasplt
 
 
 # diffusers
 importPIL
 importrequests
 importtorch
 fromioimportBytesIO
 fromdiffusersimportStableDiffusionInpaintPipeline
 
 
 fromhuggingface_hubimporthf_hub_download

然后我们设置处理的设备:

 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

然后我们创建一个 GroundingDino 模型的实例。

 defload_model_hf(repo_id, filename, ckpt_config_filename, device='cpu'):
     cache_config_file=hf_hub_download(repo_id=repo_id, filename=ckpt_config_filename)
 
     args=SLConfig.fromfile(cache_config_file) 
     args.device=device
     model=build_model(args)
     
     cache_file=hf_hub_download(repo_id=repo_id, filename=filename)
     checkpoint=torch.load(cache_file, map_location=device)
     log=model.load_state_dict(clean_state_dict(checkpoint['model']), strict=False)
     print("Model loaded from {} \n => {}".format(cache_file, log))
     _=model.eval()
     returnmodel   
 ckpt_repo_id="ShilongLiu/GroundingDINO"
 ckpt_filenmae="groundingdino_swinb_cogcoor.pth"
 ckpt_config_filename="GroundingDINO_SwinB.cfg.py"
 
 
 groundingdino_model=load_model_hf(ckpt_repo_id, ckpt_filenmae, ckpt_config_filename, device)

下面开始创建SAM 模型,定义模型并创建一个实例。

 ! wget https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth
 
 sam_checkpoint ='sam_vit_h_4b8939.pth'
 
 sam_predictor = SamPredictor(build_sam(checkpoint=sam_checkpoint).to(device))

这里我们使用与训练的 vit_h 模型,下面就是扩散模型了:

 sd_pipe=StableDiffusionInpaintPipeline.from_pretrained(
     "stabilityai/stable-diffusion-2-inpainting",
     torch_dtype=torch.float16,
 ).to(device)

然后我们开始测试:

 # Load image 
 defdownload_image(url, image_file_path):
     r=requests.get(url, timeout=4.0)
     ifr.status_code!=requests.codes.ok:
         assertFalse, 'Status code error: {}.'.format(r.status_code)
 
     withImage.open(BytesIO(r.content)) asim:
         im.save(image_file_path)
     print('Image downloaded from url: {} and saved to: {}.'.format(url, image_file_path))
 
 
 local_image_path="assets/inpaint_demo.jpg"
 image_url="https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTA1L3Vwd2s2MTc3Nzk0MS13aWtpbWVkaWEtaW1hZ2Uta293YnN1MHYuanBn.jpg"
 
 download_image(image_url, local_image_path)
 image_source, image=load_image(local_image_path)
 Image.fromarray(image_source)

先使用Grounding Dino 进行检测:

 # detect object using grounding DINO
 defdetect(image, text_prompt, model, box_threshold=0.3, text_threshold=0.25):
   boxes, logits, phrases=predict(
       model=model, 
       image=image, 
       caption=text_prompt,
       box_threshold=box_threshold,
       text_threshold=text_threshold
   )
 
   annotated_frame=annotate(image_source=image_source, boxes=boxes, logits=logits, phrases=phrases)
   annotated_frame=annotated_frame[...,::-1] # BGR to RGB 
   returnannotated_frame, boxes
 annotated_frame, detected_boxes=detect(image, text_prompt="bench", model=groundingdino_model)
 Image.fromarray(annotated_frame)

让我们看看结果:

然后使用 SAM 分割这个狐狸:

 defsegment(image, sam_model, boxes):
   sam_model.set_image(image)
   H, W, _=image.shape
   boxes_xyxy=box_ops.box_cxcywh_to_xyxy(boxes) *torch.Tensor([W, H, W, H])
 
   transformed_boxes=sam_model.transform.apply_boxes_torch(boxes_xyxy.to(device), image.shape[:2])
   masks, _, _=sam_model.predict_torch(
       point_coords=None,
       point_labels=None,
       boxes=transformed_boxes,
       multimask_output=False,
       )
   returnmasks.cpu()
 
 defdraw_mask(mask, image, random_color=True):
     ifrandom_color:
         color=np.concatenate([np.random.random(3), np.array([0.8])], axis=0)
     else:
         color=np.array([30/255, 144/255, 255/255, 0.6])
     h, w=mask.shape[-2:]
     mask_image=mask.reshape(h, w, 1) *color.reshape(1, 1, -1)
     
     annotated_frame_pil=Image.fromarray(image).convert("RGBA")
     mask_image_pil=Image.fromarray((mask_image.cpu().numpy() *255).astype(np.uint8)).convert("RGBA")
 
     returnnp.array(Image.alpha_composite(annotated_frame_pil, mask_image_pil))
 segmented_frame_masks=segment(image_source, sam_predictor, boxes=detected_boxes)
 annotated_frame_with_mask=draw_mask(segmented_frame_masks[0][0], annotated_frame)
 Image.fromarray(annotated_frame_with_mask)

这样就可以通过上面的分割结果为的扩散模型生成掩码:

 # create mask images 
 mask=segmented_frame_masks[0][0].cpu().numpy()
 inverted_mask= ((1-mask) *255).astype(np.uint8)
 
 
 image_source_pil=Image.fromarray(image_source)
 image_mask_pil=Image.fromarray(mask)
 inverted_image_mask_pil=Image.fromarray(inverted_mask)
 
 
 display(*[image_source_pil, image_mask_pil, inverted_image_mask_pil])

绘时我们还需要一个背景的掩码,这个就是上面掩码的反操作

 defgenerate_image(image, mask, prompt, negative_prompt, pipe, seed):
   # resize for inpainting 
   w, h=image.size
   in_image=image.resize((512, 512))
   in_mask=mask.resize((512, 512))
 
   generator=torch.Generator(device).manual_seed(seed) 
 
   result=pipe(image=in_image, mask_image=in_mask, prompt=prompt, negative_prompt=negative_prompt, generator=generator)
   result=result.images[0]
 
   returnresult.resize((w, h))

然后我们可以开始改图,输入一个提示:

 prompt=" a brown bulldog"
 negative_prompt="low resolution, ugly"
 seed=-1# for reproducibility 
 
 generated_image=generate_image(image=image_source_pil, mask=image_mask_pil, prompt=prompt, negative_prompt=negative_prompt, pipe=sd_pipe, seed=seed)
 generated_image

或者用上面的背景掩码来修改背景:

 prompt="a hill with grasses ,weak sunlight "
 negative_prompt="people, low resolution, ugly"
 seed=32# for reproducibility 
 
 generated_image=generate_image(image_source_pil, inverted_image_mask_pil, prompt, negative_prompt, sd_pipe, seed)
 generated_image

可以看到效果还是很好的

SAM、Grounding Dino 和 Stable Diffusion 的组合为我们提供了强大的工具。这些技术为探索令人兴奋的图像处理世界提供了坚实的基础 并为艺术家和开发者提供巨大的创造潜力。

如果你想在线测试,这里有完整的源代码:

https://avoid.overfit.cn/post/e9e083807a434935910c8116c85c8375

作者:Amir Shakiba


http://www.niftyadmin.cn/n/277186.html

相关文章

C++中的list容器

文章目录 list的介绍list的使用list的构造list iterator的使用list capacitylist元素访问list modifierslist的迭代器失效 list与vector的对比 list的介绍 list是可以在常数范围内的任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代;   …

Web App Manager - 将任何网站转换为应用程序

Web App Manager - 将任何网站转换为应用程序 WebApp Manager 是一款实用程序,由 Linux Mint 和 Peppermint 基于 Peppermint 的 ICE 合作创建——用户可以使用该应用程序将他们喜欢的应用程序转换为独立的 Web 应用程序,它最早于 2010 年首次发布&…

Java集合迭代器、Fail-Fast、Fail-Safe机制

Iterator是Java集合中迭代器的顶级接口,在此接口中定义了遍历集合的方法。 注意:Iterable与Iterator不是同一个概念 Iterable是可迭代的意思,实现了该接口就代表这个集合是可以利用迭代器和forEach()方法进行遍历的。 因此Iterable是所有集合…

Android 9.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(一)

1.前言 在9.0的系统rom产品定制化开发中,在原生系统SystemUI下拉状态栏的通知栏的通知背景默认是白色四角的背景, 由于在产品设计中,需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景, 然后通知显示流程,设置默认下拉状态栏UI中的…

java紫砂壶交易购物系统 mysql

网络紫砂壶可充通过色彩、图片、说明、设置动画加强了产品了宣传,大大达到了陶瓷业的“色型”要求。实现产品管理方便,起到立竿见影的效果,不用因为更改菜色而重新印刷。只要在后台鼠标轻轻一点,全线马上更新。采用B/S模式&#x…

Neo4j导出和导入数据库

Neo4j 4.x版本和5.x版本的导出导入有区别,这里分开来讲。 1 4.x版本 1.1 准备 导入导出之前要先关闭neo4j服务。 .neo4j stop 1.2 数据导出 进入$NEO4J_HOME%/bin目录执行如下数据库导出命令: neo4j-admin dump --database=neo4j --to=F:/neo4j_backupneo4j_graph.db.…

ChetGPT是什么,如何访问

ChetGPT是什么 ChetGPT是一款基于大规模语言模型的人工智能聊天机器人,它可以和用户进行自然流畅的对话,提供个性化的服务和建议。现在,我们非常热情地邀请您来体验ChatGPT的功能! ChatGPT的特点 ChatGPT具有以下几个特点和优势&…

【网络进阶】服务器模型Reactor与Proactor

文章目录 1. Reactor模型2. Proactor模型3. 同步IO模拟Proactor模型 在高并发编程和网络连接的消息处理中,通常可分为两个阶段:等待消息就绪和消息处理。当使用默认的阻塞套接字时(例如每个线程专门处理一个连接),这两…