update project structure and improve scripts
This commit is contained in:
@@ -0,0 +1,301 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Memory Module Detection</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
text-align: center;
|
||||
}
|
||||
.section {
|
||||
background: #f9f9f9;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.section h2 {
|
||||
margin-top: 0;
|
||||
color: #444;
|
||||
}
|
||||
button {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
button:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
input[type="file"] {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.result-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.detection-image {
|
||||
max-width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.detection-info {
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.error {
|
||||
color: #d32f2f;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.success {
|
||||
color: #388e3c;
|
||||
margin-top: 10px;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Memory Module Detection</h1>
|
||||
|
||||
<div class="section">
|
||||
<h2>Health Check</h2>
|
||||
<button id="healthCheckBtn">Check API Status</button>
|
||||
<div id="healthStatus"></div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Image Detection</h2>
|
||||
<input type="file" id="imageUpload" accept=".jpg,.jpeg,.png">
|
||||
<button id="uploadBtn">Detect Memory Modules</button>
|
||||
<div class="result-container" id="imageResult"></div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Video Detection</h2>
|
||||
<input type="file" id="videoUpload" accept=".mp4,.avi,.mov,.mkv">
|
||||
<div class="video-params">
|
||||
<label for="fpsInput">Frames per second:</label>
|
||||
<input type="number" id="fpsInput" min="1" max="30" value="1">
|
||||
|
||||
<label for="maxFramesInput">Max frames:</label>
|
||||
<input type="number" id="maxFramesInput" min="1" max="100" value="50">
|
||||
</div>
|
||||
<button id="videoBtn">Process Video</button>
|
||||
<div class="result-container" id="videoResult"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Health Check
|
||||
document.getElementById('healthCheckBtn').addEventListener('click', async () => {
|
||||
const statusDiv = document.getElementById('healthStatus');
|
||||
statusDiv.innerHTML = 'Checking...';
|
||||
|
||||
try {
|
||||
const response = await fetch("{{ url_for('health_check') }}");
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
statusDiv.innerHTML = `
|
||||
<div class="success">
|
||||
<p><strong>Status:</strong> ${data.status}</p>
|
||||
<p><strong>Service:</strong> ${data.service}</p>
|
||||
<p><strong>Model Loaded:</strong> ${data.model_loaded ? 'Yes' : 'No'}</p>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
statusDiv.innerHTML = `<div class="error">API Error: ${data.error || 'Unknown error'}</div>`;
|
||||
}
|
||||
} catch (error) {
|
||||
statusDiv.innerHTML = `<div class="error">Failed to connect to API: ${error.message}</div>`;
|
||||
}
|
||||
});
|
||||
|
||||
// Image upload detection
|
||||
document.getElementById('uploadBtn').addEventListener('click', async () => {
|
||||
const fileInput = document.getElementById('imageUpload');
|
||||
const resultDiv = document.getElementById('imageResult');
|
||||
|
||||
if (!fileInput.files || fileInput.files.length === 0) {
|
||||
resultDiv.innerHTML = '<div class="error">Please select an image file</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileInput.files[0];
|
||||
resultDiv.innerHTML = 'Processing...';
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('image', file);
|
||||
|
||||
const response = await fetch("{{ url_for('detect_memory') }}", {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok && data.success) {
|
||||
displayDetectionResult(resultDiv, data.data);
|
||||
} else {
|
||||
resultDiv.innerHTML = `<div class="error">${data.error || 'Detection failed'}</div>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
|
||||
}
|
||||
});
|
||||
|
||||
// Video processing
|
||||
document.getElementById('videoBtn').addEventListener('click', async () => {
|
||||
const fileInput = document.getElementById('videoUpload');
|
||||
const resultDiv = document.getElementById('videoResult');
|
||||
const fps = document.getElementById('fpsInput').value;
|
||||
const maxFrames = document.getElementById('maxFramesInput').value;
|
||||
|
||||
if (!fileInput.files || fileInput.files.length === 0) {
|
||||
resultDiv.innerHTML = '<div class="error">Please select a video file</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileInput.files[0];
|
||||
resultDiv.innerHTML = 'Processing... (This may take a while)';
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('video', file);
|
||||
formData.append('fps', fps);
|
||||
formData.append('max_frames', maxFrames);
|
||||
|
||||
const response = await fetch("{{ url_for('detect_video') }}", {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok && data.success) {
|
||||
displayVideoResult(resultDiv, data.data);
|
||||
} else {
|
||||
resultDiv.innerHTML = `<div class="error">${data.error || 'Video processing failed'}</div>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
|
||||
}
|
||||
});
|
||||
|
||||
// Helper function to display detection results
|
||||
function displayDetectionResult(container, data) {
|
||||
const detections = data.detections || [];
|
||||
|
||||
let html = `
|
||||
<div class="success">
|
||||
<p>Detected ${data.detection_count} memory modules</p>
|
||||
<img class="detection-image" src="{{ url_for('get_result_image', filename='') }}${data.result_image_url.split('/').pop()}" alt="Detection result">
|
||||
</div>
|
||||
<div class="detection-info">
|
||||
<h4>Detection Details:</h4>
|
||||
`;
|
||||
|
||||
if (detections.length > 0) {
|
||||
html += '<table><tr><th>Class</th><th>Confidence</th><th>Position (x1,y1,x2,y2)</th></tr>';
|
||||
|
||||
detections.forEach(det => {
|
||||
const className = 'Memory Module';
|
||||
const confidence = (det.confidence * 100).toFixed(2);
|
||||
const [x1, y1, x2, y2] = det.box.map(coord => coord.toFixed(1));
|
||||
|
||||
html += `
|
||||
<tr>
|
||||
<td>${className}</td>
|
||||
<td>${confidence}%</td>
|
||||
<td>${x1}, ${y1}, ${x2}, ${y2}</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
|
||||
html += '</table>';
|
||||
} else {
|
||||
html += '<p>No memory modules detected</p>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
// Helper function to display video results
|
||||
function displayVideoResult(container, data) {
|
||||
const detections = data.detections || [];
|
||||
const summary = data.summary || {};
|
||||
|
||||
let html = `
|
||||
<div class="success">
|
||||
<h3>Video Processing Results</h3>
|
||||
<p><strong>Video:</strong> ${data.video_filename}</p>
|
||||
<p><strong>Frames Processed:</strong> ${data.processing_info.frames_processed}</p>
|
||||
<p><strong>Processing Time:</strong> ${data.processing_info.processing_time.toFixed(2)} seconds</p>
|
||||
<p><strong>Average FPS:</strong> ${data.processing_info.average_fps.toFixed(2)}</p>
|
||||
|
||||
<h4>Summary:</h4>
|
||||
<p>Total Detections: ${summary.total_detections || 0}</p>
|
||||
<p>Average Confidence: ${summary.average_confidence ? (summary.average_confidence * 100).toFixed(2) + '%' : 'N/A'}</p>
|
||||
</div>
|
||||
|
||||
<div class="detection-info">
|
||||
<h4>Frame-by-Frame Detections:</h4>
|
||||
`;
|
||||
|
||||
if (detections.length > 0) {
|
||||
html += '<table><tr><th>Frame</th><th>Time (s)</th><th>Detections</th><th>Details</th></tr>';
|
||||
|
||||
detections.forEach(frame => {
|
||||
html += `
|
||||
<tr>
|
||||
<td>${frame.frame_number}</td>
|
||||
<td>${frame.timestamp.toFixed(2)}</td>
|
||||
<td>${frame.detection_count}</td>
|
||||
<td>
|
||||
${frame.detections.map(d => `
|
||||
Memory (${(d.confidence * 100).toFixed(2)}%) at ${d.box.map(coord => coord.toFixed(1)).join(',')}
|
||||
`).join('; ')}
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
|
||||
html += '</table>';
|
||||
} else {
|
||||
html += '<p>No memory modules detected in any frames</p>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
container.innerHTML = html;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user