DepthAnything v2 教程:如何使用 Python 将 2D 图像转换为 3D 模型 学习如何使用 AI 和 Python 将任意图像转换为精细的 3D 模型。无需任何专用硬件,只需按照本

简介

想象一下,将您收藏的任何照片转换成一个沉浸式 3D 模型,您可以旋转、探索甚至 3D 打印它——所有这些都不需要专门的设备。

直到最近,创建 3D 模型还需要昂贵的硬件设置、多个摄像机角度或艰苦的手动建模。

对于个人和小团队来说,进入门槛太高了。

现在情况已经大不相同了,我很高兴能分享一个开源解决方案。

得益于人工智能深度估计领域的最新突破,特别是DepthAnything v2等模型,我们现在可以从 2D 图像中提取令人惊讶的精确深度信息。

此功能大大降低了 3D 内容创建的门槛,任何具有基本 Python 知识的人都可以使用它,而无需昂贵的设备和专门的培训。

在我的咨询工作中,我看到这项技能直接影响业务成果,例如,当电子商务客户实施从标准目录照片创建的交互式 3D 产品视图时,产品页面上花费的时间增加了 27%,退货率降低了 23%。

该技术有效地弥合了客户在线看到的内容和收到的内容之间的差距,创造了更加透明的购物体验并推动了更多的转化。

但如果结合适当的处理技术,这将为研究人员、内容创作者、开发人员和爱好者开辟许多可能性。

在这个综合教程中,我分享了完整的流程,仅使用 Python 和免费工具将任何 2D 图像转换为详细的 3D 点云和网格。

不需要专门的硬件——只需要您的计算机和一些智能代码。

🛠️注:我将使用我那台使用了两年的 Windows 电脑。它配备了 GeForce 3090 GT 显卡(24 GB 显存)、Ryzen 9 CPU 和 32 GB 内存。文章末尾分享了所有文件,包括代码 (.py)、数据集 (.ply、.png) 和速查表 (.pdf)。

推荐文章

主要贡献

🔍单图像 3D 重建——使用最先进的深度估计和点云处理将任何 2D 图像转换为完全可操作的 3D 模型。
🛠️双重投影方法——掌握针孔和正交投影技术,以处理从自然场景到建筑照片的各种图像类型。
🧠人工智能驱动的工作流程——利用 DepthAnything v2 的转换器架构,无需专门的硬件即可从普通照片中提取高质量的深度信息。
⚙️生产就绪管道- 遵循从深度估计到网格生成的完整工作流程,并根据实际经验优化参数。
🚀实际应用——应用这些技术为 AR/VR、3D 打印、电子商务、文化保护等领域创建内容。
让我们步入正轨!

步骤 1:设置环境

让我们首先安装必要的库并配置我们的开发环境。

在这里插入图片描述
这一步至关重要——正确配置的环境可确保顺利执行并避免出现令人沮丧的兼容性问题。

对于这个项目,我们需要几个关键库:用于深度学习模型的 PyTorch、用于点云和网格处理的 Open3D 以及用于图像处理和可视化的标准库:

# For CUDA 11.7 (adjust version based on your NVIDIA driver)
pip install torch==2.0.1 torchvision==0.15.2 --index-url https://download.pytorch.org/whl/cu117

# For CPU only (if you don't have a CUDA-compatible GPU)
# pip install torch==2.0.1 torchvision==0.15.2

# For macOS with Apple Silicon (M1/M2)
# pip install torch==2.0.1 torchvision==0.15.2

# Install Hugging Face Transformers for DepthAnything model
pip install transformers

# Install Open3D for point cloud and mesh processing
pip install open3d

# Install other required packages
pip install opencv-python
pip install matplotlib
pip install numpy

如果您在新环境中工作,则需要安装这些依赖项。然后,让我们将它们导入到我们的 Python 脚本中:

import os
import random
from pathlib import Path

import numpy as np
import matplotlib.pyplot as plt
import cv2

import open3d as o3d

import torch
from transformers import AutoImageProcessor, AutoModelForDepthEstimation

PyTorch 将满足我们的深度学习需求,而 Open3D 则提供用于 3D 数据处理的专门功能。

OpenCV 提供图像处理功能,Matplotlib 则有助于可视化。我们还将使用 NumPy 进行高效的数值计算。

运行此设置代码后,您的 Python 环境将拥有完整 3D 转换管道所需的一切。

