Include JS zoom
Browse files- app.py +57 -2
- launch.sh +1 -1
- requirements.txt +1 -1
app.py
CHANGED
|
@@ -67,6 +67,7 @@ def update_rankings_table():
|
|
| 67 |
rankings.sort(key=lambda x: x[1], reverse=True)
|
| 68 |
return rankings
|
| 69 |
|
|
|
|
| 70 |
def select_new_image():
|
| 71 |
"""Select a new image and its segmented versions."""
|
| 72 |
max_attempts = 10
|
|
@@ -141,9 +142,59 @@ def compute_mask_difference(segmented_a, segmented_b):
|
|
| 141 |
# Compute the absolute difference between the masks
|
| 142 |
return np.abs(mask_a_1d - mask_b_1d)
|
| 143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
def gradio_interface():
|
| 145 |
"""Create and return the Gradio interface."""
|
| 146 |
-
with gr.Blocks() as demo:
|
| 147 |
gr.Markdown("# Background Removal Arena")
|
| 148 |
button_name = "Difference between masks"
|
| 149 |
|
|
@@ -277,7 +328,7 @@ def gradio_interface():
|
|
| 277 |
state_segmented_a, state_segmented_b, notice_markdown
|
| 278 |
]
|
| 279 |
)
|
| 280 |
-
|
| 281 |
|
| 282 |
def handle_zoom(current_image, zoomed_state_input, original_image, other_image, event: gr.SelectData):
|
| 283 |
"""Toggle between zoomed and original image based on click events."""
|
|
@@ -462,7 +513,11 @@ def schedule_dump_database(interval=60):
|
|
| 462 |
else:
|
| 463 |
logging.info("Not running in Hugging Face Spaces. Database dump scheduler not started.")
|
| 464 |
|
|
|
|
|
|
|
|
|
|
| 465 |
if __name__ == "__main__":
|
| 466 |
schedule_dump_database() # Start the periodic database dump
|
| 467 |
demo = gradio_interface()
|
|
|
|
| 468 |
demo.launch()
|
|
|
|
| 67 |
rankings.sort(key=lambda x: x[1], reverse=True)
|
| 68 |
return rankings
|
| 69 |
|
| 70 |
+
|
| 71 |
def select_new_image():
|
| 72 |
"""Select a new image and its segmented versions."""
|
| 73 |
max_attempts = 10
|
|
|
|
| 142 |
# Compute the absolute difference between the masks
|
| 143 |
return np.abs(mask_a_1d - mask_b_1d)
|
| 144 |
|
| 145 |
+
js = r"""
|
| 146 |
+
function load_zoom() {
|
| 147 |
+
setTimeout(function() {
|
| 148 |
+
|
| 149 |
+
// Select all images from the three displayed image containers.
|
| 150 |
+
const images = document.querySelectorAll('.image-container img');
|
| 151 |
+
|
| 152 |
+
// Set transform origin so scaling and translating feels "natural".
|
| 153 |
+
images.forEach(img => {
|
| 154 |
+
img.style.transformOrigin = 'top left';
|
| 155 |
+
img.style.transition = 'transform 0.1s ease-out';
|
| 156 |
+
img.style.cursor = 'zoom-in';
|
| 157 |
+
});
|
| 158 |
+
|
| 159 |
+
// Choose a scale factor
|
| 160 |
+
const scale = 2;
|
| 161 |
+
|
| 162 |
+
function handleMouseMove(e) {
|
| 163 |
+
const rect = e.currentTarget.getBoundingClientRect();
|
| 164 |
+
const xPercent = (e.clientX - rect.left) / rect.width;
|
| 165 |
+
const yPercent = (e.clientY - rect.top) / rect.height;
|
| 166 |
+
const offsetX = xPercent * (scale - 1) * 100;
|
| 167 |
+
const offsetY = yPercent * (scale - 1) * 100;
|
| 168 |
+
|
| 169 |
+
images.forEach(img => {
|
| 170 |
+
img.style.transform = `translate(-${offsetX}%, -${offsetY}%) scale(${scale})`;
|
| 171 |
+
});
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
function handleMouseEnter(e) {
|
| 175 |
+
e.currentTarget.addEventListener('mousemove', handleMouseMove);
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
function handleMouseLeave(e) {
|
| 179 |
+
e.currentTarget.removeEventListener('mousemove', handleMouseMove);
|
| 180 |
+
images.forEach(img => {
|
| 181 |
+
img.style.transform = 'translate(0,0) scale(1)';
|
| 182 |
+
});
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
const containers = document.querySelectorAll('.image-container');
|
| 186 |
+
|
| 187 |
+
containers.forEach(container => {
|
| 188 |
+
container.addEventListener('mouseenter', handleMouseEnter);
|
| 189 |
+
container.addEventListener('mouseleave', handleMouseLeave);
|
| 190 |
+
});
|
| 191 |
+
}, 1000); // 1 second timeout
|
| 192 |
+
}
|
| 193 |
+
"""
|
| 194 |
+
|
| 195 |
def gradio_interface():
|
| 196 |
"""Create and return the Gradio interface."""
|
| 197 |
+
with gr.Blocks(js=js) as demo:
|
| 198 |
gr.Markdown("# Background Removal Arena")
|
| 199 |
button_name = "Difference between masks"
|
| 200 |
|
|
|
|
| 328 |
state_segmented_a, state_segmented_b, notice_markdown
|
| 329 |
]
|
| 330 |
)
|
| 331 |
+
|
| 332 |
|
| 333 |
def handle_zoom(current_image, zoomed_state_input, original_image, other_image, event: gr.SelectData):
|
| 334 |
"""Toggle between zoomed and original image based on click events."""
|
|
|
|
| 513 |
else:
|
| 514 |
logging.info("Not running in Hugging Face Spaces. Database dump scheduler not started.")
|
| 515 |
|
| 516 |
+
|
| 517 |
+
|
| 518 |
+
|
| 519 |
if __name__ == "__main__":
|
| 520 |
schedule_dump_database() # Start the periodic database dump
|
| 521 |
demo = gradio_interface()
|
| 522 |
+
|
| 523 |
demo.launch()
|
launch.sh
CHANGED
|
@@ -1,2 +1,2 @@
|
|
| 1 |
pip3 install -r requirements.txt
|
| 2 |
-
|
|
|
|
| 1 |
pip3 install -r requirements.txt
|
| 2 |
+
gradio app.py
|
requirements.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
certifi==2024.8.30
|
| 2 |
fastapi==0.115.4
|
| 3 |
-
gradio==5.
|
| 4 |
numpy==2.0.2
|
| 5 |
pandas==2.2.3
|
| 6 |
pillow==11.0.0
|
|
|
|
| 1 |
certifi==2024.8.30
|
| 2 |
fastapi==0.115.4
|
| 3 |
+
gradio==5.8.0
|
| 4 |
numpy==2.0.2
|
| 5 |
pandas==2.2.3
|
| 6 |
pillow==11.0.0
|