MVG学习笔记(3) --从多个视角重建

本文探讨了从两幅图像重建3D场景的方法,介绍基础矩阵如何连接点对应关系,实现摄像机矩阵和3D点云的计算。重点在于解决射影模糊性和共面约束,最终通过三角测量得到3D点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从多个视角重建

  我们现在转向本次博文的议题- 从几幅图像重建场景。 最简单的情况是两个图像,我们将首先考虑。 作为一种数学抽象,我们将讨论局限于仅由点组成的“场景”。

  对于重建的许多算法,通常输入是一组点对应关系。

  因此,在两视图的情况下,我们在两个图像中考虑一组对应关系 x i ↔ x i ′ {\rm x}_i \leftrightarrow {\rm x}^\prime_i xixi。 假设存在一些相机矩阵, P \rm P P P ′ {\rm P^\prime} P 以及一组3D点 X i {\rm X}_i Xi,由这些图像上产生对应关系,满足于 P X i = x i {\rm PX}_i={\rm x}_i PXi=xi P ′ X i = x i ′ {\rm P^\prime X}_i={\rm x}^\prime_i PXi=xi

  因此,点 X i {\rm X}_i Xi投射到两个给定的数据点。 但是,摄像机(由投影矩阵 P \rm P P P ′ {\rm P^\prime} P 表示)和点 X i {\rm X}_i Xi都不是已知的。 我们的任务是确定它们。

我们的已知条件是对应图像中的匹配点对,我们的目标是计算所谓的camera matrix和3D空间中的实际点云!

  从一开始就很清楚,不可能唯一地确定点的位置。 这是一个普遍的模糊性,无论我们给出了多少图像,即使我们不仅仅有点对应数据。

  例如,给定几个立方体的图像,不可能分辨它的绝对位置(它位于Addis Ababa的夜总会,还是大英博物馆),它的方向(面朝北)或其大小。

  通过这个例子我们想说的是,重建最多可能达到世界的相似变换。 然而,事实证明,除非已知关于两个相机的校准,否则重建中的模糊性由更一般的变换类 -射影变换表示。

  产生这种模糊性是因为可能将射影变换(由4×4矩阵H表示)应用于每个点 X i {\rm X}_i Xi,并且在每个相机矩阵 P j {\rm P}_j Pj的右侧,而不改变射影图像点,因此:

P j X i = ( P j H − 1 ) ( H X i ) {\rm P}_j{\rm X}_i = ({\rm P}_j{\rm H}^{-1})({\rm HX}_i) PjXi=(PjH1)(HXi)

  没有令人信服的理由选择一组点和相机矩阵而不是另一组。 H的选择基本上是任意的,我们说重建具有射影模糊性,或者是射影重建

  然而,好消息是这是可能发生的最坏情况。 可以从两个视图重建一组点,直到不可避免的投影模糊。为了能够这样说,我们需要做一些条件限制; 必须有足够多的点,至少七个,并且它们不能位于各种明确定义的关键配置(critical configurations)中

  从两个视图重建点集的基本工具是基础矩阵(fundamental matrix),它表示如果它们是相同3D点的图像,则图像点 x \rm x x x ′ \rm x^\prime x所要遵循的约束。

  这种约束源于两个视图的相机中心,图像点和空间点的共面性。

  给定基本矩阵 F \rm F F,一对匹配点 x i ↔ x i ′ {\rm x}_i \leftrightarrow {\rm x}^\prime_i xixi, 必须满足

x i ′ F x i = 0 {\rm x}^\prime_i{\rm F}{\rm x}_i=0 xiFxi=0

  其中 F \rm F F是秩为2的3×3矩阵。这些方程在矩阵 F \rm F F的元素(entries)中是线性的,这意味着如果 F \rm F F是未知的,则可以从一组点对应计算它。

  一对相机矩阵 P \rm P P P ′ {\rm P^\prime} P 唯一地确定基本矩阵 F \rm F F,相反,基本矩阵确定一对相机矩阵,直到3D射影模糊度。 因此,基本矩阵封装了这对相机的完整投影几何,并且通过3D的射影变换而不变。

重建步骤

用于重建场景的基础矩阵方法非常简单,包括以下步骤:

  1. 给定两个视图中的几个点对应关系 x i ↔ x i ′ {\rm x}_i \leftrightarrow {\rm x}^\prime_i xixi,基于共面方程 x i ′ F x i = 0 {\rm x}^\prime_i{\rm F}{\rm x}_i=0 xiFxi=0在F的元素中形成线性方程。
  2. 找到 F \rm F F作为一组线性方程的解
  3. 根据某些给出的简单公式(后期博文若有需求则更新)计算 F \rm F F中的一对相机矩阵。
  4. 鉴于两个相机( P \rm P P P ′ {\rm P^\prime} P)和相应的图像点对 x i ↔ x i ′ {\rm x}_i \leftrightarrow {\rm x}^\prime_i xixi,找到射影到给定图像点的3D点 X i {\rm X}_i Xi。 以这种方式求解 X \rm X X被称为三角测量

  这里给出的算法只是一个大纲,以后会详细讨论了它的每个部分。 该算法不应直接从该简要描述中实现。

