当前位置:首页 > 技术 > 正文内容

高质量图像分割模型 SAM-HQ 实战指南

访客 技术 2026年7月14日 1

SAM-HQ(Segment Anything in High Quality)是由 ETH VIS 团队推出的零样本分割模型,在 NeurIPS 2023 上发布。该模型在原始 SAM 基础上优化了掩码生成质量,特别擅长处理边缘细节丰富的物体,支持全图自动分割和交互式点选分割两种模式。

环境配置与模型部署

获取源码并配置运行环境:

git clone https://github.com/SysCV/sam-hq.git
cd sam-hq
conda create -n samhq python=3.9
conda activate samhq
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
pip install -r requirements.txt

下载预训练权重文件(vit_h 版本精度最高):

wget https://huggingface.co/lkeab/hq-sam/resolve/main/sam_hq_vit_h.pth -P ./pretrained/

基础推理实现

以下是完整的图像分割推理代码,包含模型初始化与可视化输出:

import numpy as np
import torch
from PIL import Image
import matplotlib.pyplot as plt
from segment_anything import sam_model_registry
from segment_anything.utils.transforms import ResizeLongestSide

# 配置设备与模型路径
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
ckpt_path = "./pretrained/sam_hq_vit_h.pth"

# 加载 HQ-SAM 模型
sam = sam_model_registry["vit_h"](checkpoint=ckpt_path)
sam.to(device)
sam.eval()

# 预处理函数
def prepare_image(img_path):
    raw_img = np.array(Image.open(img_path).convert("RGB"))
    transform = ResizeLongestSide(sam.image_encoder.img_size)
    input_img = transform.apply_image(raw_img)
    input_tensor = torch.as_tensor(input_img, device=device).permute(2, 0, 1).contiguous()
    return raw_img, sam.preprocess(input_tensor.unsqueeze(0))

# 执行推理
src_img, img_tensor = prepare_image("demo.jpg")
with torch.no_grad():
    features = sam.image_encoder(img_tensor)
    sparse_emb, dense_emb = sam.prompt_encoder(points=None, boxes=None, masks=None)
    mask_pred, hq_token = sam.mask_decoder(
        image_embeddings=features,
        image_pe=sam.prompt_encoder.get_dense_pe(),
        sparse_prompt_embeddings=sparse_emb,
        dense_prompt_embeddings=dense_emb,
        multimask_output=True,
        hq_token_only=True
    )

# 提取高质量掩码并可视化
high_quality_mask = torch.sigmoid(mask_pred[:, -1, :, :]).squeeze().cpu().numpy()
plt.imshow(src_img)
plt.imshow(high_quality_mask, alpha=0.6, cmap='jet')
plt.axis('off')
plt.savefig("output.png", bbox_inches='tight', pad_inches=0)

交互式点选分割

通过指定前景/背景点实现精细化分割控制:

def segment_with_points(image_path, fg_coords, bg_coords=None):
    """
    fg_coords: 前景点坐标列表 [(x1, y1), (x2, y2), ...]
    bg_coords: 背景点坐标列表,可选
    """
    img_np, img_prep = prepare_image(image_path)
    h, w = img_np.shape[:2]
    
    # 坐标归一化
    def normalize(coords):
        if coords is None:
            return None
        arr = np.array(coords)
        return arr / np.array([w, h])
    
    fg_norm = normalize(fg_coords)
    bg_norm = normalize(bg_coords) if bg_coords else None
    
    # 构建点标签(1=前景, 0=背景)
    point_coords = np.vstack([fg_norm, bg_norm]) if bg_norm else fg_norm
    point_labels = np.array([1]*len(fg_coords) + [0]*len(bg_coords)) if bg_norm else np.ones(len(fg_coords))
    
    # 编码提示
    coords_torch = torch.as_tensor(point_coords[None, ...], device=device)
    labels_torch = torch.as_tensor(point_labels[None, ...], device=device)
    
    with torch.no_grad():
        img_feats = sam.image_encoder(img_prep)
        sparse_emb, dense_emb = sam.prompt_encoder(
            points=(coords_torch, labels_torch),
            boxes=None,
            masks=None
        )
        masks, scores, hq_feat = sam.mask_decoder(
            image_embeddings=img_feats,
            image_pe=sam.prompt_encoder.get_dense_pe(),
            sparse_prompt_embeddings=sparse_emb,
            dense_prompt_embeddings=dense_emb,
            multimask_output=True,
            hq_token_only=True
        )
    
    # 选择置信度最高的掩码
    best_idx = torch.argmax(scores)
    final_mask = masks[0, best_idx].cpu().numpy()
    return final_mask

# 示例:分割花朵的特定花瓣
target_mask = segment_with_points(
    "flower.jpg",
    fg_coords=[(450, 320), (480, 350)],  # 花瓣上的两个点
    bg_coords=[(300, 200)]  # 背景排除点
)

批量处理与性能优化

针对视频序列或大批量图像的高效处理方案:

from tqdm import tqdm
import os

class HQSegmentor:
    def __init__(self, model_type="vit_h", checkpoint=None):
        self.sam = sam_model_registry[model_type](checkpoint=checkpoint)
        self.sam.to(device)
        self.sam.eval()
        self.input_size = self.sam.image_encoder.img_size
        
    def encode_batch(self, image_batch):
        """批量编码图像特征"""
        with torch.cuda.amp.autocast():  # 混合精度加速
            return self.sam.image_encoder(image_batch)
    
    def batch_segment(self, img_dir, output_dir, grid_size=32):
        """自动网格采样分割"""
        os.makedirs(output_dir, exist_ok=True)
        img_files = [f for f in os.listdir(img_dir) if f.endswith(('.jpg', '.png'))]
        
        for fname in tqdm(img_files):
            img_path = os.path.join(img_dir, fname)
            img_raw, img_tensor = self.prepare(img_path)
            
            # 生成网格点提示
            h, w = img_raw.shape[:2]
            grid_x = np.linspace(0, w-1, grid_size)
            grid_y = np.linspace(0, h-1, grid_size)
            grid_points = np.array([[x, y] for y in grid_y for x in grid_x])
            
            # 分块处理避免显存溢出
            batch_points = np.array_split(grid_points, max(1, len(grid_points)//64))
            all_masks = []
            
            for pts in batch_points:
                mask = self.predict_from_points(img_raw, pts)
                all_masks.append(mask)
            
            # 合并掩码结果
            merged = self.merge_masks(all_masks)
            self.save_overlay(img_raw, merged, os.path.join(output_dir, fname))

# 初始化并运行
segmentor = HQSegmentor(checkpoint="./pretrained/sam_hq_vit_l.pth")
segmentor.batch_segment("./input_images/", "./segmented_output/")

相关生态工具

Autodistill-SAM-HQ:自动化标注流水线,支持将 SAM-HQ 作为教师模型生成伪标签,用于训练下游检测模型。

Grounded-SAM-HQ:融合 Grounding DINO 的文本检测能力与 SAM-HQ 的分割精度,实现"文本描述→目标定位→高质量分割"的全流程。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。