【小贪】项目实战——Zero-shot根据文字提示分割出图片目标掩码

目标描述

给定RGB视频或图片,目标是分割出图像中的指定目标掩码。我们需要复现两个Zero-shot的开源项目,分别为IDEA研究院的GroundingDINO和Facebook的SAM。首先使用目标检测方法GroundingDINO,输入想检测目标的文字提示,可以获得目标的anchor box。将上一步获得的box信息作为SAM的提示,分割出目标mask。具体效果如下(测试数据来自VolumeDeform数据集):

在这里插入图片描述

其中GroundingDINO根据white shirt的文字输入计算的box信息为:"shirt_000500": "[194.23726, 2.378189, 524.09503, 441.5135]"。项目实测下来单张图片的预测速度GroundingDINO要慢于SAM。GroundingDINO和SAM均会给出多个预测结果,当选择置信度最高的结果时两个模型也会存在预测不准确的情况。

论文简介

GroundingDINO

GroundingDINO extends a closedset detector DINO by performing vision-language modality fusion at multiple phases, including a feature enhancer, a language-guided query selection module, and a cross-modality decoder. Such a deep fusion strategy effectively improves open-set object detection.

在这里插入图片描述

SAM

  • 简介:使用三个组件建立图像分割的foundation model,解决一系列下游分割问题,可zero-shot生成
  • 关键技术:
    1. promptable分割任务:使用prompt engineering,prompt不确定时输出多目标mask
    2. 分割模型:image encoder + prompt encoder -> mask decoder
    3. 数据驱动:SA-1B(1B masks from 11M imgs)手工标注->半自动->全自动
  • Limitation:存在不连贯不精细的mask结果;交互式实时mask生成但是img encoder耗时;text-to-mask任务效果不鲁棒

在这里插入图片描述
在这里插入图片描述

项目实战

两个项目的复现很简单,按照github的readme配置相关环境并运行程序。当然也可以直接使用一站式项目Grounded Segment Anything等。当需要分割的图片较多时,可以修改GroundingDINO的demo.shdemo/inference_on_a_image.py文件将检测结果保存至json文件。

demo/inference_on_a_image.py文件

# 修改plot_boxes_to_image函数输出box信息
image_with_box, mask, box_coor = plot_boxes_to_image(image_pil, pred_dict)
# obj为目标名称,i为当前图片的索引
obj = 'shirt'
data = {f'{obj}_{str(i).zfill(6)}': str(list(box_coor.cpu().detach().numpy()))}
with open("box.json", "r", encoding="utf-8") as f:old_data = json.load(f)old_data.update(data)
with open("box.json", "w", encoding="utf-8") as f:json.dump(old_data, f, indent=4)# f.write(json.dumps(old_data, indent=4, ensure_ascii=False))
f.close()

然后SAM再读取json文件获取box信息,将SAM的输入提示改为box。

测试代码