🦥极客提示: 设置 PyTorch 时,请务必将 CUDA 版本与 GPU 驱动程序匹配。例如,如果您已安装 CUDA 11.7,则应专门安装针对 CUDA 11.7 的 PyTorch 版本。不匹配可能会导致难以理解的错误或性能问题,尤其是在模型推理过程中。此外,Open3D 偶尔会与最新的 Python 版本存在兼容性问题,因此我建议使用 Python 3.8 或 3.9 以获得最稳定的体验。如果您使用的是 Apple Silicon (M1/M2),请安装 PyTorch MPS 版本,以便在不使用 CUDA 的情况下实现 GPU 加速。

第 2 步:准备图像数据

你可以相信我的话:

3D 重建的成功始于高质量的输入数据。

让我们探索如何准备和预处理图像以获得最佳效果。

在深度估计方面,并非所有图像都是相同的。

前景背景分离清晰、光照充足且纹理细节丰富的图像往往能产生最佳效果。相反,具有反射表面、透明物体或非常均匀纹理(例如空白墙壁)的图像,即使是最好的深度估计模型也会面临挑战。

在此步骤中,我们将准备多种样本图像来演示不同场景类型的处理过程。

这是我的图像集,非常多样化:

在这里插入图片描述
正如您所见,我们有人工智能生成的图像(如机器人和蘑菇)以及更经典的基于相机的图像和正射投影或空间“正射图像”。

这是一个有趣的测试台!

现在,这是我用来处理加载和组织图像的一段代码:

# Read in sample images
folder_path = Path("../DATA/")

num_samples = 13
selection = random.sample(os.listdir(folder_path), num_samples)

selected_images = []
for i in range(num_samples):    
    pathi = str(folder_path / selection[i])
    selected_image = cv2.imread(pathi)
    selected_image = cv2.cvtColor(selected_image, cv2.COLOR_BGR2RGB)
    selected_images.append(selected_image)

exporting = True

此代码从您指定的文件夹中随机选择图像,将其转换为适当的颜色格式(RGB),然后存储以进行处理。

我建议从 5-10 张不同的图像开始,以了解不同场景的表现。

为了获得最佳效果,请考虑以下图像选择指南:

选择光线充足、运动模糊最少的场景
包含具有清晰深度提示的图像(不同距离的物体)
避免使用以反射或透明表面为主的图像
包含室内和室外场景

根据我的专业经验,我发现物体或场景的半特写镜头(1-5 米远)通常比大特写镜头或非常远的风景效果更好。这是因为中距离图像在细节和背景之间取得了良好的平衡,而深度估计网络可以利用这一点。如果您的源图像分辨率极高(4K 以上),则先将其下采样至 1080p 或 720p 可以加快处理速度,而不会显著影响输出质量。

现在我们准备进入第三步:DepthAnything V2

步骤 3:理解和加载 Depth Anything v2

我们现在已经达到了系统的核心:DepthAnything v2,一个尖端的单目深度估计模型。

但是,是什么让这个模型如此特别,它实际上是如何运作的?

传统的深度估计需要专门的硬件——立体摄像机、激光雷达或结构光传感器。

单目深度估计通过从单个二维图像中提取深度信息从根本上改变了这种范式。

这是可能的,因为图像包含人类本能理解的隐式深度线索:相对物体大小、遮挡(物体阻挡其他物体)、纹理梯度、大气效果等等。

DepthAnything v2 由香港大学和 TikTok 的研究人员共同开发,代表了该领域的重大进展。与以往通常在特定数据集上训练且难以泛化的模型不同,DepthAnything v2 旨在实现跨多种场景的稳健零样本性能。

在这里插入图片描述

它利用在海量多样化数据集上进行预训练的视觉转换器 (ViT) 架构,使其能够理解前所未有的场景范围内的深度关系。

让我们从 Hugging Face 的模型库中加载模型:

checkpoints = [
    "Intel/zoedepth-nyu-kitti",
    "LiheYoung/depth-anything-large-hf",
    "jingheya/lotus-depth-g-v1-0",   
    "tencent/DepthCrafter"
    ]

checkpoint = checkpoints[1]

# take care of the necessary image transformations such as resizing and normalization
processor = AutoImageProcessor.from_pretrained(checkpoints[1])
model = AutoModelForDepthEstimation.from_pretrained(checkpoints[1]).to("cuda")

此代码处理几个基本任务:

