|
import gradio as gr |
|
import requests |
|
import json |
|
from PIL import Image |
|
import io |
|
|
|
|
|
BASE_URL = "https://collectionapi.metmuseum.org/public/collection/v1" |
|
|
|
def get_departments(): |
|
"""Get all departments from the Met API""" |
|
response = requests.get(f"{BASE_URL}/departments") |
|
return response.json()['departments'] |
|
|
|
def search_artworks(query, department_id=None, is_highlight=False, has_images=True, |
|
is_on_view=False, medium=None, geo_location=None): |
|
"""Search artworks with various filters""" |
|
search_url = f"{BASE_URL}/search" |
|
params = { |
|
'q': query, |
|
'hasImages': has_images, |
|
'isHighlight': is_highlight, |
|
'isOnView': is_on_view |
|
} |
|
|
|
if department_id: |
|
params['departmentId'] = department_id |
|
if medium: |
|
params['medium'] = medium |
|
if geo_location: |
|
params['geoLocation'] = geo_location |
|
|
|
try: |
|
|
|
response = requests.get(search_url, params=params) |
|
results = response.json() |
|
|
|
if not results.get('objectIDs'): |
|
return [], "No results found." |
|
|
|
|
|
object_ids = results['objectIDs'][:12] |
|
|
|
images = [] |
|
captions = [] |
|
|
|
|
|
for object_id in object_ids: |
|
object_url = f"{BASE_URL}/objects/{object_id}" |
|
object_response = requests.get(object_url) |
|
artwork = object_response.json() |
|
|
|
if artwork.get('primaryImage'): |
|
try: |
|
img_response = requests.get(artwork['primaryImage'], timeout=10) |
|
img = Image.open(io.BytesIO(img_response.content)) |
|
|
|
if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info): |
|
img = img.convert('RGB') |
|
|
|
artwork_info = f""" |
|
Title: {artwork.get('title', 'Unknown')} |
|
Artist: {artwork.get('artistDisplayName', 'Unknown')} |
|
Date: {artwork.get('objectDate', 'Unknown')} |
|
Medium: {artwork.get('medium', 'Unknown')} |
|
Department: {artwork.get('department', 'Unknown')} |
|
""" |
|
|
|
images.append(img) |
|
captions.append(artwork_info) |
|
except Exception as e: |
|
print(f"Error processing image for object {object_id}: {e}") |
|
continue |
|
|
|
return images, "\n\n".join(captions) |
|
|
|
except Exception as e: |
|
return [], f"An error occurred: {str(e)}" |
|
|
|
|
|
custom_css = """ |
|
.gradio-container { |
|
background: linear-gradient(135deg, #1a1a1a, #2d2d2d) !important; |
|
color: #ffffff !important; |
|
} |
|
.gr-button { |
|
background: linear-gradient(135deg, #8e2de2, #4a00e0) !important; |
|
border: none !important; |
|
color: white !important; |
|
font-weight: bold !important; |
|
padding: 10px 20px !important; |
|
font-size: 1.1em !important; |
|
box-shadow: 0 4px 15px rgba(0,0,0,0.2) !important; |
|
} |
|
.gr-button:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 6px 20px rgba(0,0,0,0.3) !important; |
|
transition: all 0.3s ease; |
|
} |
|
.gr-input, .gr-select { |
|
border: 2px solid #4a00e0 !important; |
|
background: rgba(255, 255, 255, 0.1) !important; |
|
color: white !important; |
|
font-size: 1.1em !important; |
|
border-radius: 8px !important; |
|
} |
|
.gr-gallery { |
|
background: rgba(0, 0, 0, 0.3) !important; |
|
border-radius: 15px !important; |
|
padding: 20px !important; |
|
min-height: 800px !important; |
|
box-shadow: 0 8px 32px rgba(0,0,0,0.3) !important; |
|
} |
|
.title-text { |
|
text-align: center !important; |
|
color: #ffffff !important; |
|
font-size: 2.8em !important; |
|
margin-bottom: 0.3em !important; |
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.5) !important; |
|
font-weight: bold !important; |
|
} |
|
.subtitle-text { |
|
text-align: center !important; |
|
color: #cccccc !important; |
|
font-size: 1.3em !important; |
|
margin-bottom: 2em !important; |
|
font-style: italic !important; |
|
text-shadow: 1px 1px 2px rgba(0,0,0,0.3) !important; |
|
} |
|
""" |
|
|
|
|
|
departments = get_departments() |
|
department_choices = {dept['displayName']: dept['departmentId'] for dept in departments} |
|
|
|
|
|
with gr.Blocks(css=custom_css) as demo: |
|
gr.HTML( |
|
""" |
|
<div class="title-text">🎨 The Met Art Explorer</div> |
|
<div class="subtitle-text">Explore over 5,000 years of art from The Metropolitan Museum of Art's collection</div> |
|
""" |
|
) |
|
gr.HTML("""<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fimmunobiotech-MetropolitanMuseum.hf.space"> |
|
<img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fimmunobiotech-MetropolitanMuseum.hf.space&countColor=%23263759" /> |
|
</a>""") |
|
with gr.Row(): |
|
with gr.Column(scale=3): |
|
search_input = gr.Textbox( |
|
label="Search artwork", |
|
placeholder="Enter keywords (e.g., sunflowers, portrait, landscape...)" |
|
) |
|
with gr.Column(scale=2): |
|
department_dropdown = gr.Dropdown( |
|
choices=list(department_choices.keys()), |
|
label="Department", |
|
value=None |
|
) |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
highlight_checkbox = gr.Checkbox(label="Show Highlights Only", value=False) |
|
on_view_checkbox = gr.Checkbox(label="Currently On View", value=False) |
|
with gr.Column(): |
|
medium_input = gr.Textbox( |
|
label="Medium", |
|
placeholder="e.g., Paintings, Sculpture, Ceramics" |
|
) |
|
location_input = gr.Textbox( |
|
label="Geographic Location", |
|
placeholder="e.g., France, Japan, Egypt" |
|
) |
|
|
|
search_btn = gr.Button("🔍 Search Collection", variant="primary") |
|
|
|
gallery = gr.Gallery( |
|
label="Search Results", |
|
show_label=True, |
|
elem_id="gallery", |
|
columns=3, |
|
rows=4, |
|
height="800px", |
|
object_fit="contain" |
|
) |
|
|
|
info = gr.Textbox( |
|
label="Artwork Details", |
|
lines=10, |
|
show_label=True |
|
) |
|
|
|
def handle_search(query, dept, highlight, on_view, medium, location): |
|
dept_id = department_choices.get(dept) if dept else None |
|
return search_artworks(query, dept_id, highlight, True, on_view, medium, location) |
|
|
|
search_btn.click( |
|
fn=handle_search, |
|
inputs=[search_input, department_dropdown, highlight_checkbox, |
|
on_view_checkbox, medium_input, location_input], |
|
outputs=[gallery, info] |
|
) |
|
|
|
demo.launch() |