南宁哪里有做网站的公司,设计企业网店推广策略,跨境支付互联互通,做网站找众展2D图像的三维重建是从一组2D图像中创建对象或场景的三维模型的过程。这个技术广泛应用于计算机视觉、机器人技术和虚拟现实等领域。 在本文中#xff0c;我们将解释如何使用Python执行从2D图像到三维重建的过程。我们将使用TempleRing数据集作为示例#xff0c;逐步演示这个过… 2D图像的三维重建是从一组2D图像中创建对象或场景的三维模型的过程。这个技术广泛应用于计算机视觉、机器人技术和虚拟现实等领域。 在本文中我们将解释如何使用Python执行从2D图像到三维重建的过程。我们将使用TempleRing数据集作为示例逐步演示这个过程。该数据集包含了在对象周围的一个环上采样的阿格里真托Agrigento“Dioskouroi神庙”复制品的47个视图。 三维重建的关键概念 在深入了解如何使用Python从2D图像执行三维重建的详细步骤之前让我们首先回顾一些与这个主题相关的关键概念。 深度图 深度图是一幅图像其中每个像素代表摄像机和场景中相应点之间的距离。深度图常用于计算机视觉和机器人技术中用于表示场景的三维结构。 有许多不同的方法可以从2D图像计算深度图包括立体对应、结构光和飞行时间等。在本文中我们将使用立体对应来从示例数据集计算深度图。 Point Cloud 点云是表示对象或场景形状的三维空间中的一组点。点云常用于计算机视觉和机器人技术中用于表示场景的三维结构。 一旦我们计算出代表场景深度的深度图我们可以使用它来计算一个三维点云。这涉及使用有关摄像机内部和外部参数的信息将深度图中的每个像素投影回三维空间。 网格 网格是一个由顶点、边和面连接而成的表面表示。网格常用于计算机图形学和虚拟现实中用于表示对象或场景的形状。 一旦我们计算出代表对象或场景形状的三维点云我们可以使用它来生成一个网格。这涉及使用诸如Marching Cubes或Poisson表面重建等算法将表面拟合到点云上。 逐步实现 现在我们已经回顾了与2D图像的三维重建相关的一些关键概念让我们看看如何使用Python执行这个过程。我们将使用TempleRing数据集作为示例逐步演示这个过程。下面是一个执行Temple Ring数据集中图像的三维重建的示例代码 安装库 pip install numpy scipy 导入库 #importing libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os 加载TempleRing数据集的图像 # Directory containing the dataset images
dataset_dir /content/drive/MyDrive/templeRing # Initialize the list to store images
images []# Attempt to load the grayscale images and store them in the list
for i in range(1, 48): # Assuming images are named templeR0001.png to templeR0047.pngimg_path os.path.join(dataset_dir, ftempleR{i:04d}.png)img cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)if img is not None:images.append(img)else:print(fWarning: Unable to load templeR{i:04d}.png)# Visualize the input images
num_rows 5 # Specify the number of rows
num_cols 10 # Specify the number of columns
fig, axs plt.subplots(num_rows, num_cols, figsize(15, 8))# Loop through the images and display them
for i, img in enumerate(images):row_index i // num_cols # Calculate the row index for the subplotcol_index i % num_cols # Calculate the column index for the subplotaxs[row_index, col_index].imshow(img, cmapgray)axs[row_index, col_index].axis(off)# Fill any remaining empty subplots with a white background
for i in range(len(images), num_rows * num_cols):row_index i // num_colscol_index i % num_colsaxs[row_index, col_index].axis(off)plt.show() 解释这段代码加载灰度图像序列将它们排列在网格布局中并使用matplotlib显示它们。 为每个图像计算深度图 # Directory containing the dataset images
dataset_dir /content/drive/MyDrive/templeRing # Initialize the list to store images
images []# Attempt to load the grayscale images and store them in the list
for i in range(1, 48): # Assuming images are named templeR0001.png to templeR0047.pngimg_path os.path.join(dataset_dir, ftempleR{i:04d}.png)img cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)if img is not None:images.append(img)else:print(fWarning: Unable to load templeR{i:04d}.png)# Initialize the list to store depth maps
depth_maps []# Create a StereoBM object with your preferred parameters
stereo cv2.StereoBM_create(numDisparities16, blockSize15)# Loop through the images to calculate depth maps
for img in images:# Compute the depth mapdisparity stereo.compute(img, img) # Normalize the disparity map for visualizationdisparity_normalized cv2.normalize(disparity, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U) # Append the normalized disparity map to the list of depth mapsdepth_maps.append(disparity_normalized)# Visualize all the depth maps
num_rows 5 # Specify the number of rows
num_cols 10 # Specify the number of columns
fig, axs plt.subplots(num_rows, num_cols, figsize(15, 8))for i, depth_map in enumerate(depth_maps):row_index i // num_cols # Calculate the row index for the subplotcol_index i % num_cols # Calculate the column index for the subplotaxs[row_index, col_index].imshow(depth_map, cmapjet)axs[row_index, col_index].axis(off)# Fill any remaining empty subplots with a white background
for i in range(len(depth_maps), num_rows * num_cols):row_index i // num_colscol_index i % num_colsaxs[row_index, col_index].axis(off)plt.show() 解释这段代码负责使用Stereo Block MatchingStereoBM算法从一系列立体图像中计算深度图。它遍历灰度立体图像列表并为每一对相邻图像计算深度图。 可视化每个图像的深度图 # Initialize an accumulator for the sum of depth maps
sum_depth_map np.zeros_like(depth_maps[0], dtypenp.float64) # Compute the sum of all depth maps
for depth_map in depth_maps:sum_depth_map depth_map.astype(np.float64)
# Calculate the mean depth map by dividing the sum by the number of depth maps
mean_depth_map (sum_depth_map / len(depth_maps)).astype(np.uint8)
# Display the mean depth map
plt.figure(figsize(8, 6))
plt.imshow(mean_depth_map, cmapjet)
plt.title(Mean Depth Map)
plt.axis(off)
plt.show() 输出 解释这段代码通过累加深度图来计算平均深度图。然后通过将总和除以深度图的数量来计算平均值。最后使用jet颜色图谱显示平均深度图以进行可视化。 从平均深度图计算三维点云 # Initialize an accumulator for the sum of depth maps
sum_depth_map np.zeros_like(depth_maps[0], dtypenp.float64) # Compute the sum of all depth maps
for depth_map in depth_maps:sum_depth_map depth_map.astype(np.float64)# Calculate the mean depth map by dividing the sum by the number of depth maps
mean_depth_map (sum_depth_map / len(depth_maps)).astype(np.uint8)# Display the mean depth map
plt.figure(figsize(8, 6))
plt.imshow(mean_depth_map, cmapjet)
plt.title(Mean Depth Map)
plt.axis(off)
plt.show() 解释这段代码通过对深度图进行累加来计算平均深度图。然后通过将总和除以深度图的数量来计算平均值。最后使用Jet颜色映射来可视化显示平均深度图。 计算平均深度图的三维点云 #converting into point cloud
points_3D cv2.reprojectImageTo3D(mean_depth_map.astype(np.float32), np.eye(4)) 解释该代码将包含点云中点的三维坐标并且您可以使用这些坐标进行三维重建。 从点云生成网格 安装库 !pip install numpy scipy 导入库 #importing libraries
from scipy.spatial import Delaunay
from skimage import measure
from skimage.measure import marching_cubes 生成网格 verts, faces, normals, values measure.marching_cubes(points_3D) 解释该代码将Marching Cubes算法应用于3D点云以生成网格。它返回定义结果3D网格的顶点、面、顶点法线和标量值。 可视化网格 fig plt.figure()
ax fig.add_subplot(111, projection3d)
ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], trianglesfaces)
plt.show() 输出 解释该代码使用matplotlib可视化网格。它创建一个3D图并使用ax.plot_trisurf方法将网格添加到其中。 这段代码从Temple Ring数据集加载图像并使用块匹配block matching进行每个图像的深度图计算然后通过平均所有深度图来计算平均深度图并使用它来计算每个像素的三维点云。最后它使用Marching Cubes算法从点云生成网格并进行可视化。 结果比较 # importing the libraries
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # Create a figure with two subplots
fig, axs plt.subplots(1, 2, figsize(10, 5))# Visualize the original image in the first subplot
axs[0].imshow(images[0], cmapgray)
axs[0].axis(off)
axs[0].set_title(Original)# Visualize the reconstructed mesh in the second subplot
ax fig.add_subplot(1, 2, 2, projection3d)
ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], trianglesfaces)
ax.set_title(Reconstructed)# Show the figure
plt.show() 解释在此代码中使用matplotlib创建了包含两个子图的图形。在第一个图中显示了来自数据集的原始图像。在第二个图中使用3D三角形表面图可视化了重建的3D网格。 方法2 以下是执行来自TempleRing数据集图像的3D重建的另一个示例代码 引入模块 import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab.patches import cv2_imshow 加载两个Temple Ring数据集图像 # Load the PNG images (replace with your actual file paths)
image1 cv2.imread(/content/drive/MyDrive/templeRing/templeR0001.png)
image2 cv2.imread(/content/drive/MyDrive/templeRing/templeR0002.png 解释该代码使用OpenCV的cv2.imread函数从TempleRing数据集加载两个图像。 转换为灰度图 # Convert images to grayscale
gray1 cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray2 cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) 该代码使用OpenCV将两个图像转换为灰度图像。它们以单通道表示其中每个像素的值表示其强度并且没有颜色通道。 查找SIFT关键点和描述符 # Initialize the SIFT detector
sift cv2.SIFT_create() # Detect keypoints and compute descriptors for both images
kp1, des1 sift.detectAndCompute(gray1, None)
kp2, des2 sift.detectAndCompute(gray2, None) 该代码使用尺度不变特征变换SIFT算法在两个图像中查找关键点和描述符。它使用OpenCV的cv2.SIFT_create()函数创建一个SIFT对象并调用其detectAndCompute方法来计算关键点和描述符。 使用FLANN匹配器匹配描述符 # Create a FLANN-based Matcher object
flann cv2.FlannBasedMatcher({algorithm: 0, trees: 5}, {}) # Match the descriptors using KNN (k-nearest neighbors)
matches flann.knnMatch(des1, des2, k2) 解释该代码使用Fast Library for Approximate Nearest NeighborsFLANN匹配器对描述符进行匹配。它使用OpenCV的cv2.FlannBasedMatcher函数创建FLANN匹配器对象并调用其knnMatch方法来找到每个描述符的k个最近邻。 使用Lowe的比率测试筛选出好的匹配项 # Apply Lowes ratio test to select good matches
good_matches []
for m, n in matches:if m.distance 0.7 * n.distance:good_matches.append(m) 解释该代码使用Lowe的比率测试筛选出好的匹配项。它使用最近邻和次近邻之间距离比的阈值来确定匹配是否良好。 提取匹配的关键点 # Extract matched keypoints
src_pts np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2) 解释该代码从两组关键点中提取匹配的关键点这些关键点将用于估算对齐两个图像的变换。这些关键点的坐标存储在src_pts和dst_pts中。 使用RANSAC找到单应矩阵 # Find the homography matrix using RANSAC
H, _ cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) 在这段代码中它使用RANSAC算法基于匹配的关键点计算描述两个图像之间的变换的单应矩阵。单应矩阵后来可以用于拉伸或变换一个图像使其与另一个图像对齐。 使用单应矩阵将第一个图像进行变换 # Perform perspective transformation to warp image1 onto image2
height, width image2.shape[:2]
result cv2.warpPerspective(image1, H, (width, height)) # Display the result
cv2_imshow(result) 解释该代码使用单应矩阵和OpenCV的cv2.warpPerspective函数将第一个图像进行变换。它指定输出图像的大小足够大可以容纳两个图像然后呈现结果图像。 显示原始图像和重建图像 # Display the original images and the reconstructed image side by side
fig, (ax1, ax2, ax3) plt.subplots(1, 3, figsize(12, 4))
ax1.imshow(cv2.cvtColor(image1, cv2.COLOR_BGR2RGB))
ax1.set_title(Image 1)
ax1.axis(off)
ax2.imshow(cv2.cvtColor(image2, cv2.COLOR_BGR2RGB))
ax2.set_title(Image 2)
ax2.axis(off)
ax3.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
ax3.set_title(Reconstructed Image)
ax3.axis(off) plt.show() 输出 解释这段代码展示了在一个具有三个子图的单一图形中可视化原始图像和重建图像的过程。它使用matplotlib库显示图像并为每个子图设置标题和轴属性。 不同的可能方法 有许多不同的方法和算法可用于从2D图像执行3D重建。选择的方法取决于诸如输入图像的质量、摄像机校准信息的可用性以及重建的期望准确性和速度等因素。 一些常见的从2D图像执行3D重建的方法包括立体对应、运动结构和多视图立体。每种方法都有其优点和缺点对于特定应用来说最佳方法取决于具体的要求和约束。 结论 总的来说本文概述了使用Python从2D图像进行3D重建的过程。我们讨论了深度图、点云和网格等关键概念并使用TempleRing数据集演示了使用两种不同方法逐步进行的过程。我们希望本文能帮助您更好地理解从2D图像进行3D重建以及如何使用Python实现这一过程。有许多可用于执行3D重建的不同方法和算法我们鼓励您进行实验和探索以找到最适合您需求的方法。 · END · HAPPY LIFE 本文仅供学习交流使用如有侵权请联系作者删除