import os
import numpy as np
import matplotlib.pyplot as plt
import cv2
import glob
import jsoncoords = []def show_mask(mask, ax, random_color=False):if random_color:color = np.concatenate([np.random.random(3), np.array([0.6])], 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)ax.imshow(mask_image)def show_points(coords, labels, ax, marker_size=375):pos_points = coords[labels == 1]neg_points = coords[labels == 0]ax.scatter(pos_points[:, 0], pos_points[:, 1], color='green', marker='*', s=marker_size, edgecolor='white',linewidth=1.25)ax.scatter(neg_points[:, 0], neg_points[:, 1], color='red', marker='*', s=marker_size, edgecolor='white',linewidth=1.25)def show_box(box, ax):x0, y0 = box[0], box[1]w, h = box[2] - box[0], box[3] - box[1]ax.add_patch(plt.Rectangle((x0, y0), w, h, edgecolor='green', facecolor=(0, 0, 0, 0), lw=2))def on_click(event):global coordsif event.button == 1:x, y = event.xdata, event.ydataprint(f"鼠标左键点击:x={x:.2f}, y={y:.2f}")coords.append([x, y])# if len(coords) == 2:#     fig.canvas.mpl_disconnect(cid)elif event.button == 3:print("鼠标右键点击")def get_mask(image, mask_id=1, click_coords=False, choose_mask=False, box=None):image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# plt.figure(figsize=(10, 10))# plt.imshow(image)# plt.axis('on')if click_coords:global coordsfig, ax = plt.subplots()  # 创建画布和子图对象fig.set_size_inches(30, 20)  # 设置宽度和高度,单位为英寸(inch)ax.imshow(image)cid = fig.canvas.mpl_connect('button_press_event', on_click)plt.show()else:  # 如果使用 必须全局coords = []from segment_anything import SamPredictor, sam_model_registrysam_checkpoint = "sam_vit_h_4b8939.pth"model_type = "vit_h"device = "cuda"sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)sam.to(device=device)predictor = SamPredictor(sam)predictor.set_image(image)input_point = np.array(coords)input_label = np.array([1] * len(coords))# plt.figure(figsize=(10, 10))# plt.imshow(image)# show_points(input_point, input_label, plt.gca())# plt.axis('on')# plt.show()input_box = boxif len(coords) == 0:input_point = Noneinput_label = Nonemasks, scores, logits = predictor.predict(point_coords=input_point,point_labels=input_label,box=input_box[None, :],multimask_output=True)if choose_mask:plt.figure(figsize=(60, 20))plt.subplot(1, 3, 1)plt.imshow(image)show_mask(masks[0], plt.gca())# show_points(input_point, input_label, plt.gca())plt.title(f"Mask 0, Score: {scores[0]:.3f}", fontsize=18)plt.subplot(1, 3, 2)plt.imshow(image)show_mask(masks[1], plt.gca())# show_points(input_point, input_label, plt.gca())plt.title(f"Mask 1, Score: {scores[1]:.3f}", fontsize=18)plt.subplot(1, 3, 3)plt.imshow(image)show_mask(masks[2], plt.gca())# show_points(input_point, input_label, plt.gca())plt.title(f"Mask 2, Score: {scores[1]:.3f}", fontsize=18)plt.show()mask_id = int(input())  # 通过输入idx或者设置特定的idx输出mask = masks[mask_id]mask = np.tile(np.expand_dims(mask, axis=-1), 3)mask_data = np.where(mask, 255, 0)# mask_image = np.where(mask, image/255, 0.)# plt.figure(figsize=(10, 10))# plt.imshow(mask_image)# plt.show()if click_coords: coords.clear()return mask_dataif __name__ == '__main__':obj = 'shirt'color_path = f'/Data/VolumeDeformData/{obj}/data/'mask_path = f'/Data/VolumeDeformData/{obj}/mask/'if not os.path.exists(mask_path):os.makedirs(mask_path)img_paths = []for extension in ["jpg", "png", "jpeg"]:img_paths += glob.glob(os.path.join(color_path, "*.{}".format(extension)))json_path = 'GroundingDINO-main/box.json'with open(json_path, "r", encoding="utf-8") as f:data = json.load(f)for i in range(len(img_paths) // 2):img_name = f'frame-{str(i).zfill(6)}.color.png'img = cv2.imread(color_path + img_name)id = f'{obj}_{str(i).zfill(6)}'box = np.array(list(map(float, data[id][1:-1].split(','))))mask = get_mask(img, mask_id=2, click_coords=False, choose_mask=False, box=box)cv2.imwrite(mask_path + str(i).zfill(6) + '.png', mask)print(img_name)f.close()

相关链接

  • GroundingDINO github arXiv
  • SAM Demo github arXiv
  • Grounded Segment Anything github

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/37688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp中如何进行微信小程序的分包

思路:在uniapp中对微信小程序进行分包,和原生微信小程序进行分包的操作基本上没区别,主要就是在pages.json中进行配置。 如图,我新增了一个包diver-page 此时需要在pages.json中的subPackages数组中新增一项 root代表这个包的根…

用好华为小助手,生活总能快人一步

嘿!朋友们!你们有没有想过,如果身边有一个小助手,他不仅聪明伶俐,还能在生活的方方面面给予你最贴心的关怀和帮助,让我们的日常生活变得更加方便和快捷,那该有多好!没错,…

谈谈创意设计中的AI、AGI、AIGC

在当今的数字化时代,创意设计领域正经历着前所未有的变革。随着人工智能(AI)、通用人工智能(AGI)以及人工智能生成内容(AIGC)的迅猛发展,设计师们的工作方式和创作手段都发生了深刻的…

Swift 中的 StoreKit 测试

文章目录 前言创建一个 StoreKit Demo使用 SKTestSessionaskToBuyEnabled 属性总结前言 StoreKit 框架的第二次迭代是我在过去几年中应用程序中最重大的变化。最近版本的 StoreKit 框架已完全采用了 Swift 语言特性,如 async 和 await。本篇内容我们将讨论 StoreKitTest 框架…

【揭秘】嘴尚绝卤味健康新风尚,让你吃得美味又健康!

在快节奏的现代生活中,美食不仅是味蕾的享受,更是健康生活的追求。今天,我们要聊的就是备受食客们青睐的“嘴尚绝卤味”——如何在享受美味的同时,也能兼顾健康饮食的理念。 一、卤味文化,源远流长 卤味,作…

Redis缓存管理机制

在当今快节奏的数字世界中,性能优化对于提供无缝的用户体验至关重要。缓存在提高应用程序性能方面发挥着至关重要的作用,它通过将经常使用或处理的数据存储在临时高速存储中来减少数据库负载并缩短响应时间,从而减少系统的延迟。Redis 是一种…

