File size: 3,649 Bytes
84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 84ff87e c045ba0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
import streamlit as st
import cv2
import open3d as o3d
import numpy as np
import tempfile
import os
# Title of the App
st.title("3D Reconstruction Tool from Video πΉ β π οΈ β π§")
# Sidebar: Information
st.sidebar.write("""
## About the App
Upload a video file, extract frames, reconstruct a 3D point cloud using Structure from Motion (SfM), and visualize or download the 3D mesh.
""")
# Step 1: Upload Video File
uploaded_file = st.file_uploader("Upload a Video File (MP4, AVI)", type=["mp4", "avi"])
# Function to extract frames from video
def extract_frames(video_path, frame_rate=10):
cap = cv2.VideoCapture(video_path)
frames = []
count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
if count % frame_rate == 0:
frames.append(frame)
count += 1
cap.release()
return frames
# Function to save frames as images
def save_frames_as_images(frames, output_dir):
os.makedirs(output_dir, exist_ok=True)
for i, frame in enumerate(frames):
filename = os.path.join(output_dir, f"frame_{i:04d}.png")
cv2.imwrite(filename, frame)
# Step 2: Process Uploaded Video
if uploaded_file:
st.video(uploaded_file)
st.write("Extracting frames...")
# Save the uploaded video temporarily
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_video:
tmp_video.write(uploaded_file.read())
video_path = tmp_video.name
# Extract frames
frames = extract_frames(video_path, frame_rate=10)
st.write(f"β
Extracted {len(frames)} frames from the video.")
# Save extracted frames
frames_dir = tempfile.mkdtemp()
save_frames_as_images(frames, frames_dir)
st.write(f"Frames saved temporarily at `{frames_dir}`.")
# Step 3: Structure from Motion (3D Reconstruction)
st.write("π Reconstructing 3D point cloud using Structure from Motion...")
# Create Open3D Point Cloud
pcd = o3d.geometry.PointCloud()
for image_file in sorted(os.listdir(frames_dir)):
img_path = os.path.join(frames_dir, image_file)
frame = cv2.imread(img_path)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Dummy point cloud generation for simplicity
height, width = gray.shape
x, y = np.meshgrid(np.arange(width), np.arange(height))
z = gray / 255.0 # Use gray intensity as a pseudo depth
points = np.stack((x.flatten(), y.flatten(), z.flatten()), axis=1)
pcd.points.extend(o3d.utility.Vector3dVector(points))
# Step 4: Surface Reconstruction
st.write("π οΈ Generating mesh using Poisson Reconstruction...")
pcd.estimate_normals()
mesh, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=8)
# Step 5: Visualization
st.write("β
Reconstruction Complete! Visualizing the 3D model:")
o3d.io.write_triangle_mesh("reconstructed_mesh.stl", mesh)
# Use Plotly for visualization
import plotly.graph_objects as go
vertices = np.asarray(mesh.vertices)
triangles = np.asarray(mesh.triangles)
fig = go.Figure(data=[go.Mesh3d(
x=vertices[:, 0],
y=vertices[:, 1],
z=vertices[:, 2],
i=triangles[:, 0],
j=triangles[:, 1],
k=triangles[:, 2],
color='lightblue',
opacity=0.50
)])
st.plotly_chart(fig)
# Step 6: Download the Optimized Mesh
st.write("π₯ Download the reconstructed 3D model:")
with open("reconstructed_mesh.stl", "rb") as f:
st.download_button("Download 3D Mesh (STL)", f, file_name="reconstructed_3D_Model.stl")
|