从可用的深度估计模型中进行选择
从 Hugging Face 加载 DepthAnything 大型模型变体
将模型移至 GPU 以实现更快的推理
准备处理输入预处理的图像处理器
🦥极客提示: 模型选择至关重要——为了获得最佳质量,我们使用 DepthAnything v2 的“大型”版本(约 980MB)。虽然有更多小型版本可用(例如约 440MB 的“基础”版本),但大型模型在复杂场景中捕捉到的细节明显更多。对于需要在速度和质量之间取得平衡的生产系统,请考虑使用基础版本或类似英特尔 ZoeDepth 的替代方案,后者可以在没有 GPU 可用的情况下在 CPU 上高效运行。

CUDA 传输(to(“cuda”))对于性能至关重要——如果没有 GPU 加速,推理速度可能会慢 10-20 倍。

在 RTX 3070 等现代 GPU 上,您可以预期以 512x512 分辨率处理每张图像需要 100-300 毫秒,而在 CPU 上则需要几秒钟。

如果您在没有兼容 GPU 的系统上运行,则可以用“cpu”替换“cuda”,但要做好更长的处理时间的准备。

步骤4:处理图像以进行深度估计

加载模型后,我们现在可以处理图像以生成深度图 - 灰度图像,其中像素强度代表与相机的距离。

这就是奇迹开始发生的地方。

深度图是有趣的视觉表现:按照惯例,深度图中较亮的区域代表距离相机较远的点,而较暗的区域代表较近的点(尽管有时根据模型的不同,情况会相反)。

在这里插入图片描述
这种简单的表示在 2D 图像格式中编码了大量 3D 信息。

让我们通过 DepthAnything v2 处理我们的示例图像:

depth_samples = []
for i in range(num_samples):
    depth_input = processor(images=selected_images[i], return_tensors="pt").to("cuda")

    # Infer model
    with torch.no_grad():
        inference_outputs = model(**depth_input)
        output_depth = inference_outputs.predicted_depth
    
    output_depth = output_depth.squeeze().cpu().numpy()
    
    depth_samples.append([selected_images[i], output_depth])

此代码执行几个关键操作:

它使用处理器为深度估计模型准备每幅图像
为了提高效率,它在运行模型推理时禁用梯度跟踪
它提取预测的深度并将其转换为 numpy 数组
它将原始图像和相应的深度图存储在一起
在幕后,DepthAnything v2 正在完成一项令人印象深刻的壮举。

它的变换器架构以多种尺度分析图像,建立对场景结构的分层理解。

在这里插入图片描述
注意力机制帮助模型关联图像的远处部分,捕捉全局背景,同时保留局部细节。

在这里插入图片描述
与早期基于 CNN 的方法相比,这是一个显著的进步,因为早期的方法往往难以理解全局场景。

目深度估计的一个有趣特性是,它产生的是相对深度值,而非绝对深度值。模型确定的是图像中哪些部分彼此之间距离更近或更远,而不是以米为单位的精确距离。这就是 为什么你有时会看到深度图,它们在结构上看起来正确,但尺度却任意。这一特性实际上为我们后续步骤提供了灵活性——我们可以调整尺度来实现不同的 3D 效果,而不会影响整体结构。

步骤5:可视化深度图

在进行 3D 转换之前,可视化和理解我们生成的深度图至关重要。

这个可视化步骤帮助我们评估深度估计的质量并预测 3D 重建中的潜在问题。

让我们并排可视化原始图像及其对应的深度图:

plt.rcParams['figure.dpi'] = 300

for i in range(num_samples):
    fig, axs = plt.subplots(2, 1)
    
    axs[0].imshow(depth_samples[i][0])
    axs[0].set_title('Depth Estimation')
    axs[1].imshow(depth_samples[i][1])
    
    plt.show()

此代码为每个图像创建一个包含两个子图的图形:顶部是原始 RGB 图像,下方是相应的深度图。

在这里插入图片描述
仔细检查这些可视化效果可以提供有价值的见解。

在良好的深度图中,您应该观察到:

前景和背景元素之间的明确分离
连续表面上的平滑深度梯度
保留重要对象边界
一致的相对深度(较近的物体总是比较远的物体更暗)
令你惊讶的是,即使对于复杂的场景,这些深度图也非常准确。

