gradui-1 / templates /index.html
viranchi123's picture
Upload 75 files
ca46f55 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Depth Estimation, 3D Visualization</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f7f7f7;
color: #333;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
margin-bottom: 30px;
background: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header h1 {
font-size: 2.5rem;
font-weight: 700;
color: #1a1a1a;
margin-bottom: 8px;
}
.header p {
font-size: 1.1rem;
color: #666;
}
.main-content {
background: white;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
}
/* Tabs */
.tabs {
display: flex;
background: #f8f9fa;
border-bottom: 1px solid #e9ecef;
}
.tab {
flex: 1;
padding: 15px 20px;
background: none;
border: none;
cursor: pointer;
font-size: 1rem;
font-weight: 500;
color: #666;
transition: all 0.3s ease;
border-bottom: 3px solid transparent;
}
.tab.active {
background: white;
color: #1a1a1a;
border-bottom-color: #007bff;
}
.tab:hover {
background: #e9ecef;
}
.tab-content {
display: none;
padding: 30px;
}
.tab-content.active {
display: block;
}
/* Upload Section */
.upload-section {
text-align: center;
padding: 40px 20px;
border: 2px dashed #dee2e6;
border-radius: 8px;
background: #f8f9fa;
margin-bottom: 30px;
transition: all 0.3s ease;
}
.upload-section.dragover {
border-color: #007bff;
background: #e7f3ff;
}
.file-input {
display: none;
}
.upload-btn {
background: #007bff;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
font-size: 1rem;
cursor: pointer;
transition: background 0.3s ease;
}
.upload-btn:hover {
background: #0056b3;
}
/* Parameters */
.parameters {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.parameter-group {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
}
.parameter-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #495057;
font-size: 0.9rem;
}
.parameter-group input[type="range"] {
width: 100%;
margin-bottom: 8px;
}
.parameter-group .value-display {
font-size: 0.85rem;
color: #6c757d;
font-weight: 500;
}
/* Buttons */
.process-btn {
background: #28a745;
color: white;
padding: 12px 30px;
border: none;
border-radius: 6px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: background 0.3s ease;
margin: 20px 0;
}
.process-btn:hover {
background: #218838;
}
.process-btn:disabled {
background: #6c757d;
cursor: not-allowed;
}
/* Loading */
.loading {
text-align: center;
padding: 30px;
display: none;
}
.spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #007bff;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto 15px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Results */
.results {
display: none;
}
.results h2 {
margin-bottom: 20px;
color: #1a1a1a;
font-size: 1.5rem;
}
.image-comparison {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 30px;
}
.image-container {
text-align: center;
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
}
.image-container img {
max-width: 100%;
height: auto;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.image-container h3 {
margin-bottom: 15px;
color: #495057;
font-size: 1.1rem;
}
/* Downloads */
.downloads {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 15px;
margin-bottom: 30px;
}
.download-btn {
background: #6c757d;
color: white;
padding: 10px 16px;
border: none;
border-radius: 6px;
text-decoration: none;
text-align: center;
display: block;
font-size: 0.9rem;
transition: background 0.3s ease;
}
.download-btn:hover {
background: #545b62;
color: white;
text-decoration: none;
}
/* 3D Plot */
.plot-container {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
margin-top: 20px;
}
.plot-container h3 {
margin-bottom: 15px;
color: #495057;
font-size: 1.1rem;
}
#plot3d {
width: 100%;
height: 500px;
background: white;
border-radius: 6px;
}
/* Error */
.error {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 6px;
margin: 20px 0;
display: none;
border: 1px solid #f5c6cb;
}
/* Responsive */
@media (max-width: 768px) {
.header h1 {
font-size: 2rem;
}
.image-comparison {
grid-template-columns: 1fr;
}
.parameters {
grid-template-columns: 1fr;
}
.tabs {
flex-direction: column;
}
.tab {
border-bottom: 1px solid #e9ecef;
border-right: none;
}
.tab.active {
border-bottom-color: #007bff;
}
}
/* Gradio-like styling */
.gradio-container {
background: white;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.gradio-header {
padding: 20px 30px;
border-bottom: 1px solid #e9ecef;
background: #f8f9fa;
}
.gradio-header h3 {
margin: 0;
color: #1a1a1a;
font-size: 1.2rem;
font-weight: 600;
}
.gradio-body {
padding: 30px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Depth Estimation, 3D Visualization</h1>
<p>Upload an image to generate depth maps and 3D visualizations</p>
</div>
<div class="main-content">
<div class="tabs">
<button class="tab active" onclick="showTab('input')">Input</button>
<button class="tab" onclick="showTab('results')">Results</button>
<button class="tab" onclick="showTab('3d')">3D Visualization</button>
</div>
<!-- Input Tab -->
<div id="input" class="tab-content active">
<div class="gradio-container">
<div class="gradio-header">
<h3>Image Upload</h3>
</div>
<div class="gradio-body">
<div class="upload-section" id="uploadSection">
<h4>Upload Image</h4>
<p>Drag and drop an image here or click to select</p>
<input type="file" id="imageInput" class="file-input" accept="image/*">
<button class="upload-btn" onclick="document.getElementById('imageInput').click()">
Choose Image
</button>
</div>
</div>
</div>
<div class="gradio-container">
<div class="gradio-header">
<h3>Parameters</h3>
</div>
<div class="gradio-body">
<div class="parameters">
<div class="parameter-group">
<label for="numPoints">Number of 3D Points</label>
<input type="range" id="numPoints" min="1000" max="100000" value="10000" step="1000">
<div class="value-display">Value: <span id="numPointsValue">10000</span></div>
</div>
<div class="parameter-group">
<label for="focalX">Focal Length X (pixels)</label>
<input type="range" id="focalX" min="100" max="1000" value="470.4" step="10">
<div class="value-display">Value: <span id="focalXValue">470.4</span></div>
</div>
<div class="parameter-group">
<label for="focalY">Focal Length Y (pixels)</label>
<input type="range" id="focalY" min="100" max="1000" value="470.4" step="10">
<div class="value-display">Value: <span id="focalYValue">470.4</span></div>
</div>
</div>
<div style="text-align: center;">
<button class="process-btn" id="processBtn" onclick="processImage()" disabled>
Compute Depth
</button>
</div>
</div>
</div>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>Processing image... This may take a few moments.</p>
</div>
<div class="error" id="error"></div>
</div>
<!-- Results Tab -->
<div id="results" class="tab-content">
<div class="results" id="resultsContent">
<div class="gradio-container">
<div class="gradio-header">
<h3>Depth Map Results</h3>
</div>
<div class="gradio-body">
<div class="image-comparison">
<div class="image-container">
<h3>Original Image</h3>
<img id="originalImage" alt="Original Image">
</div>
<div class="image-container">
<h3>Depth Map</h3>
<img id="depthImage" alt="Depth Map">
</div>
</div>
</div>
</div>
<div class="gradio-container">
<div class="gradio-header">
<h3>Download Results</h3>
</div>
<div class="gradio-body">
<div class="downloads">
<a href="#" class="download-btn" id="grayDepthDownload">Download Grayscale Depth</a>
<a href="#" class="download-btn" id="rawDepthDownload">Download Raw Depth</a>
<a href="#" class="download-btn" id="pointcloudDownload">Download Point Cloud</a>
</div>
</div>
</div>
</div>
</div>
<!-- 3D Visualization Tab -->
<div id="3d" class="tab-content">
<div class="gradio-container">
<div class="gradio-header">
<h3>3D Point Cloud Visualization</h3>
</div>
<div class="gradio-body">
<div class="plot-container">
<div id="plot3d"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Tab functionality
function showTab(tabName) {
// Hide all tab contents
const tabContents = document.querySelectorAll('.tab-content');
tabContents.forEach(content => content.classList.remove('active'));
// Remove active class from all tabs
const tabs = document.querySelectorAll('.tab');
tabs.forEach(tab => tab.classList.remove('active'));
// Show selected tab content
document.getElementById(tabName).classList.add('active');
// Add active class to clicked tab
event.target.classList.add('active');
}
// Update value displays
document.getElementById('numPoints').addEventListener('input', function() {
document.getElementById('numPointsValue').textContent = this.value;
});
document.getElementById('focalX').addEventListener('input', function() {
document.getElementById('focalXValue').textContent = this.value;
});
document.getElementById('focalY').addEventListener('input', function() {
document.getElementById('focalYValue').textContent = this.value;
});
// File upload handling
const uploadSection = document.getElementById('uploadSection');
const imageInput = document.getElementById('imageInput');
const processBtn = document.getElementById('processBtn');
// Drag and drop functionality
uploadSection.addEventListener('dragover', function(e) {
e.preventDefault();
uploadSection.classList.add('dragover');
});
uploadSection.addEventListener('dragleave', function(e) {
e.preventDefault();
uploadSection.classList.remove('dragover');
});
uploadSection.addEventListener('drop', function(e) {
e.preventDefault();
uploadSection.classList.remove('dragover');
const files = e.dataTransfer.files;
if (files.length > 0) {
imageInput.files = files;
handleFileSelect();
}
});
imageInput.addEventListener('change', handleFileSelect);
function handleFileSelect() {
if (imageInput.files.length > 0) {
processBtn.disabled = false;
uploadSection.innerHTML = `
<h4>Image Selected</h4>
<p>${imageInput.files[0].name}</p>
<button class="upload-btn" onclick="document.getElementById('imageInput').click()">
Choose Different Image
</button>
`;
}
}
function processImage() {
if (!imageInput.files.length) return;
const formData = new FormData();
formData.append('image', imageInput.files[0]);
formData.append('num_points', document.getElementById('numPoints').value);
formData.append('focal_x', document.getElementById('focalX').value);
formData.append('focal_y', document.getElementById('focalY').value);
// Show loading
document.getElementById('loading').style.display = 'block';
document.getElementById('error').style.display = 'none';
document.getElementById('resultsContent').style.display = 'none';
processBtn.disabled = true;
fetch('/process', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
document.getElementById('loading').style.display = 'none';
processBtn.disabled = false;
if (data.success) {
// Display results
document.getElementById('originalImage').src = data.original_image;
document.getElementById('depthImage').src = data.colored_depth;
// Update download links
document.getElementById('grayDepthDownload').href = data.downloads.gray_depth;
document.getElementById('rawDepthDownload').href = data.downloads.raw_depth;
document.getElementById('pointcloudDownload').href = data.downloads.pointcloud;
// Display 3D plot
try {
const plotData = JSON.parse(data['3d_plot']);
Plotly.newPlot('plot3d', plotData.data, plotData.layout, {
responsive: true,
displayModeBar: true,
displaylogo: false
});
} catch (error) {
console.error('Error displaying 3D plot:', error);
document.getElementById('plot3d').innerHTML = '<p style="text-align: center; color: #666;">3D visualization could not be loaded</p>';
}
document.getElementById('resultsContent').style.display = 'block';
// Show results tab
showTab('results');
} else {
throw new Error(data.error || 'Unknown error occurred');
}
})
.catch(error => {
document.getElementById('loading').style.display = 'none';
processBtn.disabled = false;
document.getElementById('error').textContent = 'Error: ' + error.message;
document.getElementById('error').style.display = 'block';
});
}
</script>
</body>
</html>