File size: 3,276 Bytes
c086220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1619535
c086220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import gradio as gr
from transformers import AutoImageProcessor, AutoModel
import torch
from PIL import Image
import os
import json
import uuid
import numpy as np

# Загрузка модели DINOv2
processor = AutoImageProcessor.from_pretrained("facebook/dino-vits16")
model = AutoModel.from_pretrained("facebook/dino-vits16")

# Функция для извлечения эмбеддинга
def extract_features(img):
    inputs = processor(images=img, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**inputs)
    return outputs.last_hidden_state[:, 0].squeeze().numpy()

# Косинусное расстояние между двумя эмбеддингами
def cosine_similarity(vec1, vec2):
    a = np.array(vec1)
    b = np.array(vec2)
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# Путь к базе
db_path = "embeddings2.json"

# Сохранение фото в базу
def save_embedding(image, building_name):
    if not building_name:
        return "Ошибка: нужно указать название здания."
    
    embedding = extract_features(image).tolist()
    entry = {
        "id": str(uuid.uuid4()),
        "building_name": building_name,
        "embedding": embedding
    }

    if os.path.exists(db_path):
        with open(db_path, "r") as f:
            data = json.load(f)
    else:
        data = []

    data.append(entry)

    with open(db_path, "w") as f:
        json.dump(data, f, indent=2)

    return f"Фото сохранено для здания: {building_name}"

# Поиск похожего здания
def identify_building(image):
    if not os.path.exists(db_path):
        return "База данных пуста. Добавьте здания."

    with open(db_path, "r") as f:
        data = json.load(f)

    if not data:
        return "База данных пуста."

    embedding = extract_features(image).tolist()

    similarities = []
    for item in data:
        score = cosine_similarity(item["embedding"], embedding)
        similarities.append({
            "building_name": item["building_name"],
            "score": score
        })

    similarities.sort(key=lambda x: x["score"], reverse=True)
    best = similarities[0]

    return f"Похоже на: {best['building_name']}\nСовпадение: {best['score']:.4f}"

# Интерфейс
with gr.Blocks() as demo:
    gr.Markdown("## 🏛 Распознавание зданий и пополнение базы")

    with gr.Tab("🔍 Найти здание"):
        with gr.Row():
            img_input = gr.Image(type="pil")
            recognize_button = gr.Button("Распознать здание")
        result_text = gr.Textbox()
        recognize_button.click(fn=identify_building, inputs=img_input, outputs=result_text)

    with gr.Tab("➕ Добавить новое здание"):
        with gr.Row():
            img_save = gr.Image(type="pil")
            building_name = gr.Textbox(label="Название здания")
            save_button = gr.Button("Сохранить в базу")
        save_result = gr.Textbox()
        save_button.click(fn=save_embedding, inputs=[img_save, building_name], outputs=save_result)

demo.launch()