请添加图片描述
早期模型通常会产生模糊或不一致的深度图,而 DepthAnything v2 通常可以保留复杂的结构,并能更好地处理诸如薄物体或复杂遮挡等具有挑战性的场景。

视化代码使用 plt.rcParams[‘figure.dpi’] = 300高 DPI 为 Matplotlib 图形设置。这对于详细的深度图分析至关重要——在较低的 DPI 下,深度图中的细微渐变可能会由于像素合并而丢失。评估深度图时,请特别注意对象边界和精细结构,因为这些区域是大多数模型难以处理的区域。此外,深度图有时会在高光非常亮或阴影非常暗的区域出现伪影,因为这些区域为模型提供的纹理线索较少。

一旦我们对深度图感到满意,我们就会保存它们以供进一步处理:

for i in range(num_samples):
    depth_image = depth_samples[i][1]
    color_image = depth_samples[i][0]
    width, height = depth_image.shape

    depth_image = (depth_image * 255 / np.max(depth_image)).astype('uint8')
    color_image = cv2.resize(color_image, (height, width))
    
    cv2.imwrite('../RESULTS/'+str(i)+'.png', cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB))
    cv2.imwrite('../RESULTS/'+str(i)+'_depth.png', depth_image)

此代码将原始 RGB 图像和深度图保存到您指定的输出目录中。深度图被标准化到 0-255 范围内,以保存为标准灰度图像。

在专业处理深度图时,我经常会使用双边滤波等额外的后处理来减少噪点并保留边缘。这对于包含较大均匀区域的场景尤其有用,因为深度预测可能会产生噪点。然而,DepthAnything v2 通常可以生成足够清晰的深度图,因此对于大多数应用来说,此步骤并非必需。如果您发现深度图中存在明显的噪点,请考虑 cv2.bilateralFilter(depth_image, 5, 75, 75) 在保存之前添加。

步骤6:使用针孔方法生成3D点云

现在到了激动人心的部分——将我们的 2D 深度图转换为 3D 点云。我们首先会用到针孔相机模型,这是一个将 3D 点投影到 2D 图像平面(反之亦然)的数学框架。

针孔相机模型是计算机视觉的基础概念之一。它模拟了来自三维世界的光线如何穿过小孔径(针孔)并投射到图像平面上,从而形成倒置的图像。

在这里插入图片描述
这个简单的模型非常接近传统相机的工作原理,并提供了在二维图像坐标和三维世界坐标之间转换的数学框架。

让我们实现基于针孔的3D重建。首先,让我们准备3D的深度图和图像:

i = -4

depth_image = depth_samples[i][1]
color_image = depth_samples[i][0]
width, height = depth_image.shape

depth_image = (depth_image * 255 / np.max(depth_image)).astype('uint8')
color_image = cv2.resize(color_image, (height, width))


此代码准备将我们的深度图和彩色图像转换为点云,确保它们具有兼容的尺寸并且适合 Open3D 的正确格式。

接下来,我们将创建一个 RGBD 图像(颜色和深度的组合)并设置我们的针孔相机模型:

depth_o3d = o3d.geometry.Image(depth_image)
image_o3d = o3d.geometry.Image(color_image)
rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(image_o3d, depth_o3d, convert_rgb_to_intensity=False)

camera_intrinsic = o3d.camera.PinholeCameraIntrinsic()

# If focal length is too small: Objects appear "stretched" in depth
# If focal length is too large: Objects appear "compressed" in depth

# to create metrically accurate 3D reconstructions that match real-world scale:
fx = fy = width * 0.8  # A good approximation for a standard lens
cx, cy = width/2, height/2  # Center of the image

camera_intrinsic.set_intrinsics(width, height, fx, fy, cx, cy)


这里的关键参数是相机的固有特性,尤其是焦距。焦距决定了深度维度在最终点云中呈现的“拉伸”或“压缩”程度。

我使用启发式方法,将焦距设置为与图像宽度成比例,这种方法适用于大多数标准图像。

相机固有参数对于精确的 3D 重建至关重要。理想情况下,您应该使用拍摄照片的相机的实际参数,但这些参数对于随机图像来说很少可用。对于 fx = fy = width * 0.8 使用智能手机或单反相机以正常焦距(而非超广角或远摄)拍摄的标准照片,我们的近似值通常能产生良好的效果。乘数 (0.8) 有效地控制了“深度压缩”——较低的值会产生更拉伸的深度,而较高的值会产生更压缩的深度。

