Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Image Captioning & VQA Chatbot</title> | |
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet"> | |
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> | |
<style> | |
/* Global Styles */ | |
body { | |
background-color: #e5ddd5; /* WhatsApp light gray background */ | |
font-family: 'Roboto', sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
min-height: 100vh; | |
margin: 0; | |
color: #333; | |
} | |
.chat-container { | |
background-color: #fff; | |
border-radius: 10px; | |
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1); | |
width: 100%; | |
max-width: 700px; | |
display: flex; | |
flex-direction: column; | |
overflow: hidden; | |
} | |
.chat-header { | |
background-color: #25d366; /* WhatsApp green */ | |
color: #fff; | |
padding: 20px; | |
text-align: center; | |
font-size: 1.6rem; | |
font-weight: 500; | |
border-top-left-radius: 10px; | |
border-top-right-radius: 10px; | |
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); | |
} | |
.chat-body { | |
flex: 1; | |
padding: 20px; | |
overflow-y: auto; | |
max-height: 400px; | |
background-color: #f1f1f1; /* Light gray background for messages */ | |
border-bottom: 2px solid #ddd; | |
} | |
.chat-footer { | |
padding: 20px; | |
background-color: #ffffff; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
border-bottom-left-radius: 30px; | |
border-bottom-right-radius: 30px; | |
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); | |
} | |
.chat-bubble { | |
max-width: 75%; | |
margin-bottom: 15px; | |
padding: 12px 18px; | |
border-radius: 25px; | |
font-size: 1rem; | |
line-height: 1.5; | |
transition: all 0.3s ease; | |
} | |
.chat-bubble.bot { | |
background-color: #e4e6eb; /* Light gray color for bot messages */ | |
color: #333; | |
border-top-left-radius: 0; | |
align-self: flex-start; | |
} | |
.chat-bubble.user { | |
background-color: #25d366; /* WhatsApp green for user messages */ | |
color: #fff; | |
border-top-right-radius: 0; | |
align-self: flex-end; | |
} | |
.form-control { | |
border-radius: 5px; | |
padding: 15px; | |
font-size: 1rem; | |
border: 1px solid #ced4da; | |
transition: all 0.3s ease; | |
width: 100%; | |
} | |
.form-control:focus { | |
box-shadow: 0 0 8px rgba(108, 99, 255, 0.5); | |
border-color: #25d366; | |
} | |
.btn { | |
border-radius: 25px; | |
font-size: 1rem; | |
padding: 12px; | |
width: 100%; | |
font-weight: bold; | |
text-transform: uppercase; | |
transition: all 0.3s ease; | |
} | |
.btn-primary { | |
background-color: #25d366; /* WhatsApp green */ | |
border: none; | |
} | |
.btn-primary:hover { | |
background-color: #128c7e; | |
} | |
.upload-container { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
gap: 10px; | |
} | |
/* Custom file input */ | |
.upload-container input[type="file"] { | |
display: none; | |
} | |
.upload-btn { | |
padding: 15px 30px; | |
border-radius: 30px; | |
background-color: #25d366; /* WhatsApp green */ | |
color: white; | |
font-size: 1rem; | |
cursor: pointer; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
transition: all 0.3s ease; | |
} | |
.upload-btn:hover { | |
background-color: #128c7e; | |
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); | |
} | |
.uploaded-image { | |
max-width: 100%; | |
height: auto; | |
border-radius: 10px; | |
margin-top: 15px; | |
margin-bottom: 5px; | |
} | |
.similar-images-container { | |
margin-top: 15px; | |
} | |
.similar-images-container img { | |
border-radius: 15px; | |
margin: 5px; | |
transition: all 0.3s ease; | |
} | |
.similar-images-container img:hover { | |
transform: scale(1.1); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); | |
} | |
/* Scrollbar styling */ | |
.chat-body::-webkit-scrollbar { | |
width: 8px; | |
} | |
.chat-body::-webkit-scrollbar-thumb { | |
background-color: #25d366; | |
border-radius: 4px; | |
} | |
.output-image-container { | |
background-color: #e4e6eb; /* Light gray color for bot messages */ | |
color: #333; | |
border-top-left-radius: 0; | |
align-self: flex-start; | |
display: flex; | |
justify-content: space-between; | |
gap: 10px; | |
} | |
.output-image-container img { | |
width: 48%; /* Allow images to be side-by-side */ | |
height: auto; | |
} | |
.download-button { | |
margin-top: 10px; | |
padding: 10px 15px; | |
background-color: #02ca59; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
font-size: 14px; | |
} | |
.download-button:hover { | |
background-color: #00b34e; | |
} | |
#preview-img { | |
max-width: 300px; /* Adjust the max-width to limit the size */ | |
max-height: 300px; /* Optional: add max height to limit the height */ | |
display: none; | |
margin-bottom: 3px; | |
border-radius: 20px; | |
object-fit: contain; /* Ensures the image maintains its aspect ratio */ | |
} | |
</style> | |
</head> | |
<body> | |
<div class="chat-container"> | |
<div class="chat-header">Image Chatbot</div> | |
<div class="chat-body" id="chat-body"> | |
<div class="chat-bubble bot">Hello! Upload an image to get started.</div> | |
{% if image_url %} | |
<div class="chat-bubble user">Image uploaded successfully!</div> | |
<div class="output-image-container"> | |
<img src="{{ image_url }}" class="uploaded-image" alt="Uploaded Image"> | |
<img src="{{ input_image_url }}" class="uploaded-image" alt="Enhanced Image"> | |
</div> | |
<a href="{{ input_image_url }}" download> | |
<button class="download-button">Download Enhanced Image</button> | |
</a> | |
<div class="chat-bubble bot"> | |
Would you like to generate a caption or ask a question about the image? | |
</div> | |
{% endif %} | |
{% if caption %} | |
<div class="chat-bubble bot"> | |
Generated Caption: {{ caption }} | |
</div> | |
{% endif %} | |
{% if answer %} | |
<div class="chat-bubble bot"> | |
Answer to your question: {{ answer }} | |
</div> | |
{% endif %} | |
{% if similar_images %} | |
<div class="similar-images-container"> | |
<div class="chat-bubble bot">Here are some similar images:</div> | |
<div id="similar-images-list" class="row"> | |
{% for img_url in similar_images %} | |
<div class="col-md-3 mb-3 similar-image" style="display: {{ 'block' if loop.index <= 4 else 'none' }};"> | |
<img src="{{ img_url }}" class="img-fluid" alt="Similar Image"> | |
</div> | |
{% endfor %} | |
</div> | |
<button id="toggle-button" class="btn btn-primary mt-3">Show More</button> | |
</div> | |
{% endif %} | |
</div> | |
<div class="chat-footer"> | |
{% if not image_url %} | |
<div class="upload-container"> | |
<form action="{{ url_for('upload_file') }}" method="POST" enctype="multipart/form-data"> | |
<!-- Custom styled file input --> | |
<label class="upload-btn"> | |
Choose File | |
<input type="file" class="form-control" id="file" name="file" required> | |
</label> | |
<!-- Image preview and file name display --> | |
<div id="file-name" style="color: #555; font-size: 1rem; margin-top: 10px;"></div> | |
<div id="image-preview" style="margin-top: 10px;"> | |
<img id="preview-img" src="#" alt="Image Preview" style="max-width: 100%; display: none; border-radius: 20px;"> | |
</div> | |
<button type="submit" class="btn btn-primary">Upload Image</button> | |
</form> | |
</div> | |
{% else %} | |
<div class="message-container"> | |
<form action="{{ url_for('process_image') }}" method="POST"> | |
<input type="hidden" name="image_url" value="{{ image_url }}"> | |
<button type="submit" class="btn btn-info" name="caption">Generate Caption</button> | |
</form> | |
<form action="{{ url_for('process_image') }}" method="POST" class="mt-3"> | |
<input type="hidden" name="image_url" value="{{ image_url }}"> | |
<div class="form-group"> | |
<input type="text" class="form-control" id="question" name="question" placeholder="Ask a question about the image" required> | |
</div> | |
<button type="submit" class="btn btn-success" name="vqa">Get Answer</button> | |
</form> | |
</div> | |
{% endif %} | |
</div> | |
</div> | |
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script> | |
<script> | |
$(document).ready(function () { | |
// Initially hide the forms for Caption and VQA | |
$('#caption-form').hide(); | |
$('#vqa-form').hide(); | |
// Show caption form when "Generate Caption" button is clicked | |
$('#generate-caption').click(function() { | |
$('#caption-form').show(); | |
$('#vqa-form').hide(); | |
}); | |
// Show VQA form when "Ask a Question" button is clicked | |
$('#ask-question').click(function() { | |
$('#vqa-form').show(); | |
$('#caption-form').hide(); | |
}); | |
// Hide the "Please enter a question" alert once an answer is displayed | |
{% if answer %} | |
$('.alert-info').hide(); | |
{% endif %} | |
// File input change listener for image preview and file name | |
$('#file').on('change', function () { | |
var file = this.files[0]; | |
if (file) { | |
// Display the file name | |
$('#file-name').text("Selected file: " + file.name); | |
// Create an object URL for the image and display it as a preview | |
var reader = new FileReader(); | |
reader.onload = function (e) { | |
$('#preview-img').attr('src', e.target.result).show(); | |
}; | |
reader.readAsDataURL(file); | |
} else { | |
$('#file-name').text(""); // Reset file name if no file is selected | |
$('#preview-img').hide(); // Hide preview if no file is selected | |
} | |
}); | |
// Similar images functionality: Toggle between "Show More" and "Show Less" | |
const similarImages = $('.similar-image'); // All similar images | |
const toggleButton = $('#toggle-button'); | |
let isExpanded = false; // Track state of visibility | |
// Click event for "Show More" / "Show Less" | |
toggleButton.on('click', function () { | |
if (isExpanded) { | |
// Collapse to show only the first 4 images | |
similarImages.slice(4).hide(); | |
toggleButton.text('Show More'); | |
} else { | |
// Expand to show all images | |
similarImages.show(); | |
toggleButton.text('Show Less'); | |
} | |
isExpanded = !isExpanded; // Toggle state | |
}); | |
}); | |
</script> | |
</body> | |
</html> | |