sam3 (2)开发 - MKT

news/2025/11/21 23:47:52/文章来源:https://www.cnblogs.com/gooutlook/p/19254810

 

例子2

检测画框,并且合并

按照框大小,然后融合重叠的框

 

 

segmentation_comparison

 

 

segmentation_comparison

 

segmentation_comparison

 

 

例子1

检测画框,并且合并

按照分数排序,然后融合重叠的框

缺点 丢失框

 

 

例子1

检测画框,并且合并

按照分数排序,然后融合重叠的框

缺点 丢失框

segmentation_comparison

 

segmentation_comparison

 

segmentation_comparison

 

import torch
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import matplotlib.patches as patches
import time  # 添加时间模块#################################### For Image ####################################
from sam3.model_builder import build_sam3_image_model
from sam3.model.sam3_image_processor import Sam3Processor# 记录总开始时间
total_start_time = time.time()# 记录模型加载开始时间
model_load_start_time = time.time()# Load the model
model = build_sam3_image_model(checkpoint_path="/home/r9000k/v2_project/sam/sam3/assets/model/sam3.pt"
)
processor = Sam3Processor(model, confidence_threshold=0.5)# 记录模型加载结束时间
model_load_end_time = time.time()
model_load_time = model_load_end_time - model_load_start_time
print(f"模型加载时间: {model_load_time:.3f} 秒")# 记录单张检测开始时间
detection_start_time = time.time()image_path = "testimage/微信图片_20251120225838_38.jpg"
image_path = "3.jpg"
# Load an image
image = Image.open(image_path)
inference_state = processor.set_image(image)# Prompt the model with text
output = processor.set_text_prompt(state=inference_state, prompt="building") #building,road and playground building  car、people、bicycle# Get the masks, bounding boxes, and scores
masks, boxes, scores = output["masks"], output["boxes"], output["scores"]# 记录单张检测结束时间
detection_end_time = time.time()
detection_time = detection_end_time - detection_start_time
print(f"检测单张时间: {detection_time:.3f} 秒")
print(f"原始检测到 {len(masks)} 个分割结果")
print(f"掩码形状: {masks.shape}")def calculate_iou(box1, box2):"""计算两个边界框的IoU(交并比)"""# 解包坐标x1_1, y1_1, x1_2, y1_2 = box1x2_1, y2_1, x2_2, y2_2 = box2# 计算交集区域xi1 = max(x1_1, x2_1)yi1 = max(y1_1, y2_1)xi2 = min(x1_2, x2_2)yi2 = min(y1_2, y2_2)# 计算交集面积inter_area = max(0, xi2 - xi1) * max(0, yi2 - yi1)# 计算并集面积box1_area = (x1_2 - x1_1) * (y1_2 - y1_1)box2_area = (x2_2 - x2_1) * (y2_2 - y2_1)union_area = box1_area + box2_area - inter_area# 避免除以零if union_area == 0:return 0.0#iou_= inter_area / union_areaiou_2= inter_area / box2_areaiou_1= inter_area / box1_areaiou_=max(iou_2,iou_1)return iou_def calculate_mask_overlap(mask1, mask2):"""计算两个掩码的重叠比例(基于mask1)"""mask1_np = mask1.cpu().numpy().squeeze().astype(bool)mask2_np = mask2.cpu().numpy().squeeze().astype(bool)# 计算交集和mask1的面积intersection = np.logical_and(mask1_np, mask2_np)mask1_area = np.sum(mask1_np)if mask1_area == 0:return 0.0overlap_ratio = np.sum(intersection) / mask1_areareturn overlap_ratiodef fuse_overlapping_masks(masks, boxes, scores, iou_threshold=0.5, overlap_threshold=0.6):"""融合重叠的掩码和边界框参数:masks: 形状为 [N, 1, H, W] 的掩码张量boxes: 形状为 [N, 4] 的边界框张量scores: 形状为 [N] 的得分张量iou_threshold: IoU阈值,用于判定边界框是否重叠overlap_threshold: 掩码重叠阈值,用于判定是否融合"""if len(masks) == 0:return masks, boxes, scores# 转换为numpy数组进行处理(使用copy()避免负步长问题)boxes_np = boxes.cpu().numpy().copy()scores_np = scores.cpu().numpy().copy()# 按得分降序排序# 降序索引sorted_indices = np.argsort(scores_np)[::-1]# 根据索引重新调整顺序boxes_sorted = boxes_np[sorted_indices]scores_sorted = scores_np[sorted_indices]# 处理masks:先转换为列表,然后按排序索引重新组织masks_list = [masks[i] for i in range(len(masks))]# 根据索引重新调整顺序masks_sorted = [masks_list[i] for i in sorted_indices]# 初始化保留索引keep_indices = []suppressed = set()for i in range(len(boxes_sorted)):print('=====================',i)if i in suppressed:print('1 跳过',i)continuekeep_indices.append(i)for j in range(i + 1, len(boxes_sorted)):if j in suppressed:print('2 跳过',i)continue# 计算IoUiou = calculate_iou(boxes_sorted[i], boxes_sorted[j])if iou > iou_threshold:# 计算掩码重叠比例#overlap_ratio = calculate_mask_overlap(masks_sorted[i], masks_sorted[j])#if overlap_ratio > overlap_threshold:suppressed.add(j)print(f"融合检测结果: 索引 {sorted_indices[i]} (得分: {scores_sorted[i]:.3f}) 覆盖索引 {sorted_indices[j]} (得分: {scores_sorted[j]:.3f})"," iou:",iou)#print(f"  - IoU: {iou:.3f}, 掩码重叠比例: {overlap_ratio:.3f}")else:#keep_indices.append(i)print(f"xxxxxx融合检测结果: 索引 {sorted_indices[i]} (得分: {scores_sorted[i]:.3f}) 覆盖索引 {sorted_indices[j]} (得分: {scores_sorted[j]:.3f})"," iou:",iou)# 获取保留的检测结果final_indices = [sorted_indices[i] for i in keep_indices]# 使用PyTorch的索引操作来获取最终结果final_masks = torch.stack([masks_list[i] for i in final_indices])final_boxes = boxes[final_indices]final_scores = scores[final_indices]print(f"融合后剩余 {len(final_masks)} 个分割结果 (减少了 {len(masks) - len(final_masks)} 个)")return final_masks, final_boxes, final_scores# 应用融合函数
print("\n开始融合重叠的检测结果...")
fusion_start_time = time.time()# 调用融合函数
fused_masks, fused_boxes, fused_scores = fuse_overlapping_masks(masks, boxes, scores, iou_threshold=0.5,  # 可以调整这个阈值overlap_threshold=0.6  # 可以调整这个阈值
)fusion_time = time.time() - fusion_start_time
print(f"融合完成时间: {fusion_time:.3f} 秒")def overlay_masks_with_info(image, masks, boxes, scores, fusion_mode=False):"""在图像上叠加掩码,并添加ID、得分和矩形框masks: 形状为 [N, 1, H, W] 的四维张量boxes: 形状为 [N, 4] 的边界框张量 [x1, y1, x2, y2]scores: 形状为 [N] 的得分张量fusion_mode: 是否为融合后的模式(使用不同颜色)"""# 转换为RGB模式以便绘制image = image.convert("RGB")draw = ImageDraw.Draw(image)# 尝试加载字体,如果失败则使用默认字体try:# 尝试使用系统中文字体font = ImageFont.truetype("SimHei.ttf", 20)except:try:font = ImageFont.truetype("Arial.ttf", 20)except:font = ImageFont.load_default()# 将掩码转换为numpy数组并去除通道维度masks_np = masks.cpu().numpy().astype(np.uint8)  # 形状: [N, 1, H, W]masks_np = masks_np.squeeze(1)  # 移除通道维度,形状: [N, H, W]boxes_np = boxes.cpu().numpy()  # 形状: [N, 4]scores_np = scores.cpu().numpy()  # 形状: [N]n_masks = masks_np.shape[0]# 根据是否为融合模式选择不同的颜色映射if fusion_mode:cmap = plt.cm.get_cmap("viridis", n_masks)  # 融合模式使用viridis配色else:cmap = plt.cm.get_cmap("rainbow", n_masks)  # 原始模式使用rainbow配色for i, (mask, box, score) in enumerate(zip(masks_np, boxes_np, scores_np)):# 获取颜色color = tuple(int(c * 255) for c in cmap(i)[:3])# 确保掩码是二维的if mask.ndim == 3:mask = mask.squeeze(0)# 创建透明度掩码alpha_mask = (mask * 128).astype(np.uint8)  # 0.5透明度# 创建彩色覆盖层overlay = Image.new("RGBA", image.size, color + (128,))# 应用alpha通道alpha = Image.fromarray(alpha_mask, mode='L')overlay.putalpha(alpha)# 叠加到图像上image = Image.alpha_composite(image.convert("RGBA"), overlay).convert("RGB")draw = ImageDraw.Draw(image)# 绘制边界框x1, y1, x2, y2 = box# 确保坐标在图像范围内x1 = max(0, min(x1, image.width))y1 = max(0, min(y1, image.height))x2 = max(0, min(x2, image.width))y2 = max(0, min(y2, image.height))# 绘制矩形框draw.rectangle([x1, y1, x2, y2], outline=color, width=3)# 准备文本信息if fusion_mode:text = f"Fused-ID:{i} Score:{score:.3f}"else:text = f"ID:{i} Score:{score:.3f}"# 计算文本位置(在框的上方)try:# 新版本的PILleft, top, right, bottom = draw.textbbox((0, 0), text, font=font)text_width = right - lefttext_height = bottom - topexcept:# 旧版本的PILtext_width, text_height = draw.textsize(text, font=font)text_x = x1text_y = max(0, y1 - text_height - 5)# 绘制文本背景draw.rectangle([text_x, text_y, text_x + text_width + 10, text_y + text_height + 5], fill=color)# 绘制文本draw.text((text_x + 5, text_y + 2), text, fill="white", font=font)return image# 记录可视化开始时间
visualization_start_time = time.time()# 应用掩码叠加(原始结果)
original_image = Image.open(image_path)
result_image_original = overlay_masks_with_info(original_image, masks, boxes, scores, fusion_mode=False)# 应用掩码叠加(融合后结果)
result_image_fused = overlay_masks_with_info(original_image, fused_masks, fused_boxes, fused_scores, fusion_mode=True)# 保存结果图像
output_path_original = "segmentation_result_original.png"
output_path_fused = "segmentation_result_fused.png"
result_image_original.save(output_path_original)
result_image_fused.save(output_path_fused)# 记录可视化结束时间
visualization_end_time = time.time()
visualization_time = visualization_end_time - visualization_start_time
print(f"可视化时间: {visualization_time:.3f} 秒")print(f"原始分割结果已保存到: {output_path_original}")
print(f"融合后分割结果已保存到: {output_path_fused}")# 设置中文字体或使用英文避免警告
try:# 尝试设置中文字体plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']plt.rcParams['axes.unicode_minus'] = False
except:pass# 显示对比图像
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 8))# 原始结果
ax1.imshow(result_image_original)
ax1.set_title(f"原始结果: 检测到 {len(masks)} 个分割结果", fontsize=14)
ax1.axis('off')# 融合后结果
ax2.imshow(result_image_fused)
ax2.set_title(f"融合后结果: 剩余 {len(fused_masks)} 个分割结果", fontsize=14)
ax2.axis('off')plt.tight_layout()
plt.savefig("segmentation_comparison.png", bbox_inches='tight', dpi=300, facecolor='white')
plt.show()# 记录总结束时间
total_end_time = time.time()
total_time = total_end_time - total_start_time# 打印详细的时间统计
print("\n" + "="*50)
print("运行时间统计:")
print("="*50)
print(f"模型加载时间: {model_load_time:.3f} 秒")
print(f"检测单张时间: {detection_time:.3f} 秒")
print(f"融合处理时间: {fusion_time:.3f} 秒")
print(f"可视化时间:   {visualization_time:.3f} 秒")
print("-"*50)
print(f"总运行时间:   {total_time:.3f} 秒")
print("="*50)def save_mask(masks_to_save, boxes_to_save, scores_to_save, prefix="mask"):"""保存单个掩码的通用函数"""print(f"\n保存{prefix}的单个掩码...")for i, (mask, box, score) in enumerate(zip(masks_to_save, boxes_to_save, scores_to_save)):# 创建单个掩码的可视化base_image = Image.open(image_path).convert("RGB")single_draw = ImageDraw.Draw(base_image)# 尝试加载字体try:single_font = ImageFont.truetype("SimHei.ttf", 24)except:try:single_font = ImageFont.truetype("Arial.ttf", 24)except:single_font = ImageFont.load_default()# 处理掩码mask_np = mask.cpu().numpy().squeeze().astype(np.uint8)color = tuple(int(c * 255) for c in plt.cm.get_cmap("viridis", len(masks_to_save))(i)[:3])# 创建透明度掩码alpha_mask = (mask_np * 128).astype(np.uint8)overlay = Image.new("RGBA", base_image.size, color + (128,))alpha = Image.fromarray(alpha_mask, mode='L')overlay.putalpha(alpha)base_image = Image.alpha_composite(base_image.convert("RGBA"), overlay).convert("RGB")single_draw = ImageDraw.Draw(base_image)# 绘制边界框和文本x1, y1, x2, y2 = box.cpu().numpy()single_draw.rectangle([x1, y1, x2, y2], outline=color, width=3)text = f"ID:{i} Score:{score:.3f}"try:# 新版本的PILleft, top, right, bottom = single_draw.textbbox((0, 0), text, font=single_font)text_width = right - lefttext_height = bottom - topexcept:# 旧版本的PILtext_width, text_height = single_draw.textsize(text, font=single_font)text_x = x1text_y = max(0, y1 - text_height - 5)single_draw.rectangle([text_x, text_y, text_x + text_width + 10, text_y + text_height + 5], fill=color)single_draw.text((text_x + 5, text_y + 2), text, fill="white", font=single_font)base_image.save(f"{prefix}_with_info_{i:02d}.png")print(f"保存{prefix} {i:02d}.png (得分: {score:.3f})")# # 保存原始和融合后的单个掩码
# save_mask(masks, boxes, scores, "original_mask")
# save_mask(fused_masks, fused_boxes, fused_scores, "fused_mask")print("所有处理完成!")

  

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

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