三维重建是计算机视觉领域的一个重要研究方向,它将多个视图的二维图像转换为三维模型。在深度学习的帮助下,三维重建技术已经取得了显著的进展。下面是一个基于深度学习的多视图三维重建的示例代码,使用了 TensorFlow 和 PyTorch 深度学习框架。 首先,我们需要准备数据集。假设我们有一个包含多个视图图像的数据集,每个视图图像都对应着一个三维模型。我们需要将这些视图图像和对应的三维模型一一配对,并将它们作为训练数据。 ```python import numpy as np import cv2 import os def load_data(data_dir): images = [] models = [] for filename in os.listdir(data_dir): if filename.endswith('.jpg'): image_path = os.path.join(data_dir, filename) model_path = os.path.join(data_dir, filename.replace('.jpg', '.npy')) images.append(cv2.imread(image_path)) models.append(np.load(model_path)) return images, models ``` 在加载数据之后,我们需要对图像进行预处理。具体来说,我们需要将图像缩放到相同的大小,并将像素值归一化到 [0, 1] 的范围。 ```python def preprocess_image(image, image_size): image = cv2.resize(image, (image_size, image_size)) image = image.astype(np.float32) / 255.0 return image ``` 接下来,我们将使用卷积神经网络对图像进行特征提取。具体来说,我们将使用一个基于 ResNet 架构的深度卷积神经网络。我们将从预训练的模型中加载权重,并使用它来提取图像特征。 ```python import tensorflow as tf from tensorflow.keras.applications.resnet50 import ResNet50 def build_feature_extractor(input_shape): model = ResNet50(include_top=False, weights='imagenet', input_shape=input_shape) for layer in model.layers: layer.trainable = False return model def extract_features(images, feature_extractor): features = [] for image in images: image = np.expand_dims(image, axis=0) features.append(feature_extractor.predict(image)) features = np.concatenate(features, axis=0) return features ``` 在提取图像特征之后,我们将使用多视图几何算法MVG)将多个视图的特征融合起来。具体来说,我们将使用一个基于 GCN 的图卷积神经网络来学习视图之间的关系,并将它们融合成一个三维模型。 ```python import torch import torch.nn as nn import torch.nn.functional as F from torch_geometric.nn import GCNConv class GraphConvolution(nn.Module): def __init__(self, input_dim, output_dim): super(GraphConvolution, self).__init__() self.conv = GCNConv(input_dim, output_dim) def forward(self, x, edge_index): x = self.conv(x, edge_index) x = F.relu(x) return x class MVGNet(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super(MVGNet, self).__init__() self.conv1 = GraphConvolution(input_dim, hidden_dim) self.conv2 = GraphConvolution(hidden_dim, output_dim) def forward(self, x, edge_index): x = self.conv1(x, edge_index) x = self.conv2(x, edge_index) return x def build_mvg_network(input_dim, hidden_dim, output_dim): model = MVGNet(input_dim, hidden_dim, output_dim) return model def train_mvg_network(features, models, mvg_network): optimizer = torch.optim.Adam(mvg_network.parameters(), lr=0.001) features = torch.from_numpy(features).float() models = torch.from_numpy(models).float() for epoch in range(100): optimizer.zero_grad() predictions = mvg_network(features, edge_index) loss = F.mse_loss(predictions, models) loss.backward() optimizer.step() print('Epoch {}, Loss: {}'.format(epoch, loss.item())) ``` 在训练 MVG 网络之后,我们可以使用它来预测新的三维模型。具体来说,我们将输入图像特征到 MVG 网络中,获得一个三维模型的预测值。 ```python def predict_3d_model(features, mvg_network): features = torch.from_numpy(features).float() with torch.no_grad(): predictions = mvg_network(features, edge_index) return predictions.numpy() ``` 最后,我们将所有代码整合起来,并在数据集上进行训练和预测。 ```python data_dir = '/path/to/data' image_size = 224 input_dim = 2048 hidden_dim = 128 output_dim = 3 images, models = load_data(data_dir) features = extract_features(images, build_feature_extractor((image_size, image_size, 3))) edge_index = build_edge_index(len(images)) mvg_network = build_mvg_network(input_dim, hidden_dim, output_dim) train_mvg_network(features, models, mvg_network) test_image = cv2.imread('/path/to/test/image.jpg') test_image = preprocess_image(test_image, image_size) test_features = extract_features([test_image], build_feature_extractor((image_size, image_size, 3))) predicted_model = predict_3d_model(test_features, mvg_network) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

YuYunTan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值