《Probing the 3D Awareness of Visual Foundation Models》论文解析——单图像表面重建

devtools/2024/11/18 7:33:57/

一、论文简介

        论文讨论了大规模预训练产生的视觉基础模型在处理任意图像时的强大能力,这些模型不仅能够完成训练任务,其中间表示还对其他视觉任务(如检测和分割)有用。研究者们提出了一个问题:这些模型是否能够表示物体的三维结构。他们通过一系列实验,使用特定任务的探针和零样本推理程序来分析这些模型的3D感知能力,并发现当前模型存在一些限制。这个实验旨在评估模型对图像中可见表面表示的能力,具体包括两个任务:深度估计(Monocular Depth Estimation)和表面法线估计(Surface Normal Estimation)。

二、深度估计(Monocular Depth Estimation)

        任务:预测图像中每个像素点的深度。

        数据集:使用NYUv2数据集评估场景级性能,NAVI数据集评估对象级性能。

        输入:单张RGB图像;输出:图像中每个像素点的深度

        网络结构:使用AdaBins的二进制预测结果,在模型的多层特征图基础上,构建一个类似于DPT解码器的多尺度探测器,用于密集预测。通过训练密集探针来预测每个像素点的深度。

        1.预训练模型特征提取

        对于一张待估计深度的图像,使用一个预训练的视觉模型(例如,一个视觉变换器或卷积神经网络)来提取图像的特征。这些特征通常在模型的中间层获得,以捕捉到图像的高层语义信息。

        2.深度预测网络(Dense Probe)

        设计一个密集探针(dense probe)网络,这个网络将从预训练模型中提取的特征映射到深度图。这个探针网络可以是一个简单的全连接层,或者是一个更复杂的网络结构,如多层感知机(MLP)或卷积层。使用AdaBins方法来训练这个探针网络(AdaBins是一种基于分箱的深度预测技术,它将深度范围划分为一系列离散的“bins”,并学习将图像特征映射到这些bins的概率分布),度量预测深度和真实深度之间的差距。

        3. 损失函数和优化

        AdaBins方法使用特定的损失函数来训练网络,这个损失函数同时考虑了深度值的回归和分类任务;使用AdamW优化器进行训练,这是一种带有权重衰减的随机梯度下降变体,有助于防止过拟合并提高训练稳定性;采用线性预热和余弦衰减学习率调度器进行学习率调度,这意味着在训练初期逐步增加学习率,然后在训练后期逐渐减小学习率,以促进模型收敛。

        4.深度图生成

        对于输入图像中的每个像素,探针网络预测一个深度值或一个深度bins的概率分布。并根据预测的概率分布,为每个像素选择最有可能的深度值,或者通过某种方式(如取期望值)从概率分布中得到一个单一的深度估计值。

        5.评估方法

        使用均方根预测误差(RMSE)和不同阈值下的召回率来评估深度估计的准确性,将预测的深度图与真实深度图(第二列)进行比较,以验证模型的性能。

三、表面法线估计(Surface Normal Estimation)

        任务:预测每个像素点的表面法线方向。

        数据集:NYUv2数据集:该数据集提供了与表面法线相关的注释,用于评估室内场景的表面法线估计性能。

        NAVI数据集:该数据集包含了对象实例在多种场景和方向中的表面法线注释,用于评估对象级别的表面法线估计性能。

        输入:单张RGB图像;输出:图像中每个像素点表面法线方向

        1.同深度估计进行预训练模型特征提取

        2.表面法线预测网络(Surface Normal Prediction Network)

        设计一个网络结构,将从预训练模型中提取的特征映射到表面法线的预测。这个网络可以是一个简单的全连接层,或者是一个更复杂的网络结构,如多层感知机(MLP)或卷积层。使用Bae等人提出的不确定性感知的角度损失函数来训练网络,以预测法线的方向。

        3.表面法线图生成

        对于输入图像中的每个像素,网络预测一个表面法线的方向向量。并将预测的法线向量归一化,以确保它们具有单位长度。

        4.评估方法

        使用均方根角度预测误差(RMSE)和不同角度阈值下的召回率来评估表面法线估计的准确性。将预测的表面法线图与真实表面法线图(如果有的话)进行比较,以验证模型的性能。

