Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| from search import search_images_by_text, get_similar_images, search_images_by_image | |
| import requests | |
| from io import BytesIO | |
| def create_collection_url(row): | |
| base_url = "https://www.vogue.com/fashion-shows/" | |
| season = str(row["season"]).lower() | |
| year = str(row["year"]) | |
| category = str(row["category"]).lower() if pd.notna(row["category"]) and row["category"] and str(row["category"]).lower() != "nan" else None | |
| designer = str(row["designer"]).lower().replace(" ", "-") | |
| # Add city if available | |
| city = str(row["city"]).lower().replace(" ", "-") if pd.notna(row["city"]) and row["city"] and str(row["city"]).lower() != "nan" else None | |
| if pd.isna(category) or category is None or category == "nan": | |
| if city: | |
| return f"{base_url}{city}-{season}-{year}/{designer}" | |
| else: | |
| return f"{base_url}{season}-{year}/{designer}" | |
| else: | |
| if city: | |
| return f"{base_url}{city}-{season}-{year}-{category}/{designer}" | |
| else: | |
| return f"{base_url}{season}-{year}-{category}/{designer}" | |
| import requests | |
| from io import BytesIO | |
| #@st.cache_data(show_spinner="Loading FashionDB...") | |
| def load_data_hf(): | |
| # Load the Parquet file directly from Hugging Face | |
| df_url = "https://huggingface.co/datasets/traopia/vogue-runway/resolve/main/VogueRunway.parquet" | |
| df = pd.read_parquet(df_url) | |
| # Load the .npy file using requests | |
| npy_url = "https://huggingface.co/datasets/traopia/vogue-runway/resolve/main/VogueRunway_image.npy" | |
| response = requests.get(npy_url) | |
| response.raise_for_status() # Raise error if download fails | |
| embeddings = np.load(BytesIO(response.content)) | |
| df['collection'] = df.apply(create_collection_url, axis=1) | |
| return df, embeddings | |
| df, embeddings = load_data_hf() | |
| # Filter and search | |
| def filter_and_search(fashion_house, category, season, start_year, end_year, query): | |
| filtered = df.copy() | |
| if fashion_house: | |
| filtered = filtered[filtered['designer'].isin(fashion_house)] | |
| if category: | |
| filtered = filtered[filtered['category'].isin(category)] | |
| if season: | |
| filtered = filtered[filtered['season'].isin(season)] | |
| filtered = filtered[(filtered['year'] >= start_year) & (filtered['year'] <= end_year)] | |
| if query: | |
| results = search_images_by_text(query, filtered, embeddings) | |
| else: | |
| results = filtered.head(30) | |
| image_urls = results["url"].tolist() | |
| metadata = results.to_dict(orient="records") | |
| return image_urls, metadata | |
| # Display metadata and similar | |
| def show_metadata(idx, metadata): | |
| item = metadata[idx] | |
| out = "" | |
| for field in ["designer", "season", "year", "category"]: | |
| if field in item and pd.notna(item[field]): | |
| out += f"**{field.title()}**: {item[field]}\n" | |
| if 'collection' in item and pd.notna(item['collection']): | |
| out += f"\n[View Collection]({item['collection']})" | |
| return out | |
| def find_similar(idx, metadata): | |
| if not isinstance(idx, int) or idx >= len(metadata) or idx < 0: | |
| return [] # or gr.update(visible=False) | |
| key = metadata[idx]["key"] | |
| similar_df = get_similar_images(df, key, embeddings, top_k=5) | |
| return similar_df["url"].tolist(), similar_df.to_dict(orient="records") | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 👗 FashionDB Explorer") | |
| with gr.Tabs(): | |
| # TEXT SEARCH TAB | |
| with gr.Tab("Search by Text"): | |
| with gr.Row(): | |
| fashion_house = gr.Dropdown(label="Fashion House", choices=sorted(df["designer"].dropna().unique()), multiselect=True) | |
| category = gr.Dropdown(label="Category", choices=sorted(df["category"].dropna().unique()), multiselect=True) | |
| season = gr.Dropdown(label="Season", choices=sorted(df["season"].dropna().unique()), multiselect=True) | |
| min_year = int(df['year'].min()) | |
| max_year = int(df['year'].max()) | |
| start_year = gr.Slider(label="Start Year", minimum=min_year, maximum=max_year, value=2000, step=1) | |
| end_year = gr.Slider(label="End Year", minimum=min_year, maximum=max_year, value=2024, step=1) | |
| query = gr.Textbox(label="Search by text", placeholder="e.g., pink dress") | |
| search_button = gr.Button("Search") | |
| result_gallery = gr.Gallery(label="Search Results", columns=5, height="auto") | |
| metadata_output = gr.Markdown() | |
| reference_image = gr.Image(label="Reference Image", interactive=False) | |
| similar_gallery = gr.Gallery(label="Similar Images", columns=5, height="auto") | |
| metadata_state = gr.State([]) | |
| selected_idx = gr.Number(value=0, visible=False) | |
| def handle_search(fh, cat, sea, sy, ey, q): | |
| imgs, meta = filter_and_search(fh, cat, sea, sy, ey, q) | |
| return imgs, meta, "", [], None | |
| search_button.click( | |
| handle_search, | |
| inputs=[fashion_house, category, season, start_year, end_year, query], | |
| outputs=[result_gallery, metadata_state, metadata_output, similar_gallery, reference_image] | |
| ) | |
| def handle_click(evt: gr.SelectData, metadata): | |
| idx = evt.index | |
| md = show_metadata(idx, metadata) | |
| img_path = metadata[idx]["url"] | |
| return idx, md, img_path | |
| result_gallery.select( | |
| handle_click, | |
| inputs=[metadata_state], | |
| outputs=[selected_idx, metadata_output, reference_image] | |
| ) | |
| def show_similar(idx, metadata): | |
| if idx is None or not str(idx).isdigit(): | |
| return [], [] | |
| return find_similar(int(idx), metadata) | |
| similar_metadata_state = gr.State() | |
| similar_metadata_output = gr.Markdown() | |
| show_similar_button = gr.Button("Show Similar Images") | |
| show_similar_button.click( | |
| show_similar, | |
| inputs=[selected_idx, metadata_state], | |
| outputs=[similar_gallery, similar_metadata_state] | |
| ) | |
| def handle_similar_click(evt: gr.SelectData, metadata): | |
| idx = evt.index | |
| md = show_metadata(idx, metadata) | |
| img_path = metadata[idx]["url"] | |
| return idx, md, img_path | |
| similar_gallery.select( | |
| handle_similar_click, | |
| inputs=[similar_metadata_state], | |
| outputs=[selected_idx, similar_metadata_output, reference_image] | |
| ) | |
| # IMAGE SEARCH TAB | |
| with gr.Tab("Search by Image"): | |
| with gr.Row(): | |
| fashion_house_img = gr.Dropdown(label="Fashion House", choices=sorted(df["designer"].dropna().unique()), multiselect=True) | |
| category_img = gr.Dropdown(label="Category", choices=sorted(df["category"].dropna().unique()), multiselect=True) | |
| season_img = gr.Dropdown(label="Season", choices=sorted(df["season"].dropna().unique()), multiselect=True) | |
| start_year_img = gr.Slider(label="Start Year", minimum=min_year, maximum=max_year, value=2000, step=1) | |
| end_year_img = gr.Slider(label="End Year", minimum=min_year, maximum=max_year, value=2024, step=1) | |
| uploaded_image = gr.Image(label="Upload an image", type="pil") | |
| search_by_image_button = gr.Button("Search by Image") | |
| uploaded_result_gallery = gr.Gallery(label="Search Results by Image", columns=5, height="auto") | |
| uploaded_metadata_state = gr.State([]) | |
| uploaded_metadata_output = gr.Markdown() | |
| uploaded_reference_image = gr.Image(label="Reference Image", interactive=False) | |
| def handle_search_by_image(image, fh, cat, sea, sy, ey): | |
| if image is None: | |
| return [], "Please upload an image first.", None | |
| # Apply filters | |
| filtered_df = df.copy() | |
| if fh: filtered_df = filtered_df[filtered_df["designer"].isin(fh)] | |
| if cat: filtered_df = filtered_df[filtered_df["category"].isin(cat)] | |
| if sea: filtered_df = filtered_df[filtered_df["season"].isin(sea)] | |
| filtered_df = filtered_df[(filtered_df["year"] >= sy) & (filtered_df["year"] <= ey)] | |
| results_df = search_images_by_image(image, filtered_df, embeddings) | |
| images = results_df['url'].tolist() | |
| metadata = results_df.to_dict(orient="records") | |
| return images, metadata, "" | |
| search_by_image_button.click( | |
| handle_search_by_image, | |
| inputs=[uploaded_image, fashion_house_img, category_img, season_img, start_year_img, end_year_img], | |
| outputs=[uploaded_result_gallery, uploaded_metadata_state, uploaded_metadata_output] | |
| ) | |
| uploaded_selected_idx = gr.Number(visible=False) | |
| def handle_uploaded_click(evt: gr.SelectData, metadata): | |
| idx = evt.index | |
| md = show_metadata(idx, metadata) | |
| img_path = metadata[idx]["url"] | |
| return idx, md, img_path | |
| uploaded_result_gallery.select( | |
| handle_uploaded_click, | |
| inputs=[uploaded_metadata_state], | |
| outputs=[uploaded_selected_idx, uploaded_metadata_output, uploaded_reference_image] | |
| ) | |
| # SIMILAR IMAGE SEARCH FOR IMAGE TAB | |
| uploaded_similar_gallery = gr.Gallery(label="Similar Images", columns=5, height="auto") | |
| uploaded_similar_metadata_state = gr.State([]) | |
| uploaded_similar_metadata_output = gr.Markdown() | |
| uploaded_show_similar_button = gr.Button("Show Similar Images") | |
| def show_similar_uploaded(idx, metadata): | |
| if idx is None or not str(idx).isdigit(): | |
| return [], [] | |
| return find_similar(int(idx), metadata) | |
| uploaded_show_similar_button.click( | |
| show_similar_uploaded, | |
| inputs=[uploaded_selected_idx, uploaded_metadata_state], | |
| outputs=[uploaded_similar_gallery, uploaded_similar_metadata_state] | |
| ) | |
| def handle_uploaded_similar_click(evt: gr.SelectData, metadata): | |
| idx = evt.index | |
| md = show_metadata(idx, metadata) | |
| img_path = metadata[idx]["url"] | |
| return idx, md, img_path | |
| uploaded_similar_gallery.select( | |
| handle_uploaded_similar_click, | |
| inputs=[uploaded_similar_metadata_state], | |
| outputs=[uploaded_selected_idx, uploaded_similar_metadata_output, uploaded_reference_image] | |
| ) | |
| uploaded_back_button = gr.Button("Back to Initial Uploaded Search") | |
| def back_to_uploaded_home(): | |
| return [], "", None | |
| uploaded_back_button.click( | |
| back_to_uploaded_home, | |
| outputs=[uploaded_similar_gallery, uploaded_similar_metadata_output, uploaded_reference_image] | |
| ) | |
| with gr.Tab("Query on FashionDB"): | |
| with gr.Row(): | |
| gr.Markdown( | |
| "### 🔗 Query FashionDB SPARQL Endpoint\n" | |
| "[Click here to open the SPARQL endpoint](https://fashionwiki.wikibase.cloud/query/)", | |
| elem_id="sparql-link" | |
| ) | |
| back_button = gr.Button("Back to Home") | |
| def back_to_home(): | |
| return [], "", None # clear similar_gallery, metadata_output, reference image | |
| back_button.click( | |
| back_to_home, | |
| outputs=[similar_gallery, similar_metadata_output, reference_image] | |
| ) | |
| demo.launch() |