主点(cx, cy)代表图像的光学中心,我们将其设置为图像中心。实际应用中,真实相机与几何中心会略有偏移,但就我们的目的而言,这种近似值效果良好。

如果您的点云出现倾斜或歪斜,您可能需要调整这些参数。

现在,让我们生成并可视化我们的点云:

pcd_raw = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, camera_intrinsic)

o3d.visualization.draw_geometries([pcd_raw])

请添加图片描述

步骤7:增强点云

原始点云通常包含噪声和异常值,这些会降低最终 3D 模型的质量。在这一步中,我们将应用关键的后处理技术来优化点云。

让我们从统计异常值去除开始,它根据与邻近点的统计距离来识别和消除可能的噪声点:

# outliers removal
cl, ind = pcd_raw.remove_statistical_outlier(nb_neighbors=20, std_ratio=1.0)
pcd = pcd_raw.select_by_index(ind)


此代码根据与 20 个最近邻点的距离,移除统计异常点。与邻点距离显著大于平均值(由标准差控制)的点将被视为异常值并被移除。

接下来,我们将估算点云中每个点的表面法线。法线是垂直于每个点的表面向量,它们对于许多后续操作至关重要,尤其是网格生成。

在这里插入图片描述
此代码计算每个点的法线并确保它们都指向一致的方向:

# estimate normals
pcd.estimate_normals()
pcd.orient_normals_to_align_with_direction()
o3d.visualization.draw_geometries([pcd])

法线方向至关重要——如果法线指向不一致的方向,我们的网格生成可能会创建内外表面或完全失败。

统计异常值移除的参数需要根据您的数据仔细调整。该 nb_neighbors=20 设置会检查最近的 20 个点,以确定某个点是否为异常值。较小的值(例如 10)可以移除更多点,但可能会在稀疏区域剔除有效数据;而较大的值(例如 30)则更为保守,但可能会遗漏一些异常值。该std_ratio=1.0 参数控制异常值分类的阈值——与平均值距离大于 1.0 个标准差的点被视为异常值。将此设置增加到 2.0 可以保留更多点(包括潜在的噪声点);而将此设置降低到 0.5 可以更积极地移除异常值。

对于法线估计,Open3D 默认使用局部平面拟合方法。法线方向最初是任意的,因此我们调用orient_normals_to_align_with_direction()after 函数。此函数尝试使所有法线始终从估计的对象中心向外指向。正确的方向对于下一步成功生成网格至关重要。结果如下:

请添加图片描述
在专业处理点云数据时,我发现操作顺序非常重要。务必在法线估计之前执行异常值移除——否则,异常值可能会严重扭曲附近合法点的法线计算。此外,如果您的点云非常庞大(数百万个点),请考虑 pcd.voxel_down_sample(voxel_size=0.01) 在法线估计之前对其进行下采样,以在不显著影响质量的情况下提高性能。

现在,让我们讨论一个小技巧:生成正交 3D 点云。

步骤8:使用正交投影创建点云

虽然针孔方法对于传统场景很有效,但使用正交投影的替代方法有时可以产生更好的效果,特别是对于保留平行线很重要的建筑或技术主题。

与透视(针孔)投影不同,物体距离越远,投影看起来就越小。正交投影则不同,无论距离远近,其比例都保持不变。这在技术插图、建筑模型和工程应用方面尤其有用。

在这里插入图片描述
让我们实现一个纯正交投影函数:

def depth_to_pointcloud_orthographic(depth_map, image, scale_factor=255):

    height, width = depth_map.shape

    # Create a grid of pixel coordinates
    y, x = np.meshgrid(np.arange(height), np.arange(width), indexing='ij')

    # Scale the depth values
    z = (depth_map / scale_factor) * height/2

    # Create 3D points (x and y are pixel coordinates, z is from the depth map)
    points = np.stack((x, y, z), axis=-1).reshape(-1, 3)

    # Filter out points with zero depth
    mask = points[:, 2] != 0
    points = points[mask]

    # Create Open3D PointCloud object
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(points)
    o3d.visualization.draw_geometries([pcd])
    
    # Add colors to the point cloud
    colors = image.reshape(-1, 3)[mask] / 255.0  # Normalize color values to [0, 1]
    pcd.colors = o3d.utility.Vector3dVector(colors)
    
    _, ind = pcd.remove_statistical_outlier(nb_neighbors=15, std_ratio=1)
    inlier_cloud = pcd.select_by_index(ind)

    return inlier_cloud, z, height, width 