四、相关代码解析

        1.深度估计

        深度估计是一个复杂的计算机视觉任务,通常涉及到机器学习或深度学习技术。以下是一个简单的示例,使用Python和OpenCV库来从单个RGB图像中估计深度。

        

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms
from PIL import Image# 定义一个自定义的数据集
class DepthDataset(Dataset):def __init__(self, image_paths, transform=None):self.image_paths = image_pathsself.transform = transformdef __len__(self):return len(self.image_paths)def __getitem__(self, idx):image_path = self.image_paths[idx]image = Image.open(image_path)if self.transform:image = self.transform(image)# 假设我们有一个对应的深度图,这里我们随机生成一个作为示例depth = torch.rand(1, 1, image.size[1], image.size[0])return image, depth# 定义CNN模型
class DepthCNN(nn.Module):def __init__(self):super(DepthCNN, self).__init__()self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1)self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1)self.conv3 = nn.Conv2d(32, 64, kernel_size=3, stride=2, padding=1)self.fc1 = nn.Linear(64*16*16, 1024)self.fc2 = nn.Linear(1024, 1)  # 假设深度图是单通道的def forward(self, x):x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = torch.relu(self.conv3(x))x = x.view(x.size(0), -1)  # Flatten the tensorx = torch.relu(self.fc1(x))x = self.fc2(x)return x# 实例化数据集和数据加载器
image_paths = ['path_to_your_image1.jpg', 'path_to_your_image2.jpg']  # 替换为实际图像路径
transform = transforms.Compose([transforms.ToTensor()])
dataset = DepthDataset(image_paths, transform)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)# 实例化模型
model = DepthCNN()# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练模型
for epoch in range(10):  # 迭代10个epochfor images, depths in dataloader:optimizer.zero_grad()outputs = model(images)loss = criterion(outputs, depths)loss.backward()optimizer.step()print(f'Epoch [{epoch+1}/10], Loss: {loss.item():.4f}')

        在这个示例中,我们定义了一个DepthDataset类来加载图像和对应的深度图。然后,我们定义了一个DepthCNN类来构建CNN模型。模型包含三个卷积层和两个全连接层。我们使用均方误差损失(MSELoss)作为损失函数,并使用Adam优化器来更新模型权重。

        2.表面法线估计

        表面法线分析是计算机视觉中的一个高级任务,通常涉及到从RGB图像中估计表面的法线向量。这通常需要复杂的深度学习模型,比如卷积神经网络(CNN)。以下是一个使用PyTorch框架的简化示例,展示了如何构建一个CNN模型来进行表面法线分析。

        

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms
from PIL import Image# 定义一个自定义的数据集
class NormalDataset(Dataset):def __init__(self, image_paths, transform=None):self.image_paths = image_pathsself.transform = transformdef __len__(self):return len(self.image_paths)def __getitem__(self, idx):image_path = self.image_paths[idx]image = Image.open(image_path)if self.transform:image = self.transform(image)# 假设我们有一个对应的法线图,这里我们随机生成一个作为示例# 法线图通常有三个通道,分别对应x, y, z坐标normal = torch.rand(3, image.size[1], image.size[0])return image, normal# 定义CNN模型
class NormalCNN(nn.Module):def __init__(self):super(NormalCNN, self).__init__()self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1)self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1)self.conv3 = nn.Conv2d(32, 64, kernel_size=3, stride=2, padding=1)self.fc1 = nn.Linear(64*16*16, 256)self.fc2 = nn.Linear(256, 3)  # 法线有三个分量def forward(self, x):x = torch.relu(self.conv1(x))x = torch.relu(self.conv2(x))x = torch.relu(self.conv3(x))x = x.view(x.size(0), -1)  # Flatten the tensorx = torch.relu(self.fc1(x))x = self.fc2(x)return x# 实例化数据集和数据加载器
image_paths = ['path_to_your_image1.jpg', 'path_to_your_image2.jpg']  # 替换为实际图像路径
transform = transforms.Compose([transforms.ToTensor()])
dataset = NormalDataset(image_paths, transform)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)# 实例化模型
model = NormalCNN()# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练模型
for epoch in range(10):  # 迭代10个epochfor images, normals in dataloader:optimizer.zero_grad()outputs = model(images)loss = criterion(outputs, normals)loss.backward()optimizer.step()print(f'Epoch [{epoch+1}/10], Loss: {loss.item():.4f}')

        在这个示例中,我们定义了一个NormalDataset类来加载图像和对应的法线图。然后,我们定义了一个NormalCNN类来构建CNN模型。模型包含三个卷积层和两个全连接层。我们使用均方误差损失(MSELoss)作为损失函数,并使用Adam优化器来更新模型权重。


