Spaces:
Runtime error
Runtime error
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Compare Two Images</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> | |
<style> | |
.preset-image-container { | |
width: 100%; | |
overflow: hidden; | |
margin-bottom: 10px; | |
} | |
.preset-image { | |
width: 100%; | |
height: auto; | |
cursor: pointer; | |
transition: transform 0.2s, border 0.2s; | |
border: 2px solid transparent; | |
border-radius: 8px; | |
} | |
.preset-image:hover { | |
transform: scale(1.05); | |
} | |
.preset-image.selected { | |
border-color: #0d6efd; | |
} | |
.dropzone { | |
border: 2px dashed #ccc; | |
padding: 20px; | |
text-align: center; | |
margin-top: 10px; | |
border-radius: 8px; | |
background-color: #f9f9f9; | |
} | |
.preview-image { | |
width: 100%; | |
max-width: 200px; | |
height: auto; | |
margin: 10px auto; | |
display: block; | |
border-radius: 8px; | |
opacity: 0; | |
transition: opacity 0.5s ease-in; | |
} | |
.preview-image.visible { | |
opacity: 1; | |
} | |
.loading-container { | |
text-align: center; | |
margin-top: 20px; | |
} | |
.loading-text { | |
margin-top: 10px; | |
font-size: 18px; | |
color: #555; | |
} | |
#compareSection { | |
margin-top: 30px; | |
text-align: center; | |
} | |
#results { | |
margin-top: 20px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container my-4"> | |
<h1 class="text-center">Compare Two Images</h1> | |
<div class="row mt-4"> | |
<!-- Column 1: Original Image --> | |
<div class="col-md-6"> | |
<h5 class="text-center">Select Original Image</h5> | |
<div class="row"> | |
<div class="col-4"> | |
<div class="preset-image-container"> | |
<img id="preset-1-1" src="/static/back to the future_1b.jpg" class="preset-image" onclick="selectPreset(1, 1)" alt="Original 1"> | |
</div> | |
</div> | |
<div class="col-4"> | |
<div class="preset-image-container"> | |
<img id="preset-2-1" src="/static/chagall_1b.jpeg" class="preset-image" onclick="selectPreset(2, 1)" alt="Original 2"> | |
</div> | |
</div> | |
<div class="col-4"> | |
<div class="preset-image-container"> | |
<img id="preset-3-1" src="/static/muhammad ali_1.jpg" class="preset-image" onclick="selectPreset(3, 1)" alt="Original 3"> | |
</div> | |
</div> | |
</div> | |
<div class="dropzone" id="dropzone1"> | |
<p>Or drag and drop an image here</p> | |
<input type="file" id="fileInput1" accept="image/*" hidden> | |
<button class="btn btn-outline-primary" onclick="document.getElementById('fileInput1').click()">Upload Original</button> | |
</div> | |
</div> | |
<!-- Column 2: AI Generated Image --> | |
<div class="col-md-6"> | |
<h5 class="text-center">Select AI Generated Image</h5> | |
<div class="row"> | |
<div class="col-4"> | |
<div class="preset-image-container"> | |
<img id="preset-1-2" src="/static/back to the future_2b.png" class="preset-image" onclick="selectPreset(1, 2)" alt="AI 1"> | |
</div> | |
</div> | |
<div class="col-4"> | |
<div class="preset-image-container"> | |
<img id="preset-2-2" src="/static/chagall_2b.jpg" class="preset-image" onclick="selectPreset(2, 2)" alt="AI 2"> | |
</div> | |
</div> | |
<div class="col-4"> | |
<div class="preset-image-container"> | |
<img id="preset-3-2" src="/static/muhammad ali_2.png" class="preset-image" onclick="selectPreset(3, 2)" alt="AI 3"> | |
</div> | |
</div> | |
</div> | |
<div class="dropzone" id="dropzone2"> | |
<p>Or drag and drop an image here</p> | |
<input type="file" id="fileInput2" accept="image/*" hidden> | |
<button class="btn btn-outline-primary" onclick="document.getElementById('fileInput2').click()">Upload AI Image</button> | |
</div> | |
</div> | |
</div> | |
<!-- Section for Preview + Compare Button + Distance --> | |
<div id="compareSection" class="d-flex justify-content-center align-items-center flex-column" style="display: none;"> | |
<div class="d-flex justify-content-around align-items-center w-100"> | |
<img id="previewImage1" class="preview-image" alt="Original Preview"> | |
<div id="compareButtonContainer"></div> | |
<img id="previewImage2" class="preview-image" alt="AI Preview"> | |
</div> | |
<div id="results"></div> | |
</div> | |
</div> | |
<!-- Scripts --> | |
<script> | |
let file1 = null; | |
let file2 = null; | |
function resetSelection(target) { | |
for (let i = 1; i <= 3; i++) { | |
const img = document.getElementById(`preset-${i}-${target}`); | |
if (img) img.classList.remove('selected'); | |
} | |
} | |
function selectPreset(presetNumber, target) { | |
fetch(`/static/${presetNumber}.webp`) | |
.then(res => res.blob()) | |
.then(blob => { | |
const file = new File([blob], `preset${presetNumber}.webp`, { type: blob.type }); | |
if (target === 1) { | |
file1 = file; | |
updatePreview(blob, 1); | |
resetSelection(1); | |
document.getElementById(`preset-${presetNumber}-1`).classList.add('selected'); | |
} else { | |
file2 = file; | |
updatePreview(blob, 2); | |
resetSelection(2); | |
document.getElementById(`preset-${presetNumber}-2`).classList.add('selected'); | |
} | |
}) | |
.then(() => checkReadyToCompare()); | |
} | |
function updatePreview(blob, target) { | |
const reader = new FileReader(); | |
reader.onload = (event) => { | |
if (target === 1) { | |
document.getElementById('previewImage1').src = event.target.result; | |
document.getElementById('previewImage1').classList.add('visible'); | |
} else { | |
document.getElementById('previewImage2').src = event.target.result; | |
document.getElementById('previewImage2').classList.add('visible'); | |
} | |
document.getElementById('compareSection').style.display = 'flex'; | |
}; | |
reader.readAsDataURL(blob); | |
} | |
document.getElementById('fileInput1').addEventListener('change', (e) => { | |
file1 = e.target.files[0]; | |
updatePreview(file1, 1); | |
resetSelection(1); | |
checkReadyToCompare(); | |
}); | |
document.getElementById('fileInput2').addEventListener('change', (e) => { | |
file2 = e.target.files[0]; | |
updatePreview(file2, 2); | |
resetSelection(2); | |
checkReadyToCompare(); | |
}); | |
function checkReadyToCompare() { | |
const container = document.getElementById('compareButtonContainer'); | |
if (file1 && file2) { | |
container.innerHTML = ` | |
<button class="btn btn-primary" onclick="processImages()">Compare</button> | |
`; | |
} else { | |
container.innerHTML = ''; | |
} | |
} | |
async function processImages() { | |
if (!file1 || !file2) { | |
alert('Please select two images first!'); | |
return; | |
} | |
const formData = new FormData(); | |
formData.append('image1', file1); | |
formData.append('image2', file2); | |
const resultsDiv = document.getElementById('results'); | |
resultsDiv.innerHTML = ` | |
<div class="loading-container"> | |
<div class="spinner-border text-primary" role="status"></div> | |
<div class="loading-text">Processing...</div> | |
</div>`; | |
try { | |
const response = await fetch('/process', { | |
method: 'POST', | |
body: formData | |
}); | |
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); | |
const data = await response.json(); | |
if (data.distance !== undefined) { | |
resultsDiv.innerHTML = ` | |
<div class="card mt-3 p-4 text-center"> | |
<h4>Euclidean Distance</h4> | |
<p class="display-6">${data.distance.toFixed(4)}</p> | |
</div>`; | |
} else { | |
throw new Error('Invalid server response.'); | |
} | |
} catch (error) { | |
console.error('Error:', error); | |
resultsDiv.innerHTML = ` | |
<div class="alert alert-danger" role="alert"> | |
${error.message} | |
</div>`; | |
} | |
} | |
</script> | |
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> | |
</body> | |
</html> | |