相关文章

P1719 最大加权矩阵

点击查看代码 #include<bits/stdc++.h>using namespace std;const int N=125;int a[N][N],s[N][N]; int n;int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n;for(int i=1;i<=n;…

Python pyinstaller convert py file as *.exe file

pyinstaller --onefile PythonTest9.py import uuid import datetime import timedef get_uuid_time():return f{uuid.uuid4().hex}_{datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")}def get_time_uui…

掌控Apple Silicon MacBook电池健康的神器

batt是一款专为Apple Silicon MacBook设计的电池充电控制工具,通过智能限制充电阈值来延长电池寿命,支持MagSafe LED控制和多种防过充机制,让您的MacBook电池保持最佳健康状态。batt - Apple Silicon MacBook 电池充…

HTML 零基础入门到实战(附 100 + 代码示例与图解教程)

https://blog.csdn.net/Liu_Zhong_Yuan/article/details/148105231

立方数

立方数 题目描述 对于给定的正整数 $N$,求最大的正整数 $A$,使得存在正整数 $B$,满足 $A^3B=N$。 输入包含 $T$ 组数据,$1 \leq T \leq 10000$;$1 \leq N \leq 10^{18}$。 输入描述: 第一行数字 $T$ 表示数据组数…

Rust环境搭建

步骤一:设置 Rustup 镜像, 修改配置~/.zshrcexport RUSTUP_DIST_SERVER="https://rsproxy.cn" export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"步骤二:安装 Rust(请先完成步骤一的环…

Python json list as json and write in json file,tkinter popup as messagebox

import uuid import datetime import time import json import tkinter as tk import tkinter.messagebox as msgBoxclass Book():def __init__(self,id,name,isbn,comment,content,summary,title,topic):self.id=idse…

Trick——树

Part1 问题:统计一条根链上的点权值出现次数。 首先不难想到对根链建立主席树,可以做到 \(O(nlogn)-O(logn)\) 的优秀复杂度。 码量有些大,但它是在线算法。 离线算法 我们这样考虑: 若知道 \(x\) 的根链的点权集合…

windows的句柄和linux的fd对比

以下是不严谨的对比表格:特性 Linux 文件描述符 (FD) Windows 句柄 (Handle)资源覆盖范围 主要集中在 I/O 相关资源。(文件、目录、设备、管道、套接字等) 覆盖所有内核对象。(I/O 资源 + 进程、线程、同步对象、内…

20251117~20251123NOIP模拟赛

20251117NOIP模拟赛 A: 题目大意: 有 \(n\) 个点,每个点有 \(a_{i}\) 个孔,你现在要在这 \(n\) 个点中连 \(n - 1\) 条边,使得他们联通。 每条边连接两个孔,每个孔最多连接 \(1\) 条边,两种连接方案相同,当且仅…

谁又不是一边破碎一边前行

谁又不是一边破碎一边前行太厉害了语文考试,一句看起来如此简单的话居然能扯出这么多的内涵。 突然联想到考试的经历,或许也是一边破碎一边前行。下午考数学的时候不知道为啥心情非常烦躁,最后两分钟极限发现一个弱…

Java的第一个程序

HelloWorld 1.随便新建一个文件夹,存放代码 2.新建一个Java文件 文件后缀名为.java Hello.java 【注意点】系统可能没有显示文件后缀名,我们需要手动打开 3.编写代码 public class Hello{public static main(String[…

题解:qoj14419 Maximum Segment Sum

清新小巧题! 题意:给出一个数 \(n\),求对于所有 \(k=[0,n]\),满足由 \(-1,1\) 构成的 \(n\) 长序列的最大子段和等于 \(k\) 的个数。 做法: 首先肯定考虑把答案改为算 \(\le k\) 的个数再差分得到答案。 考虑怎么…

20232310 2025-2026-1 《网络与系统攻防技术》实验七实验报告

1.实验内容及要求 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法。具体实践有 (1)简单应用SET工具建立冒名网站 (2)ettercap DNS spoof (3)结合应用两种技术,用DNS spoof引导特…

完整教程:基于Python楼王争霸劳动竞赛数据处理分析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

46

所学时间:9小时 博客量啊 代码量:几百 所学知识:ai儿童作文生成器

【springboot线上零食舱系统】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

html导出pdf

index.vue <template><div class="app"><el-button type="primary" size="small" @click="exportPDF">导出pdf</el-button><h1>导出PDF进度:…

【第7章 I/O编程与异常】为什么句柄看起来像指针却不是指针?

这是一个极佳的问题,触及了操作系统设计中抽象、兼容性与安全的核心权衡。 “句柄看起来像指针却不是指针”这一现象,本质上是 Windows API 在类型系统上的“善意伪装”,背后有深刻的历史和工程原因。🔍 一、为什…