土建设计网站,怎样学习网站建设,无锡网站建设唯唯网络,贸易公司取什么名字Meta 一直是开发图像和视频模型的领导者#xff0c;现在他们又增加了一个新东西#xff1a;Meta Sapiens。和Homo sapiens一样#xff0c;这个模型也是关于人类的。它旨在执行与人类相关的任务#xff0c;例如理解身体姿势、识别身体部位、预测深度#xff0c;甚至确定皮肤…Meta 一直是开发图像和视频模型的领导者现在他们又增加了一个新东西Meta Sapiens。和Homo sapiens一样这个模型也是关于人类的。它旨在执行与人类相关的任务例如理解身体姿势、识别身体部位、预测深度甚至确定皮肤纹理等表面细节。
2023-2024 年许多计算机视觉模型都专注于创建逼真的人类图像。虽然存在许多用于姿势估计和分割等任务的模型但 Meta 的 Sapiens 模型是专门为与人类相关的任务而设计的。
本博客解释了 Meta 如何创建这个统一模型、优缺点以及它与其他模型的比较。 NSDT工具推荐 Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 1、Meta Sapiens 的三大支柱
Meta 声称用于与人类相关的任务的模型应该满足以下三个关键品质
泛化这意味着该模型在许多不同情况下都能很好地工作。例如它可以处理不同的光照条件、相机角度甚至各种类型的衣服。广泛适用该模型可以做很多事情。它可以估计姿势、识别身体部位甚至预测某物与相机的距离所有这些都不需要进行大的改变。高保真度它可以创建高质量、详细的结果。例如如果任务是生成一个人的 3D 模型结果将看起来非常逼真具有清晰的细节如面部特征和身体形状。
Meta Sapiens 使用一些强大的技术来实现这些任务。让我们简单地看一下其中的一些
MAE蒙版自动编码器将其视为一种使用拼图进行有效学习的方法。该模型查看缺少一些部分的图像如缺少部分的拼图并尝试填补空白。这使模型更好地理解图像并节省训练时间。例如如果模型在图像中看到一个人手臂的一部分缺失它可以通过理解图像的其余部分来猜测手臂应该是什么样子。使用关键点和分割该模型识别人体上的 308 个点包括手、脚、脸和躯干。它还知道大约 28 个不同的身体部位从头发到嘴唇再到四肢非常详细。为了训练模型Meta 使用了真实的人体扫描和合成数据这有助于它非常详细地了解人类。
2、2D 姿势估计 - 了解人体运动
这项任务就像给模型一张图片并要求它猜测关键身体部位在哪里。该模型会寻找眼睛、肘部、膝盖等的位置。例如如果您上传某人跑步的照片该模型可以准确识别他们的手臂、腿和头部在图像中的位置。
该过程通过创建“热图”来工作这些热图显示了身体部位在特定位置的可能性。该模型经过训练通过调整直到其猜测热图与身体部位的实际位置紧密匹配以最大限度地减少错误。
架构
输入图像I ∈ R^H×W×3其中 H 为高度W 为宽度。步骤 1重新缩放图像 — 输入图像被调整为固定高度 H 和宽度 W。这样做是为了在所有图像中标准化输入大小。步骤 2姿势估计变换器 (P) — 变换器模型处理图像以预测关键点位置。这涉及a边界框输入在图像中的人周围提供一个边界框。b关键点热图该模型生成 K 个热图其中每个热图代表关键点位于某个位置的概率。例如一个热图代表右肘另一个代表左膝依此类推。步骤 3损失函数均方误差 — 这里使用的损失函数是均方误差 (MSE)。该模型将预测的热图 ŷ ∈ R^H×W×K 与地面真实关键点 y 进行比较并使用 MSE 计算差异 L_pose MSE(y, ŷ)步骤 4编码器-解码器架构 - 姿势估计模型使用编码器-解码器设置。编码器使用预训练的权重初始化而解码器则随机初始化。然后对整个系统进行微调以完成关键点预测任务。关键点差异与之前的模型可能只能检测 68 个面部点相比Meta 的 Sapiens 模型可以检测多达 243 个面部关键点捕捉眼睛、嘴唇、鼻子、耳朵等周围的更精细的细节。
2.1 代码实现
下载姿势模型的检查点并按照后续步骤操作
TASK pose
VERSION sapiens_1bmodel_path get_model_path(TASK, VERSION)
print(model_path)
使用“sapiens”模型函数定义姿势函数
def get_pose(image, pose_estimator, input_shape(3, 1024, 768), devicecuda):# Preprocess the imageimg preprocess_image(image, input_shape)# Run the modelwith torch.no_grad():heatmap pose_estimator(img.to(device))# Post-process the outputkeypoints, keypoint_scores udp_decode(heatmap[0].cpu().float().numpy(), input_shape[1:], (input_shape[1] // 4, input_shape[2] // 4))# Scale keypoints to original image sizescale_x image.width / input_shape[2]scale_y image.height / input_shape[1]keypoints[:, 0] * scale_xkeypoints[:, 1] * scale_y# Visualize the keypoints on the original imagepose_image visualize_keypoints(image, keypoints, keypoint_scores)return pose_imagedef preprocess_image(image, input_shape):# Resize and normalize the imageimg image.resize((input_shape[2], input_shape[1]))img np.array(img).transpose(2, 0, 1)img torch.from_numpy(img).float()img img[[2, 1, 0], ...] # RGB to BGRmean torch.tensor([123.675, 116.28, 103.53]).view(3, 1, 1)std torch.tensor([58.395, 57.12, 57.375]).view(3, 1, 1)img (img - mean) / stdreturn img.unsqueeze(0)def udp_decode(heatmap, img_size, heatmap_size):# This is a simplified version. You might need to implement the full UDP decode logich, w heatmap_sizekeypoints np.zeros((heatmap.shape[0], 2))keypoint_scores np.zeros(heatmap.shape[0])for i in range(heatmap.shape[0]):hm heatmap[i]idx np.unravel_index(np.argmax(hm), hm.shape)keypoints[i] [idx[1] * img_size[1] / w, idx[0] * img_size[0] / h]keypoint_scores[i] hm[idx]return keypoints, keypoint_scoresdef visualize_keypoints(image, keypoints, keypoint_scores, threshold0.3):draw ImageDraw.Draw(image)for (x, y), score in zip(keypoints, keypoint_scores):if score threshold:draw.ellipse([(x-2, y-2), (x2, y2)], fillred, outlinered)return image
加载输入图像
from utils.vis_utils import resize_image
pil_image Image.open(path/to/input/image)if pil_image.mode RGBA:pil_image pil_image.convert(RGB)resized_pil_image resize_image(pil_image, (640, 480))
resized_pil_image 输出
from PIL import Image, ImageDrawoutput_pose get_pose(resized_pil_image, model) 3、身体部位分割——了解人体形状
在此任务中模型对图像中的每个像素进行分类将其分解为手臂、腿或脸等身体部位。例如如果你上传一张照片模型可以将你的脸与头发分开将你的手与手臂分开。这有助于虚拟试穿系统或动画角色等任务。
Meta 的 Sapiens 模型使用大量词汇表28 个身体部位来提供详细的结果。它不仅限于手臂和腿还可以区分上下嘴唇、牙齿甚至手指。
架构
输入图像I ∈ R^H×W×3类似于姿势估计。步骤 1编码器-解码器架构——身体部位分割模型遵循与姿势估计相同的编码器-解码器设置。编码器从输入图像中提取特征解码器将这些特征转换为逐像素预测。步骤 2像素分类 — 该模型将图像的每个像素分类为 C 个身体部位类别之一例如头部、手臂、躯干等。例如在标准分割中 C 20但 Meta 将其扩展为 C 28并提供了更详细的词汇包括上/下嘴唇、牙齿和舌头等区别。步骤 3损失函数加权交叉熵 — 该模型使用加权交叉熵损失进行微调将预测的身体部位类别 p̂ 与地面真相 p 进行比较。 L_seg WeightedCE(p, p̂)步骤 4扩展词汇表和分辨率 — Sapiens 模型使用高分辨率图像4K 分辨率并手动注释了超过 100K 张带有这些详细身体部位标签的图像。与之前的模型相比分割词汇量要大得多使其对人体部位有了更细致的了解。
注意尽管 Meta Sapiens 在身体部位分割方面取得了进展但它仍然没有达到与 SAM 或 SAM2 等基于掩模的分割模型相同的精度水平。这些模型提供了更准确、更详细的掩模特别是对于细粒度的对象边界。
3.1 代码实现
加载分割权重并按照以下步骤操作
def get_model_path(task, version):try:model_path SAPIENS_LITE_MODELS_PATH[task][version]if not os.path.exists(model_path):print(fWarning: The model file does not exist at {model_path})return model_pathexcept KeyError as e:print(fError: Invalid task or version. {e})return None# Example usage
TASK seg
VERSION sapiens_0.3bmodel_path get_model_path(TASK, VERSION)
print(model_path)
从“sapiens”模型实现分割函数
def segment(image):input_tensor transform_fn(image).unsqueeze(0).to(cuda)preds run_model(input_tensor, heightimage.height, widthimage.width)mask preds.squeeze(0).cpu().numpy()mask_image Image.fromarray(mask.astype(uint8))blended_image visualize_mask_with_overlay(image, mask_image, LABELS_TO_IDS, alpha0.5)return blended_image
加载输入图像
pil_image Image.open(sapiens2.jpg)if pil_image.mode RGBA:pil_image pil_image.convert(RGB)resized_pil_image resize_image(pil_image, (640, 480))
resized_pil_image 元分割的输出结果并不令人满意它没有清晰地显示人体分割相反Meta 的 SAM[分割任何模型] 可以更好地分割图像。 4、深度估计——有多远
深度估计有助于模型了解图像不同部分的距离。这就像让模型能够分辨照片中哪些东西近哪些东西远。例如在一个人站在汽车旁边的照片中模型可以估计这个人离汽车有多远这对于增强现实等任务很重要。
架构
输入图像 I ∈ R^H×W×3。步骤 1编码器-解码器架构——与身体部位分割类似编码器从图像中提取特征解码器预测每个像素的深度。步骤 2单通道深度图——深度估计的关键区别在于输出通道设置为 1从而生成深度图。此深度图 d̂ ∈ R^H×W预测图像中每个点与相机的距离。步骤 3损失函数回归——深度估计任务被视为回归问题。该模型将其预测的深度值 (d̂) 与地面实况 (d) 进行比较并使用回归损失最小化差异 L_depth ||d − d̂||1步骤 4在合成数据上进行训练——为了改进其深度预测Meta Sapiens 使用合成人体数据包括来自 RenderPeople 的 600 个高分辨率人体 3D 扫描。这使得模型即使在困难的情况下也能生成详细而逼真的深度估计。
4.1 代码实现
加载深度权重
TASK depth
VERSION sapiens_0.3bmodel_path get_model_path(TASK, VERSION)
print(model_path)
使用“sapiens”模型编写深度函数
def get_depth(image, depth_model, input_shape(3, 1024, 768), devicecuda):# Preprocess the imageimg preprocess_image(image, input_shape)# Run the modelwith torch.no_grad():result depth_model(img.to(device))# Post-process the outputdepth_map post_process_depth(result, (image.shape[0], image.shape[1]))# Visualize the depth mapdepth_image visualize_depth(depth_map)return depth_image, depth_mapdef preprocess_image(image, input_shape):img cv2.resize(image, (input_shape[2], input_shape[1]), interpolationcv2.INTER_LINEAR).transpose(2, 0, 1)img torch.from_numpy(img)img img[[2, 1, 0], ...].float()mean torch.tensor([123.5, 116.5, 103.5]).view(-1, 1, 1)std torch.tensor([58.5, 57.0, 57.5]).view(-1, 1, 1)img (img - mean) / stdreturn img.unsqueeze(0)def post_process_depth(result, original_shape):# Check the dimensionality of the resultif result.dim() 3:result result.unsqueeze(0)elif result.dim() 4:passelse:raise ValueError(fUnexpected result dimension: {result.dim()})# Ensure were interpolating to the correct dimensionsseg_logits F.interpolate(result, sizeoriginal_shape, modebilinear, align_cornersFalse).squeeze(0)depth_map seg_logits.data.float().cpu().numpy()# If depth_map has an extra dimension, squeeze itif depth_map.ndim 3 and depth_map.shape[0] 1:depth_map depth_map.squeeze(0)return depth_mapdef visualize_depth(depth_map):# Normalize the depth mapmin_val, max_val np.nanmin(depth_map), np.nanmax(depth_map)depth_normalized 1 - ((depth_map - min_val) / (max_val - min_val))# Convert to uint8depth_normalized (depth_normalized * 255).astype(np.uint8)# Apply colormapdepth_colored cv2.applyColorMap(depth_normalized, cv2.COLORMAP_INFERNO)return depth_colored# You can add the surface normal calculation if needed
def calculate_surface_normal(depth_map):kernel_size 7grad_x cv2.Sobel(depth_map.astype(np.float32), cv2.CV_32F, 1, 0, ksizekernel_size)grad_y cv2.Sobel(depth_map.astype(np.float32), cv2.CV_32F, 0, 1, ksizekernel_size)z np.full(grad_x.shape, -1)normals np.dstack((-grad_x, -grad_y, z))normals_mag np.linalg.norm(normals, axis2, keepdimsTrue)with np.errstate(divideignore, invalidignore):normals_normalized normals / (normals_mag 1e-5)normals_normalized np.nan_to_num(normals_normalized, nan-1, posinf-1, neginf-1)normal_from_depth ((normals_normalized 1) / 2 * 255).astype(np.uint8)normal_from_depth normal_from_depth[:, :, ::-1] # RGB to BGR for cv2return normal_from_depth
加载输入图像
from utils.vis_utils import resize_imagepil_image Image.open(/home/user/app/assets/image.webp)# Load and process an image
image cv2.imread(/home/user/app/assets/frame.png)
depth_image, depth_map get_depth(image, model)
输出
surface_normal calculate_surface_normal(depth_map)
cv2.imwrite(output_surface_normal.jpg, surface_normal)
# Save the results
output_im cv2.imwrite(output_depth_image2.jpg, depth_image) 5、表面法线估计——理解表面
此任务让模型找出人体的 3D 表面细节例如每个点的表面角度或方向。例如它可以理解一个人脸部的曲线或手臂和腿的角度。
架构
输入图像 I ∈ R^H×W×3。步骤 1编码器-解码器架构——与前面的任务一样法线估计模型使用编码器-解码器框架。编码器从图像中提取特征解码器针对法线预测进行调整。步骤 2表面法线的三通道输出——对于法线估计解码器输出通道设置为 3对应于法线矢量的 xyz 分量。每个像素都会获得一个 xyz 值表示该点的表面朝向的方向。步骤 3损失函数余弦相似度——该模型使用 L1 损失和余弦相似度的组合来比较预测的法线向量 (n̂) 与地面真实法线 (n)。损失计算如下 L_normal ||n − n̂||1 (1 − n · n̂)步骤 4从合成数据进行监督——与深度估计一样法线估计依赖于合成人体数据进行监督。这使得模型能够准确预测表面方向即使在弯曲的身体部位或极端姿势等复杂情况下也是如此。
5.1 代码实现
加载法线权重
TASK normal
VERSION sapiens_0.3bmodel_path get_model_path(TASK, VERSION)
print(model_path)
从“智人”模型定义法线函数
import torch
import torch.nn.functional as F
import numpy as np
import cv2def get_normal(image, normal_model, input_shape(3, 1024, 768), devicecuda):# Preprocess the imageimg preprocess_image(image, input_shape)# Run the modelwith torch.no_grad():result normal_model(img.to(device))# Post-process the outputnormal_map post_process_normal(result, (image.shape[0], image.shape[1]))# Visualize the normal mapnormal_image visualize_normal(normal_map)return normal_image, normal_mapdef preprocess_image(image, input_shape):img cv2.resize(image, (input_shape[2], input_shape[1]), interpolationcv2.INTER_LINEAR).transpose(2, 0, 1)img torch.from_numpy(img)img img[[2, 1, 0], ...].float()mean torch.tensor([123.5, 116.5, 103.5]).view(-1, 1, 1)std torch.tensor([58.5, 57.0, 57.5]).view(-1, 1, 1)img (img - mean) / stdreturn img.unsqueeze(0)def post_process_normal(result, original_shape):# Check the dimensionality of the resultif result.dim() 3:result result.unsqueeze(0)elif result.dim() 4:passelse:raise ValueError(fUnexpected result dimension: {result.dim()})# Ensure were interpolating to the correct dimensionsseg_logits F.interpolate(result, sizeoriginal_shape, modebilinear, align_cornersFalse).squeeze(0)normal_map seg_logits.float().cpu().numpy().transpose(1, 2, 0) # H x W x 3return normal_mapdef visualize_normal(normal_map):normal_map_norm np.linalg.norm(normal_map, axis-1, keepdimsTrue)normal_map_normalized normal_map / (normal_map_norm 1e-5) # Add a small epsilon to avoid division by zero# Convert to 0-255 range and BGR format for visualizationnormal_map_vis ((normal_map_normalized 1) / 2 * 255).astype(np.uint8)normal_map_vis normal_map_vis[:, :, ::-1] # RGB to BGRreturn normal_map_visdef load_normal_model(checkpoint, use_torchscriptFalse):if use_torchscript:return torch.jit.load(checkpoint)else:model torch.export.load(checkpoint).module()model model.to(cuda)model torch.compile(model, modemax-autotune, fullgraphTrue)return model
输入图像
import cv2
import numpy as np# Load the model
normal_model load_normal_model(model_path, use_torchscript_torchscript)# Load the image
image cv2.imread(/home/user/app/assets/image.webp)
输出图像 6、结束语
尽管 Meta Sapiens 在理解与人类相关的任务方面表现出色但它在更复杂的场景中也面临挑战。例如当多个人站得很近拥挤或个人摆出不寻常或罕见的姿势时模型很难准确估计姿势并分割身体部位。此外严重的遮挡——当身体的某些部位被遮挡时——进一步增加了模型提供精确结果的能力。
Meta Sapiens 代表了以人为本的人工智能向前迈出的重要一步在姿势估计、分割、深度预测和表面法线估计方面提供了强大的功能。然而与许多模型一样它仍然存在局限性特别是在拥挤或高度复杂的场景中。随着人工智能的不断发展像 Sapiens 这样的模型的未来迭代有望解决这些挑战使我们更接近更准确、更可靠的以人为本的应用程序。 原文链接Meta Sapiens 人体AI - BimAnt