Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Car Damage Detection</title> | |
| <link rel="stylesheet" href="/static/css/style.css"> | |
| <script> | |
| function copyJSON() { | |
| const pre = document.getElementById('json-pre'); | |
| if (pre) { | |
| navigator.clipboard.writeText(pre.innerText); | |
| alert('JSON copied to clipboard!'); | |
| } | |
| } | |
| function toggleJSON() { | |
| const block = document.getElementById('json-block'); | |
| const btn = document.getElementById('toggle-json-btn'); | |
| if (block.style.display === 'none') { | |
| block.style.display = 'block'; | |
| btn.innerText = 'Hide JSON'; | |
| } else { | |
| block.style.display = 'none'; | |
| btn.innerText = 'Show JSON'; | |
| } | |
| } | |
| // Add new toggle function for LLM analysis | |
| function toggleLLM() { | |
| const block = document.getElementById('llm-block'); | |
| const btn = document.getElementById('toggle-llm-btn'); | |
| if (block.style.display === 'none') { | |
| block.style.display = 'block'; | |
| btn.innerText = 'Hide Analysis'; | |
| } else { | |
| block.style.display = 'none'; | |
| btn.innerText = 'Show Analysis'; | |
| } | |
| } | |
| function toggleBlock(blockId, btnId) { | |
| const block = document.getElementById(blockId); | |
| const btn = document.getElementById(btnId); | |
| if (block.style.display === 'none' || !block.style.display) { | |
| block.style.display = 'block'; | |
| btn.innerText = `Hide ${btnId.includes('json') ? 'JSON' : 'Analysis'}`; | |
| } else { | |
| block.style.display = 'none'; | |
| btn.innerText = `Show ${btnId.includes('json') ? 'JSON' : 'Analysis'}`; | |
| } | |
| } | |
| </script> | |
| <style> | |
| /* Add new LLM analysis styles */ | |
| .llm-section { | |
| margin-top: 20px; | |
| padding: 15px; | |
| background: #f8f9fa; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| } | |
| .llm-content { | |
| width: 100%; | |
| max-width: 800px; | |
| margin: 10px auto; | |
| display: none; | |
| } | |
| .llm-content pre { | |
| white-space: pre-wrap; | |
| word-wrap: break-word; | |
| background: white; | |
| padding: 15px; | |
| border-radius: 4px; | |
| border: 1px solid #dee2e6; | |
| } | |
| .toggle-llm-btn { | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| padding: 8px 16px; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| margin: 10px 0; | |
| } | |
| .toggle-llm-btn:hover { | |
| background-color: #0056b3; | |
| } | |
| .warning { | |
| background-color: #fff3cd; | |
| color: #856404; | |
| padding: 1rem; | |
| margin: 1rem 0; | |
| border: 1px solid #ffeeba; | |
| border-radius: 4px; | |
| } | |
| .llm-analysis { | |
| margin-top: 2rem; | |
| background: white; /* White background */ | |
| border-radius: 12px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); | |
| overflow: hidden; | |
| transition: all 0.3s ease; | |
| } | |
| .analysis-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 1.5rem; | |
| background: linear-gradient(135deg, #805ad5 0%, #6b46c1 100%); /* Keep purple gradient header */ | |
| color: white; | |
| } | |
| .analysis-header h3 { | |
| margin: 0; | |
| font-size: 1.5rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| color: white; | |
| } | |
| .toggle-btn { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| background: rgba(255, 255, 255, 0.15); | |
| color: white; | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| padding: 8px 16px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| .toggle-btn:hover { | |
| background: rgba(255, 255, 255, 0.25); | |
| } | |
| .toggle-btn i { | |
| transition: transform 0.3s ease; | |
| } | |
| .toggle-btn.active i { | |
| transform: rotate(180deg); | |
| } | |
| .analysis-content { | |
| padding: 1.5rem; | |
| background: white; | |
| color: #2d3748; /* Dark gray text */ | |
| } | |
| .damage-grid { | |
| display: grid; | |
| gap: 1.5rem; | |
| grid-template-columns: 1fr; | |
| } | |
| @media (min-width: 1024px) { | |
| .damage-grid { | |
| grid-template-columns: 3fr 2fr; | |
| } | |
| } | |
| .table-container { | |
| overflow-x: auto; | |
| background: white; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | |
| } | |
| .damage-table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin: 0; | |
| font-size: 0.95rem; | |
| color: #2d3748; | |
| } | |
| .damage-table th, .damage-table td { | |
| padding: 12px 16px; | |
| text-align: left; | |
| border-bottom: 1px solid #e2e8f0; | |
| } | |
| .damage-table th { | |
| background: #f7fafc; | |
| font-weight: 600; | |
| color: #4a5568; | |
| text-transform: uppercase; | |
| font-size: 0.85rem; | |
| letter-spacing: 0.05em; | |
| } | |
| .damage-table tr:last-child td { | |
| border-bottom: none; | |
| } | |
| .damage-table tbody tr { | |
| transition: background-color 0.2s ease; | |
| } | |
| .damage-table tbody tr:hover { | |
| background-color: #f7fafc; | |
| } | |
| .summary-section { | |
| background: white; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | |
| padding: 1.5rem; | |
| } | |
| .summary-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 1rem; | |
| color: #4a5568; | |
| } | |
| .summary-header h4 { | |
| margin: 0; | |
| font-size: 1.2rem; | |
| color: #2d3748; | |
| } | |
| .summary-content { | |
| color: #4a5568; | |
| line-height: 1.6; | |
| } | |
| .summary-content p { | |
| margin: 0 0 1rem; | |
| } | |
| .summary-content p:last-child { | |
| margin-bottom: 0; | |
| } | |
| /* Updated Severity colors for light background */ | |
| .severity-high { | |
| color: #e53e3e; /* Red */ | |
| } | |
| .severity-medium { | |
| color: #d69e2e; /* Yellow */ | |
| } | |
| .severity-low { | |
| color: #38a169; /* Green */ | |
| } | |
| /* Animation for content */ | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(-10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .analysis-content.show { | |
| animation: fadeIn 0.3s ease-out forwards; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header" style="position:relative;"> | |
| <h2 style="margin:0;">Car Damage & Parts Detection</h2> | |
| <img src="/static/img/logo.jpg" alt="Logo" class="logo" style="position:absolute; top:18px; right:32px; max-width:110px;"> | |
| </div> | |
| <div class="container"> | |
| <form method="post" action="/upload" enctype="multipart/form-data"> | |
| <input type="file" name="file" accept="image/*" required> | |
| <button type="submit">Upload & Analyze</button> | |
| </form> | |
| {% if error %}<div class="error">{{ error }}</div>{% endif %} | |
| {% if result %} | |
| <div class="results"> | |
| <h3>Results</h3> | |
| <div class="images-row"> | |
| <div> | |
| <div class="result-label">Original</div> | |
| <img src="{{ original_image }}" alt="Original Image" class="result-img"> | |
| </div> | |
| {% if result.parts_image %} | |
| <div> | |
| <div class="result-label">Parts Prediction</div> | |
| <img src="{{ result.parts_image }}" alt="Parts Prediction" class="result-img"> | |
| </div> | |
| {% endif %} | |
| </div> | |
| {% if result.warning %} | |
| <div class="warning">{{ result.warning }}</div> | |
| {% endif %} | |
| {% if result.json %} | |
| <h4 style="margin-bottom:8px;">JSON Output</h4> | |
| <button class="copy-btn" onclick="copyJSON()">Copy JSON</button> | |
| <button class="toggle-btn" id="toggle-json-btn" onclick="toggleBlock('json-block', 'toggle-json-btn')">Show JSON</button> | |
| <div id="json-block" style="display:none;"> | |
| <pre class="json-output" id="json-pre">{{ result.json | tojson(indent=2) }}</pre> | |
| </div> | |
| <a class="download-btn" href="{{ result.json_download }}" download>Download JSON</a> | |
| {% endif %} | |
| {% if result.parts_image %} | |
| <a class="download-btn" href="{{ result.parts_image }}" download>Download Parts Image</a> | |
| {% endif %} | |
| {% if result.llm_analysis %} | |
| <div class="llm-analysis"> | |
| <div class="analysis-header"> | |
| <h3><i class="fas fa-robot"></i> AI Damage Assessment Report</h3> | |
| <button class="toggle-btn" id="toggle-analysis-btn" onclick="toggleBlock('analysis-block', 'toggle-analysis-btn')"> | |
| <span class="btn-text">Show Analysis</span> | |
| <i class="fas fa-chevron-down"></i> | |
| </button> | |
| </div> | |
| <div id="analysis-block" class="analysis-content" style="display:none;"> | |
| <div class="damage-grid"> | |
| <div class="table-container"> | |
| <table class="damage-table"> | |
| <thead> | |
| <tr> | |
| <th>Component</th> | |
| <th>Status</th> | |
| <th>Severity</th> | |
| <th>Action Needed</th> | |
| </tr> | |
| </thead> | |
| <tbody id="damageTbody"> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div class="summary-section"> | |
| <div class="summary-header"> | |
| <i class="fas fa-clipboard-list"></i> | |
| <h4>Assessment Summary</h4> | |
| </div> | |
| <div id="summaryText" class="summary-content"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"> | |
| <style> | |
| .llm-analysis { | |
| margin-top: 2rem; | |
| background: white; /* White background */ | |
| border-radius: 12px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); | |
| overflow: hidden; | |
| transition: all 0.3s ease; | |
| } | |
| .analysis-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 1.5rem; | |
| background: linear-gradient(135deg, #805ad5 0%, #6b46c1 100%); /* Keep purple gradient header */ | |
| color: white; | |
| } | |
| .analysis-header h3 { | |
| margin: 0; | |
| font-size: 1.5rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| color: white; | |
| } | |
| .toggle-btn { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| background: rgba(255, 255, 255, 0.15); | |
| color: white; | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| padding: 8px 16px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| .toggle-btn:hover { | |
| background: rgba(255, 255, 255, 0.25); | |
| } | |
| .toggle-btn i { | |
| transition: transform 0.3s ease; | |
| } | |
| .toggle-btn.active i { | |
| transform: rotate(180deg); | |
| } | |
| .analysis-content { | |
| padding: 1.5rem; | |
| background: white; | |
| color: #2d3748; /* Dark gray text */ | |
| } | |
| .damage-grid { | |
| display: grid; | |
| gap: 1.5rem; | |
| grid-template-columns: 1fr; | |
| } | |
| @media (min-width: 1024px) { | |
| .damage-grid { | |
| grid-template-columns: 3fr 2fr; | |
| } | |
| } | |
| .table-container { | |
| overflow-x: auto; | |
| background: white; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | |
| } | |
| .damage-table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin: 0; | |
| font-size: 0.95rem; | |
| color: #2d3748; | |
| } | |
| .damage-table th, .damage-table td { | |
| padding: 12px 16px; | |
| text-align: left; | |
| border-bottom: 1px solid #e2e8f0; | |
| } | |
| .damage-table th { | |
| background: #f7fafc; | |
| font-weight: 600; | |
| color: #4a5568; | |
| text-transform: uppercase; | |
| font-size: 0.85rem; | |
| letter-spacing: 0.05em; | |
| } | |
| .damage-table tr:last-child td { | |
| border-bottom: none; | |
| } | |
| .damage-table tbody tr { | |
| transition: background-color 0.2s ease; | |
| } | |
| .damage-table tbody tr:hover { | |
| background-color: #f7fafc; | |
| } | |
| .summary-section { | |
| background: white; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | |
| padding: 1.5rem; | |
| } | |
| .summary-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 1rem; | |
| color: #4a5568; | |
| } | |
| .summary-header h4 { | |
| margin: 0; | |
| font-size: 1.2rem; | |
| color: #2d3748; | |
| } | |
| .summary-content { | |
| color: #4a5568; | |
| line-height: 1.6; | |
| } | |
| .summary-content p { | |
| margin: 0 0 1rem; | |
| } | |
| .summary-content p:last-child { | |
| margin-bottom: 0; | |
| } | |
| /* Updated Severity colors for light background */ | |
| .severity-high { | |
| color: #e53e3e; /* Red */ | |
| } | |
| .severity-medium { | |
| color: #d69e2e; /* Yellow */ | |
| } | |
| .severity-low { | |
| color: #38a169; /* Green */ | |
| } | |
| /* Animation for content */ | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(-10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .analysis-content.show { | |
| animation: fadeIn 0.3s ease-out forwards; | |
| } | |
| </style> | |
| <script> | |
| function parseAndDisplayDamageReport() { | |
| const block = document.getElementById('analysis-block'); | |
| const tbody = document.getElementById('damageTbody'); | |
| const summaryDiv = document.getElementById('summaryText'); | |
| const analysisText = `{{ result.llm_analysis | safe }}`; | |
| tbody.innerHTML = ''; | |
| summaryDiv.innerHTML = ''; | |
| const lines = analysisText.split('\n'); | |
| let summaryText = []; | |
| lines.forEach(line => { | |
| if (line.includes('|')) { | |
| const parts = line.split('|').filter(part => part.trim() !== ''); | |
| if (parts.length === 4 && !line.includes('Component') && !line.includes('---')) { | |
| const row = document.createElement('tr'); | |
| parts.forEach((part, index) => { | |
| const td = document.createElement('td'); | |
| const text = part.trim(); | |
| td.textContent = text; | |
| // Add severity class | |
| if (index === 2) { // Severity column | |
| if (text.toLowerCase().includes('high')) { | |
| td.classList.add('severity-high'); | |
| } else if (text.toLowerCase().includes('medium')) { | |
| td.classList.add('severity-medium'); | |
| } else if (text.toLowerCase().includes('low')) { | |
| td.classList.add('severity-low'); | |
| } | |
| } | |
| row.appendChild(td); | |
| }); | |
| tbody.appendChild(row); | |
| } | |
| } else if (line.trim() !== '' && !line.includes('**')) { | |
| if (line.length > 10) { | |
| summaryText.push(line.trim()); | |
| } | |
| } | |
| }); | |
| summaryText.forEach(text => { | |
| const p = document.createElement('p'); | |
| p.textContent = text; | |
| summaryDiv.appendChild(p); | |
| }); | |
| } | |
| function toggleBlock(blockId, btnId) { | |
| const block = document.getElementById(blockId); | |
| const btn = document.getElementById(btnId); | |
| const isHidden = block.style.display === 'none' || !block.style.display; | |
| block.style.display = isHidden ? 'block' : 'none'; | |
| btn.classList.toggle('active'); | |
| const btnText = btn.querySelector('.btn-text'); | |
| btnText.textContent = isHidden ? 'Hide Analysis' : 'Show Analysis'; | |
| if (isHidden) { | |
| block.classList.add('show'); | |
| parseAndDisplayDamageReport(); | |
| } else { | |
| block.classList.remove('show'); | |
| } | |
| } | |
| </script> | |
| {% endif %} | |
| </div> | |
| {% endif %} | |
| </div> | |
| <div class="footer"> | |
| © {{ 2025 }} DS Team. All rights reserved. | |
| </div> | |
| </body> | |
| </html> | |