Initial commit
This commit is contained in:
commit
ecf10ebf91
1785 files changed
+303456
No files matched your search
@@ -0,0 +1,284 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Web visualization version - Generate interactive HTML using plotly
|
||||
Point cloud data visualization tool with 3D interactive display support
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
import open3d as o3d
|
||||
import plotly.graph_objects as go
|
||||
|
||||
|
||||
def get_default_paths():
|
||||
"""Get default file paths"""
|
||||
# Get the directory where the script is located (tools directory)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
# Get project root directory (parent directory of tools)
|
||||
project_root = os.path.dirname(script_dir)
|
||||
|
||||
# Default PCD file paths (search in project root directory)
|
||||
possible_pcd_paths = [
|
||||
os.path.join(project_root, "test_data", "map_only23456.pcd"),
|
||||
os.path.join(project_root, "test_data", "0619", "1", "output.pcd"),
|
||||
os.path.join(project_root, "utm_test", "3", "output.pcd"),
|
||||
]
|
||||
|
||||
# Find existing PCD files
|
||||
for pcd_path in possible_pcd_paths:
|
||||
if os.path.exists(pcd_path):
|
||||
return pcd_path, os.path.join(project_root, "web_visualization")
|
||||
|
||||
# If not found, return the first path as default
|
||||
return possible_pcd_paths[0], os.path.join(project_root, "web_visualization")
|
||||
|
||||
|
||||
def find_pcd_files(directory):
|
||||
"""Find all PCD files in the specified directory"""
|
||||
pcd_files = []
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for file in files:
|
||||
if file.lower().endswith(".pcd"):
|
||||
pcd_files.append(os.path.join(root, file))
|
||||
return pcd_files
|
||||
|
||||
|
||||
def create_3d_visualization(pcd, output_dir="web_output", title="Point Cloud"):
|
||||
"""Create 3D interactive visualization"""
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
points = np.asarray(pcd.points)
|
||||
x, y, z = points[:, 0], points[:, 1], points[:, 2]
|
||||
|
||||
# Create 3D scatter plot
|
||||
fig_3d = go.Figure(
|
||||
data=[
|
||||
go.Scatter3d(
|
||||
x=x,
|
||||
y=y,
|
||||
z=z,
|
||||
mode="markers",
|
||||
marker=dict(
|
||||
size=2,
|
||||
color="steelblue", # Use single color
|
||||
opacity=0.8,
|
||||
),
|
||||
text=[
|
||||
f"X: {x[i]:.3f}<br>Y: {y[i]:.3f}<br>Z: {z[i]:.3f}"
|
||||
for i in range(min(1000, len(x)))
|
||||
], # Only add hover info for the first 1000 points
|
||||
hoverinfo="text",
|
||||
name="Point Cloud",
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
fig_3d.update_layout(
|
||||
title=dict(
|
||||
text="Interactive 3D Point Cloud Visualization", x=0.5, font=dict(size=20)
|
||||
),
|
||||
scene=dict(
|
||||
xaxis_title="X (m)",
|
||||
yaxis_title="Y (m)",
|
||||
zaxis_title="Z (m)",
|
||||
aspectmode="cube", # Use cube mode to maintain proportions and center
|
||||
camera=dict(
|
||||
eye=dict(x=0, y=0, z=2.5), # Set camera position for centered top view
|
||||
center=dict(x=0, y=0, z=0), # Set view center point
|
||||
),
|
||||
),
|
||||
width=1000,
|
||||
height=700,
|
||||
margin=dict(l=50, r=50, t=80, b=50), # Adjust margins to center the graph
|
||||
)
|
||||
|
||||
# Save 3D visualization
|
||||
html_3d_path = os.path.join(output_dir, "pointcloud_3d.html")
|
||||
fig_3d.write_html(html_3d_path)
|
||||
|
||||
return html_3d_path
|
||||
|
||||
|
||||
def create_simple_index(output_dir, html_3d_path):
|
||||
"""Create simplified index page"""
|
||||
html_content = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>3D Point Cloud Visualization</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
text-align: center;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 30px;
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.header h1 {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
}
|
||||
.header p {
|
||||
color: #666;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
padding: 15px 30px;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
margin: 20px 0;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.solution-box {
|
||||
background-color: #e8f5e8;
|
||||
border: 1px solid #28a745;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.solution-box h3 {
|
||||
color: #28a745;
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🎯 3D Point Cloud Interactive Visualization</h1>
|
||||
</div>
|
||||
|
||||
<a href="pointcloud_3d.html" class="btn">🌐 Open 3D Point Cloud Visualization</a>
|
||||
|
||||
<div style="margin-top: 40px; padding: 20px; background-color: #f8f9fa; border-radius: 8px; text-align: center;">
|
||||
<h3>💡 Usage Instructions</h3>
|
||||
<p>Click the button above to open the 3D visualization page and use mouse for interactive operations:</p>
|
||||
<ul style="display: inline-block; text-align: left; margin: 0; padding-left: 20px;">
|
||||
<li>Drag: Rotate view</li>
|
||||
<li>Scroll wheel: Zoom</li>
|
||||
<li>Right-click drag: Pan</li>
|
||||
<li>Hover: View point coordinates</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
index_path = os.path.join(output_dir, "index.html")
|
||||
with open(index_path, "w", encoding="utf-8") as f:
|
||||
f.write(html_content)
|
||||
|
||||
return index_path
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
print("=== Image2PCD Web Visualization Tool ===")
|
||||
|
||||
# Get default paths
|
||||
default_pcd_path, default_output_dir = get_default_paths()
|
||||
|
||||
# Check for command line arguments
|
||||
if len(sys.argv) > 1:
|
||||
pcd_path = sys.argv[1]
|
||||
if not os.path.exists(pcd_path):
|
||||
print(f"Error: Specified PCD file does not exist: {pcd_path}")
|
||||
return
|
||||
else:
|
||||
pcd_path = default_pcd_path
|
||||
if not os.path.exists(pcd_path):
|
||||
print(f"Warning: Default PCD file does not exist: {pcd_path}")
|
||||
# Try to find other PCD files
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_root = os.path.dirname(script_dir)
|
||||
|
||||
print("Searching for PCD files...")
|
||||
pcd_files = find_pcd_files(project_root)
|
||||
|
||||
if pcd_files:
|
||||
pcd_path = pcd_files[0]
|
||||
print(f"Found PCD file: {pcd_path}")
|
||||
else:
|
||||
print("Error: No PCD files found")
|
||||
print(
|
||||
"Please ensure there are PCD files in the project, or specify file path via command line"
|
||||
)
|
||||
print("Usage: python pcd_web.py <pcd_file_path>")
|
||||
return
|
||||
|
||||
# Set output directory
|
||||
if len(sys.argv) > 2:
|
||||
output_dir = sys.argv[2]
|
||||
else:
|
||||
output_dir = default_output_dir
|
||||
|
||||
print(f"Input file: {pcd_path}")
|
||||
print(f"Output directory: {output_dir}")
|
||||
|
||||
# Load point cloud
|
||||
print("Loading point cloud file...")
|
||||
pcd = o3d.io.read_point_cloud(pcd_path)
|
||||
if len(pcd.points) == 0:
|
||||
print("Error: Unable to load point cloud file or file is empty")
|
||||
print("Please check if the file format is correct")
|
||||
return
|
||||
|
||||
print(f"Successfully loaded point cloud with {len(pcd.points)} points")
|
||||
|
||||
# Get filename as title
|
||||
pcd_filename = os.path.basename(pcd_path)
|
||||
title = f"Point Cloud: {pcd_filename}"
|
||||
|
||||
# Create 3D visualization
|
||||
print("Generating 3D visualization...")
|
||||
html_3d_path = create_3d_visualization(pcd, output_dir, title)
|
||||
|
||||
# Create index page
|
||||
print("Generating index page...")
|
||||
index_path = create_simple_index(output_dir, html_3d_path)
|
||||
|
||||
print("\n3D visualization created successfully!")
|
||||
print(f"Output directory: {os.path.abspath(output_dir)}")
|
||||
print(f"Main page: {os.path.abspath(index_path)}")
|
||||
print(f"3D visualization: {os.path.abspath(html_3d_path)}")
|
||||
print("\nUsage:")
|
||||
print(f"1. Open in browser: file://{os.path.abspath(index_path)}")
|
||||
print(f"2. Or open directly: file://{os.path.abspath(html_3d_path)}")
|
||||
|
||||
# Try to automatically open browser (optional)
|
||||
try:
|
||||
import webbrowser
|
||||
|
||||
webbrowser.open(f"file://{os.path.abspath(index_path)}")
|
||||
print("Attempted to open visualization page in default browser")
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user