Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import numpy as np | |
| import pandas as pd | |
| import torch | |
| from transformers import CLIPProcessor, CLIPModel | |
| from sklearn.metrics.pairwise import cosine_similarity | |
| from datasets import load_dataset | |
| # Load model | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| model_name = "openai/clip-vit-base-patch32" | |
| model = CLIPModel.from_pretrained(model_name).to(device) | |
| processor = CLIPProcessor.from_pretrained(model_name) | |
| # Load embeddings | |
| df = pd.read_parquet("nature_embeddings.parquet") | |
| EMBEDDINGS_MATRIX = np.array(df['embedding'].tolist()) | |
| CAPTIONS = df['caption'].tolist() | |
| ORIGINAL_INDICES = df['original_index'].tolist() | |
| # Load dataset | |
| dataset = load_dataset("mertcobanov/nature-dataset") | |
| train_data = dataset['train'] | |
| def classify_scene(caption): | |
| """Classify nature scene based on caption keywords""" | |
| caption = caption.lower() | |
| if any(w in caption for w in ['beach', 'ocean', 'sea', 'coast', 'wave']): | |
| return 'π Coastal' | |
| elif any(w in caption for w in ['waterfall', 'stream', 'river', 'lake']): | |
| return 'π§ Water' | |
| elif any(w in caption for w in ['mountain', 'peak', 'cliff', 'rock']): | |
| return 'ποΈ Mountain' | |
| elif any(w in caption for w in ['desert', 'dune', 'sand', 'arid']): | |
| return 'ποΈ Desert' | |
| elif any(w in caption for w in ['forest', 'tree', 'jungle', 'wood']): | |
| return 'π² Forest' | |
| else: | |
| return 'πΏ Nature' | |
| def get_image_embedding(image): | |
| inputs = processor(images=image, return_tensors="pt", padding=True).to(device) | |
| with torch.no_grad(): | |
| outputs = model.vision_model(**inputs) | |
| features = outputs.pooler_output | |
| features = torch.nn.functional.normalize(features, p=2, dim=-1) | |
| return features.cpu().numpy() | |
| def recommend(image): | |
| query_embedding = get_image_embedding(image) | |
| similarities = cosine_similarity(query_embedding, EMBEDDINGS_MATRIX)[0] | |
| top_indices = np.argsort(similarities)[::-1] | |
| top_indices = [idx for idx in top_indices if similarities[idx] < 0.9999][:3] | |
| results = [] | |
| for idx in top_indices: | |
| original_idx = ORIGINAL_INDICES[idx] | |
| img = train_data[int(original_idx)]['image'] | |
| cap = CAPTIONS[idx] | |
| sim = float(similarities[idx]) | |
| scene = classify_scene(cap) | |
| results.append((img, f"{scene} | {cap} (similarity: {sim:.4f})")) | |
| return results[0][0], results[0][1], results[1][0], results[1][1], results[2][0], results[2][1] | |
| # Gradio interface | |
| with gr.Blocks(title="Nature Scene Recommender") as demo: | |
| gr.Markdown("# πΏ Nature Scene Recommender") | |
| gr.Markdown("Upload a nature image and get the 3 most similar scenes!") | |
| with gr.Row(): | |
| input_image = gr.Image(type="pil", label="Upload Nature Image") | |
| btn = gr.Button("Find Similar Scenes π", variant="primary") | |
| gr.Markdown("### Top 3 Similar Scenes") | |
| with gr.Row(): | |
| img1 = gr.Image(label="Match #1") | |
| img2 = gr.Image(label="Match #2") | |
| img3 = gr.Image(label="Match #3") | |
| with gr.Row(): | |
| cap1 = gr.Textbox(label="Scene #1") | |
| cap2 = gr.Textbox(label="Scene #2") | |
| cap3 = gr.Textbox(label="Scene #3") | |
| btn.click(fn=recommend, inputs=input_image, | |
| outputs=[img1, cap1, img2, cap2, img3, cap3]) | |
| demo.launch(server_name="0.0.0.0", server_port=7860) |