http://www.ppmy.cn/devtools/134900.html

相关文章

Python自动检测requests所获得html文档的编码

使用chardet库自动检测requests所获得html文档的编码 使用requests和BeautifulSoup库获取某个页面带来的乱码问题 使用requests配合BeautifulSoup库,可以轻松地从网页中提取数据。但是,当网页返回的编码格式与Python默认的编码格式不一致时&#xff0c…

【HOT100第四天】除自身以外数组的乘积,矩阵置零,螺旋矩阵,旋转图像

今天感觉是边界值练习专场。。。整体难度不大但是细节还是需要多动手写一写。 238. 除自身以外的数组的乘积 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意…

【C语言】连接陷阱探秘(2):命令冲突与static修饰符

目录 一、命令冲突 1.1. 常见情况及原因 1.1.1. 符号重定义冲突 1.1.2. 不同编译单元中静态函数调用冲突 1.2. 解决办法 1.3. 示例 二、static 修饰符的陷阱与缺陷 2.1. 变量方面的陷阱 2.1.1. 静态局部变量的初始化顺序问题 2.1.2. 静态全局变量的作用域误解 2.2. …

【AI图像生成网站Golang】项目架构

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 四、项目架构 本项目的后端基于Golang和Gin框架开发,主要包括的模块有: backend/ ├── …

第8章:TDengine 开发、测试、生产三大环境中数据库创建指南

TDengine 开发、测试、生产三大环境中数据库创建指南 TDengine3.0社区版在开发、测试、以及生产三大环境中数据库创建SQL语句以及相应参数的说明文档。 一、概述 TDengine3.0社区版是一款开源、高性能、云原生的时序数据库,支持SQL语法,并针对时序数据进行了优化。在开发、…

QT适配最新版Android SDK

从AndroidStudio的SDK管理下载最新版SDK 从https://www.androiddevtools.cn/下载国内安卓SKDTools 这里下载SKDTools后不需要使用SDK Manager.exe下载SDK(SDK Manager.exe下载的SDK都是旧版,没法支持新版本),直接使用从AndroidS…

web-02

回顾 full stack web前端 结构(html) 样式(css) 动作/交互(js) html html常用标签 扩展标签 列表 ul/ol u–un – 无序的 o-order --有顺序的 <ol> 你最喜欢的游戏是什么&#xff1f;<li>bar sleep</li><li>who knows</li> </ol>布…

Apache Doris:深度优化与最佳实践

引言 在前两篇文章中&#xff0c;我们已经介绍了 Apache Doris 的基本概念、安装配置、基础操作以及一些高级特性。本文将进一步深入探讨 Doris 的性能优化技巧、高级查询优化、数据建模最佳实践以及常见问题的解决方法。通过本文&#xff0c;读者将能够更好地理解和应用 Dori…