该正交投影函数以深度图和彩色图像作为输入,并生成 3D 点云。

与针孔投影的主要区别在于,它将深度值视为直接高度(z 坐标)值,而不是距离相机的距离。x 和 y 坐标直接来自像素坐标。

现在,让我们使用此函数从我们的一张深度图中生成一个替代点云:

# Code for generating a point cloud with orthographic projection will go here

这段代码加载已保存的深度图及其对应的彩色图像,然后使用我们的正交投影函数创建点云。结果使用 Open3D 进行可视化。

请添加图片描述
您可以在我们的机器人样本上看到它如何在没有那么多浮点的情况下提供“更好”的 3D 重建。

数 scale_factor=255 至关重要——它控制深度值如何转换为 z 坐标。由于我们在保存时将深度图标准化为 0-255 的范围,因此我们使用 255 作为分母来获取 0-1 范围内的值。然后,我们乘以 ,height/2将深度缩放到相对于其他维度的合理范围内。调整此缩放因子直接控制最终模型的“平坦度”或“深度”——较小的值会创建更平坦的模型,而较大的值会夸大深度。对于艺术应用,您可能需要尝试不同的缩放因子以达到所需的美学效果。

统计异常值去除参数(nb_neighbors=15, std_ratio=1)与我们的针孔方法略有不同,以解释通常在正交投影点云中发现的不同点分布模式。

步骤9:从点云创建3D网格

点云能够出色地表示三维结构,但在许多应用中,我们需要一个由面连接点的连续表面网格。这时,泊松曲面重建就派上用场了。

泊松曲面重建是一种先进的算法,它将具有定向法线的点云转换为水密的三角网格。

请添加图片描述

它的工作原理是求解泊松方程来找到梯度与输入法线场最匹配的指示函数,然后从该函数中提取等值面。

在这里插入图片描述
让我们在处理过的点云上实现泊松重建:

point_cloud.estimate_normals()
point_cloud.orient_normals_to_align_with_direction()

print('run Poisson surface reconstruction')
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(point_cloud, depth=9)
o3d.visualization.draw_geometries([mesh])

此代码采用具有法线的点云并使用泊松重建来创建三角形网格。

请添加图片描述
该depth参数控制重建的分辨率——更高的值可以创建更详细的网格,但需要更多的计算时间和内存。

🦥极客提示: 泊松重建深度参数(在我们的代码中设置为 9)是网格质量最关键的设置。它控制重建过程中使用的八叉树深度,直接影响细节级别。该值通常在 5 到 12 之间:

深度 5-6:非常粗略的重建,适合预览或内存有限时
深度 7–8:中等细节,适合一般用途
深度 9–10:细节丰富,可捕捉精细结构,但需要更多内存
深度 11-12:细节非常丰富,可以捕捉微小的特征,但需要大量内存和处理时间
对于大多数单幅图像重建,8-9 的深度能够提供良好的细节和性能平衡。如果您的网格出现不必要的伪影或孔洞,请尝试将深度降低到 8。如果丢失了重要的精细细节,请尝试增加到 10。

基本实现中未显示的另一个重要参数是scale,默认值为 1.1。它控制重建表面相对于输入点边界框的大小。接近 1.0 的值会产生与数据更紧密的拟合,而较大的值会创建更平滑、更延伸的表面,从而可能更好地填充小孔。

生成网格后,您可能希望保存它以便在其他软件中使用:

o3d.io.write_triangle_mesh('../RESULTS/mesh_ortho.obj', mesh, write_triangle_uvs = True)

这会将网格保存为 OBJ 格式,该格式广泛受 Blender、Maya、Unity 等 3D 软件支持。现在,您可以根据需要为网格添加纹理、制作动画或进行 3D 打印。

更进一步:高级扩展

现在您已经构建了完整的 2D 到 3D 转换管道,但还有许多令人兴奋的方法可以扩展和增强该系统。

在我的咨询工作中,我发现将这种单图像 3D 重建与其他技术相结合可以产生更强大的结果。

例如,使用同一物体的多个重建视图,然后进行对齐和合并,可以生成更完整的模型。同样,将深度信息与其他传感器数据(例如新款智能手机上的激光雷达)相结合,可以提高特定应用的准确性。

以下是一些需要探索的高级方向:

模型基准测试和优化
深度估计模型是我们整个流程的基础。虽然 DepthAnything v2 提供了出色的结果,但值得将其与其他模型进行比较,以找到最适合您特定用例的模型:

英特尔 ZoeDepth擅长室内场景,可在 CPU 上高效运行
腾讯的 DepthCrafter在复杂的户外环境中表现出色
经过 KITTI 训练的模型可能在驾驶场景和街景方面表现更佳
每个模型都有不同的优势和计算要求。请在典型的输入图像上对它们进行基准测试,以找到质量和性能的最佳平衡点。

语义分割集成
我最喜欢的扩展之一是将深度估计与语义分割相结合。这使得我能够根据场景中的物体的类别(人、车、建筑物等)进行分离,然后再将它们处理成 3D 图像。

通过这种集成,可以选择性地处理某些对象、自动去除背景或将不同的网格参数应用于不同的对象类别。

例如,我经常对前景对象使用更高细节的网格,对背景元素使用更低细节的网格,以优化性能而不牺牲感知质量。

在最近的一个项目中,我使用这种方法自动从电商照片中提取产品,并在丢弃背景的同时为每个产品创建单独的 3D 模型。这节省了数小时的手动遮罩和编辑时间。

与专业3D软件集成
我使用此流程生成的网格可以导入专业的 3D 软件进行进一步细化。我经常使用:

Blender用于艺术增强、动画和高级渲染
Unity 或 Unreal Engine,用于集成到交互式体验和游戏中
用于工程应用和精密建模的CAD 软件
学习这些平台的基础知识可以显著扩展你生成的 3D 模型的功能。我经常使用 Blender 的雕刻工具来优化自动重建可能存在局限性的区域,尤其是对于有机形状。

我还使用了 Blender 的“Remesh”修改器,在需要动画或变形的区域创建更均匀的拓扑结构。泊松重建的网格通常三角形分布不均匀,这可能会在动画过程中造成问题。

对于像 Unity 这样的游戏引擎,我总是会使用抽取 (decimation) 流程来减少网格的多边形数量,同时保持视觉质量。这种流程生成的网格可能非常密集(通常包含 10 万个以上的三角形),这对于实时应用来说过于复杂了。一般来说,游戏素材的三角形数量应减少到原始三角形数量的 10% 到 25% 左右。

数据融合与多视图增强
我们方法最大的局限性在于,我们只能重建单幅图像中可见的部分。为了解决这个问题,我开发了一套工作流程,可以整合同一主题的多个视图。

我通过流程分别处理每幅图像,然后使用点云配准技术将生成的部分重建对齐成更完整的模型。这种方法填补了空白,并创建了更完整的3D表示。

我还成功地将这种基于深度的方法与其他 3D 重建技术(如摄影测量法或 N​​eRF(神经辐射场))相结合,以实现两全其美的效果。

🦥极客笔记: 对于多视图对齐,我使用两步配准流程。首先,我使用带有 FPFH(快速点特征直方图)特征的 RANSAC 进行粗配准,使云图大致对齐。然后,我使用 ICP(迭代最近点)进行细化配准,以实现精确配准。

成功的多视图融合的关键是视图之间有足够的重叠(至少 30-40%)和一致的照明条件。

图像之间剧烈的光照变化可能会导致最终模型的颜色不一致。为了缓解这个问题,我有时会在融合之前使用直方图匹配来标准化不同视图的颜色。

对于复杂的主题,我将视图组织成图结构,其中边表示重叠的视图。这有助于确定成对配准的最佳顺序,并减少长序列中配准误差的累积。

结论

我刚刚向您介绍了完整的 2D 到 3D 转换流程,它代表了我们创建 3D 内容方式的范式转变。

曾经需要专门的设备、技术专长和大量时间投入的工作,现在只需一张图像和巧妙的算法就能完成。

让我们回顾一下我们所取得的成就:

我已经向你展示了 DepthAnything v2 等最先进的 AI 模型如何从普通照片中提取深度信息
我们实现了两种不同的方法(针孔和正交)将深度图转换为 3D 点云
您拥有必要的点云处理技术,可以将噪声数据转换为干净、可用的 3D 表示
我们使用泊松重建创建了连续表面网格,可用于广泛的应用
您探索了 AR/VR、电子商务、文化保护等行业的实际应用
这不仅仅代表着一项技术成就——它还是您创意和专业工具包中一个强大的新工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识大胖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值