navicat Lite 版

navicat Lite 版: Navicat 出了一个 Navicat Premium 的Lite版。 官方现在链接:https://www.navicat.com.cn/download/navicat-premium-lite#windows 从官网可以看到现在能够下载最新版本 17,支持各种平台

[vue2/vue3] 详细剖析watch、computed、watchEffect的区别,原理解读

前言:哈喽,大家好,我是前端菜鸟的自我修养!今天给大家分享【深入剖析watch、computed、watchEffect的区别】,并提供具体代码帮助大家深入理解,彻底掌握!原创不易,如果能帮助到带大家…

为什么企业应用开发,c++干不过java?

在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「c的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!! C/C这种东西,根本…

一个 API 客户端和一份 TS 学习手册

第75期: Insomnia:超好看的 API 客户端 项目介绍: 一款适用于 GraphQL、REST、WebSockets 和 gRPC 的开源 API 客户端,颜值超高。 跨平台,支持 Mac、Windows 和 Linux。但不支持网页版,需要下载客户端。…

Supabase 自托管部署实践

Supabase 是 Firebase 的开源替代品。使用 Postgres 数据库、身份验证、即时 API、边缘函数、实时订阅、存储和向量嵌入来启动您的项目。 Supabase介绍 Supabase 是一个开源的后端即服务(BaaS)平台,提供了一系列工具和服务,帮助…

CrimsonEDR:一款恶意软件模式识别与EDR策略评估工具

关于CrimsonEDR CrimsonEDR是一个功能强大的开源项目,该项目旨在帮助广大研究人员识别特定的恶意软件模式,以此来优化终端检测与响应(EDR)的策略方案。通过使用各种不同的检测方案,可以加深开发人员与研究人员加深对安…

SpringBoot入门实战:SpringBoot整合WebSocket

1.背景介绍 SpringBoot是一个快速开发的框架,它可以帮助我们快速开发Web应用程序。SpringBoot整合WebSocket是SpringBoot的一个组件,它可以帮助我们快速开发WebSocket应用程序。 WebSocket是一种新的协议,它可以让客户端和服务器之间建立持久…

MSYS2教程(windows环境下使用linux工具)

MSYS2教程(windows环境下使用linux工具) 1.msys2简介 MSYS2(Minimal SYStem 2)是一个集成了大量的GNU工具链、工具和库的开源软件包集合。它提供了一个类似于Linux的shell环境,可以在Windows系统中编译和运行许多Linux应用程序和工具。 MS…

excel修改批量一列单价的金额并保留1位小数

1.打开表格,要把单价金额变成现在的两倍,数据如下: 2.把单价这一列粘贴到一个新的sheet页面,在B2单元格输入公式:A2*2 然后按enter回车键,这时候吧鼠标放到B2单元格右下角,会出现一个黑色的小加号&#xf…

《信创数据库沙龙上海站:共话发展,智启未来》

2024 年 6 月 29 日周六 14:00,信创数据库沙龙在上海市徐汇区建国西路 285 号科投大厦 13 楼金星厅成功举办。本次活动吸引了众多学术界和产业界的专家、学者以及技术爱好者参与。 活动中,多位嘉宾带来了精彩分享。薛晓刚探讨了 Oracle 在国内的前景&a…

EAGLE-2:一种高效无损的推测性采样方法,提升LLM的推理速度。

欢迎关注我的公众号:Halo咯咯 01。概述 北京大学的研究人员联合微软研究院、滑铁卢大学以及Vector研究所共同推出了EAGLE-2,这是一种利用上下文感知的动态草图树来增强推测性采样的方法。EAGLE-2在先前的EAGLE方法基础上进行了改进,不仅显著…

【源码+文档+调试讲解】基于vue的线上点餐系统

摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了线上点餐系统的开发全过程。通过分析线上点餐系统管理的不足,创建了一个计算机管理线上点餐系统的方案。文章介绍了线上点餐系统的系统分析部分&…

电脑提示vcomp140.dll缺失怎么解决?vcomp140.dll是什么文件?

当你的电脑提示vcomp140.dll缺失的时候,你就应该要注意了,因为这个提示的出现,代表你的某个程序开不了!想要程序能正常运行,那么只要修复好这个vcomp140.dll文件就可以了,下面我们就来给大家详细的说说说vc…

超详细之IDEA上传项目到Gitee完整步骤

1. 注册gitee 账号密码,gitee官网地址:Gitee官网,注册完成后,登录。 2. 创建仓库,在主页左下角有新建按钮,点击新建后会进入到此页面填写仓库信息。 3. 创建完成后复制仓库地址 4. 打开IntelliJ IDEA新建或…