ziffir commited on
Commit
9dbebec
·
verified ·
1 Parent(s): 75a02ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +326 -92
app.py CHANGED
@@ -1,140 +1,374 @@
1
- # app.py - Hafif Jeo-Referanslama Demo
2
- import gradio as gr
3
- import requests
 
 
 
4
  from PIL import Image
5
- import json
6
- import tempfile
 
7
  import folium
 
8
  import os
 
 
9
 
10
- class LightweightGeoDemo:
11
  def __init__(self):
12
- self.dataset_info = {
13
- 'name': 'allenai/s2-naip',
14
- 'description': 'Sentinel-2 ve NAIP görüntü çiftleri'
15
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- def predict_coordinates(self, image):
18
- """Basit koordinat tahmini (demo amaçlı)"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  try:
20
- # Demo için rastgele koordinatlar
21
- import random
22
- lat = random.uniform(36.0, 42.0) # Türkiye enlemleri
23
- lon = random.uniform(26.0, 45.0) # Türkiye boylamları
24
-
25
- # Görüntü boyutuna göre basit güven skoru
26
- if hasattr(image, 'size'):
27
- confidence = min(0.8, image.size[0] / 1000 * 0.1)
28
- else:
29
- confidence = 0.5
30
-
31
- result = {
32
- 'latitude': round(lat, 4),
33
- 'longitude': round(lon, 4),
34
- 'confidence': round(confidence, 2),
35
- 'location': 'Türkiye',
36
- 'method': 'Demo Tahmini'
37
- }
38
-
39
- return result
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  except Exception as e:
42
  return {'error': str(e)}
43
 
44
- def create_simple_map(self, lat, lon):
45
- """Basit harita oluştur"""
 
 
 
 
 
 
 
 
 
 
 
46
  try:
47
- # Folium haritası
48
  m = folium.Map(location=[lat, lon], zoom_start=10)
49
-
50
- # Marker ekle
51
  folium.Marker(
52
  [lat, lon],
53
  popup=f'Tahmin: {lat}, {lon}',
54
  tooltip='Tahmin Edilen Konum'
55
  ).add_to(m)
56
 
57
- # Geçici dosyaya kaydet
58
  with tempfile.NamedTemporaryFile(suffix='.html', delete=False) as tmp:
59
  m.save(tmp.name)
60
  return tmp.name
61
  except Exception as e:
 
62
  return None
63
 
64
- def create_demo_interface():
65
- demo = LightweightGeoDemo()
 
66
 
67
- with gr.Blocks(title="🌍 Jeo-Referanslama Demo", theme=gr.themes.Soft()) as interface:
68
  gr.Markdown("""
69
- # 🌍 Jeo-Referanslama Demo
70
- **Hafif AI destekli koordinat tahmini sistemi**
71
 
72
- Bu demo, S2-NAIP dataseti için geliştirilmiş jeo-referanslama sisteminin basit bir versiyonudur.
73
  """)
74
 
75
- with gr.Row():
76
- with gr.Column():
77
- image_input = gr.Image(
78
- type="filepath",
79
- label="Uydu Görüntüsü Yükle",
80
- height=300
81
- )
82
- predict_btn = gr.Button("📍 Koordinatları Tahmin Et", variant="primary")
83
-
84
- with gr.Column():
85
- output_json = gr.JSON(label="Tahmin Sonuçları")
86
- output_map = gr.HTML(label="Harita Görünümü")
87
-
88
- # Örnek görüntüler
89
- gr.Markdown("### 📸 Örnek Görüntüler")
90
- with gr.Row():
91
- gr.Examples(
92
- examples=[
93
- ["https://raw.githubusercontent.com/usc-isi-i2/datasets/master/s2-NAIP/sample_images/sentinel_sample1.jpg"],
94
- ["https://raw.githubusercontent.com/usc-isi-i2/datasets/master/s2-NAIP/sample_images/naip_sample1.jpg"]
95
- ],
 
 
 
 
 
 
96
  inputs=image_input,
97
- label="Örnek Görüntüler"
98
  )
99
 
100
- # Dataset bilgisi
101
- with gr.Accordion("ℹ️ Dataset Bilgisi", open=False):
102
- gr.Markdown(f"""
103
- **Kullanılan Dataset:** {demo.dataset_info['name']}
 
 
 
 
 
 
104
 
105
- **Açıklama:** {demo.dataset_info['description']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
  **Özellikler:**
108
  - Sentinel-2 (10m çözünürlük) görüntüleri
109
- - NAIP (1m çözünürlük) görüntüleri
110
  - Koordinat metadata'sı
111
  - ABD genelinde çeşitli lokasyonlar
112
 
113
- **Not:** Bu demo basit tahminler yapar. Tam model eğitimi gereklidir.
 
 
 
 
 
 
 
 
114
  """)
 
 
 
 
 
 
115
 
116
- # Tahmin butonu işlevi
117
- def process_prediction(image):
118
- result = demo.predict_coordinates(image)
119
- if 'error' not in result:
120
- map_path = demo.create_simple_map(result['latitude'], result['longitude'])
121
- if map_path:
122
- with open(map_path, 'r') as f:
123
- map_html = f.read()
124
- os.unlink(map_path) # Temizlik
125
- return result, map_html
126
- return result, "<p>Harita oluşturulamadı</p>"
127
-
128
- predict_btn.click(
129
- fn=process_prediction,
130
- inputs=image_input,
131
- outputs=[output_json, output_map]
132
- )
133
 
134
- return interface
135
 
136
  if __name__ == "__main__":
137
- demo = create_demo_interface()
138
  demo.launch(
139
  server_name="0.0.0.0",
140
  server_port=7860,
 
1
+ # app.py - Orta Ölçek Jeo-Referanslama
2
+ import torch
3
+ import torch.nn as nn
4
+ from transformers import AutoModel, AutoImageProcessor
5
+ from datasets import load_dataset
6
+ import torchvision.transforms as transforms
7
  from PIL import Image
8
+ import numpy as np
9
+ import gradio as gr
10
+ import matplotlib.pyplot as plt
11
  import folium
12
+ import tempfile
13
  import os
14
+ from tqdm import tqdm
15
+ import json
16
 
17
+ class MediumScaleGeoSystem:
18
  def __init__(self):
19
+ self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
20
+ print(f"Cihaz: {self.device}")
21
+
22
+ # Hafif model - DINOv2-small
23
+ self.model_name = "facebook/dinov2-small"
24
+ self.processor = AutoImageProcessor.from_pretrained(self.model_name)
25
+ self.backbone = AutoModel.from_pretrained(self.model_name).to(self.device)
26
+
27
+ # Regression head
28
+ self.regressor = nn.Sequential(
29
+ nn.Linear(384, 256), # small model 384 feature
30
+ nn.ReLU(),
31
+ nn.Dropout(0.2),
32
+ nn.Linear(256, 128),
33
+ nn.ReLU(),
34
+ nn.Linear(128, 2) # lat, lon
35
+ ).to(self.device)
36
+
37
+ self.transform = transforms.Compose([
38
+ transforms.Resize((224, 224)),
39
+ transforms.ToTensor(),
40
+ transforms.Normalize(mean=[0.485, 0.456, 0.406],
41
+ std=[0.229, 0.224, 0.225])
42
+ ])
43
+
44
+ # Dataset cache - sadece küçük kısmı
45
+ self.dataset = None
46
+ self.load_medium_dataset()
47
+
48
+ def load_medium_dataset(self, num_samples=2000):
49
+ """Orta ölçekte dataset yükle (1-2GB)"""
50
+ try:
51
+ print(f"{num_samples} örnek yükleniyor...")
52
+ self.dataset = load_dataset(
53
+ "allenai/s2-naip",
54
+ split=f"train[:{num_samples}]",
55
+ streaming=False # Küçük olduğu için memory'de tut
56
+ )
57
+ print(f"Dataset yüklendi: {len(self.dataset)} örnek")
58
+
59
+ # Dataset istatistikleri
60
+ self.analyze_dataset()
61
+
62
+ except Exception as e:
63
+ print(f"Dataset yükleme hatası: {e}")
64
+ self.dataset = None
65
+
66
+ def analyze_dataset(self):
67
+ """Dataset analizi"""
68
+ if self.dataset is None:
69
+ return
70
+
71
+ print("\n=== Dataset Analizi ===")
72
+ print(f"Toplam örnek: {len(self.dataset)}")
73
+
74
+ # Koordinat istatistikleri
75
+ lats, lons = [], []
76
+ for i in range(min(100, len(self.dataset))):
77
+ sample = self.dataset[i]
78
+ if 'lat' in sample and 'lon' in sample:
79
+ lats.append(sample['lat'])
80
+ lons.append(sample['lon'])
81
+
82
+ if lats:
83
+ print(f"Enlem aralığı: {min(lats):.2f} - {max(lats):.2f}")
84
+ print(f"Boylam aralığı: {min(lons):.2f} - {max(lons):.2f}")
85
+ print(f"Koordinatlı örnek: {len(lats)}")
86
+
87
+ def prepare_training_data(self, num_samples=1000):
88
+ """Eğitim verisi hazırla"""
89
+ if self.dataset is None:
90
+ return None, None
91
+
92
+ images = []
93
+ coordinates = []
94
+
95
+ print("Eğitim verisi hazırlanıyor...")
96
+ for i in tqdm(range(min(num_samples, len(self.dataset)))):
97
+ sample = self.dataset[i]
98
+
99
+ try:
100
+ # Sentinel-2 görüntüsünü kullan
101
+ img = sample['sentinel']
102
+ if img.mode != 'RGB':
103
+ img = img.convert('RGB')
104
+
105
+ img_tensor = self.transform(img)
106
+ images.append(img_tensor)
107
+
108
+ # Koordinatları normalize et
109
+ lat = sample.get('lat', 0.0)
110
+ lon = sample.get('lon', 0.0)
111
+
112
+ # Normalize: [-90,90] -> [-1,1], [-180,180] -> [-1,1]
113
+ lat_norm = lat / 90.0
114
+ lon_norm = lon / 180.0
115
+
116
+ coordinates.append([lat_norm, lon_norm])
117
+
118
+ except Exception as e:
119
+ continue
120
+
121
+ if len(images) == 0:
122
+ return None, None
123
+
124
+ images_tensor = torch.stack(images)
125
+ coords_tensor = torch.tensor(coordinates, dtype=torch.float32)
126
+
127
+ print(f"Eğitim verisi: {len(images_tensor)} örnek")
128
+ return images_tensor, coords_tensor
129
 
130
+ def train(self, epochs=3, batch_size=16, learning_rate=1e-4):
131
+ """Model eğitimi"""
132
+ if self.dataset is None:
133
+ return {"error": "Dataset yüklenemedi"}
134
+
135
+ # Eğitim verisini hazırla
136
+ images, coords = self.prepare_training_data(800) # 800 örnekle eğit
137
+ if images is None:
138
+ return {"error": "Eğitim verisi hazırlanamadı"}
139
+
140
+ # Optimizer
141
+ optimizer = torch.optim.AdamW(
142
+ list(self.regressor.parameters()) + list(self.backbone.parameters()),
143
+ lr=learning_rate,
144
+ weight_decay=1e-4
145
+ )
146
+ criterion = nn.MSELoss()
147
+
148
+ losses = []
149
+ self.backbone.train()
150
+ self.regressor.train()
151
+
152
+ print("Model eğitimi başlıyor...")
153
+ for epoch in range(epochs):
154
+ epoch_loss = 0
155
+ num_batches = 0
156
+
157
+ for i in range(0, len(images), batch_size):
158
+ batch_images = images[i:i+batch_size].to(self.device)
159
+ batch_coords = coords[i:i+batch_size].to(self.device)
160
+
161
+ # Forward pass
162
+ optimizer.zero_grad()
163
+
164
+ # Özellik çıkarımı
165
+ features = self.backbone(batch_images).last_hidden_state
166
+ features = features.mean(dim=1)
167
+
168
+ # Tahmin
169
+ pred_coords = self.regressor(features)
170
+ loss = criterion(pred_coords, batch_coords)
171
+
172
+ # Backward pass
173
+ loss.backward()
174
+ optimizer.step()
175
+
176
+ epoch_loss += loss.item()
177
+ num_batches += 1
178
+
179
+ avg_loss = epoch_loss / num_batches if num_batches > 0 else 0
180
+ losses.append(avg_loss)
181
+ print(f"Epoch {epoch+1}/{epochs}, Loss: {avg_loss:.6f}")
182
+
183
+ # Modeli kaydet
184
+ self.save_model()
185
+ return {"success": True, "final_loss": avg_loss, "losses": losses}
186
+
187
+ def predict(self, image):
188
+ """Görüntüden koordinat tahmini"""
189
  try:
190
+ # Görüntüyü işle
191
+ if isinstance(image, str):
192
+ image = Image.open(image).convert('RGB')
193
+ elif isinstance(image, np.ndarray):
194
+ image = Image.fromarray(image.astype('uint8')).convert('RGB')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
+ image_tensor = self.transform(image).unsqueeze(0).to(self.device)
197
+
198
+ with torch.no_grad():
199
+ self.backbone.eval()
200
+ self.regressor.eval()
201
+
202
+ # Özellik çıkarımı
203
+ features = self.backbone(image_tensor).last_hidden_state
204
+ features = features.mean(dim=1)
205
+
206
+ # Tahmin
207
+ pred_coords = self.regressor(features)
208
+ pred_coords = pred_coords.cpu().numpy()[0]
209
+
210
+ # Gerçek koordinatlara dönüştür
211
+ lat = pred_coords[0] * 90.0
212
+ lon = pred_coords[1] * 180.0
213
+
214
+ # Basit güven skoru
215
+ confidence = max(0.1, 1.0 - (abs(pred_coords[0]) + abs(pred_coords[1])) / 2)
216
+
217
+ result = {
218
+ 'latitude': round(lat, 4),
219
+ 'longitude': round(lon, 4),
220
+ 'confidence': round(confidence, 2),
221
+ 'model': 'DINOv2-small',
222
+ 'dataset_samples': len(self.dataset) if self.dataset else 0
223
+ }
224
+
225
+ return result
226
+
227
  except Exception as e:
228
  return {'error': str(e)}
229
 
230
+ def save_model(self):
231
+ """Modeli kaydet"""
232
+ try:
233
+ torch.save({
234
+ 'regressor_state_dict': self.regressor.state_dict(),
235
+ 'backbone_state_dict': self.backbone.state_dict(),
236
+ }, 'medium_geo_model.pth')
237
+ print("Model kaydedildi: medium_geo_model.pth")
238
+ except Exception as e:
239
+ print(f"Model kaydetme hatası: {e}")
240
+
241
+ def create_map(self, lat, lon):
242
+ """Harita oluştur"""
243
  try:
 
244
  m = folium.Map(location=[lat, lon], zoom_start=10)
 
 
245
  folium.Marker(
246
  [lat, lon],
247
  popup=f'Tahmin: {lat}, {lon}',
248
  tooltip='Tahmin Edilen Konum'
249
  ).add_to(m)
250
 
 
251
  with tempfile.NamedTemporaryFile(suffix='.html', delete=False) as tmp:
252
  m.save(tmp.name)
253
  return tmp.name
254
  except Exception as e:
255
+ print(f"Harita oluşturma hatası: {e}")
256
  return None
257
 
258
+ # Gradio Arayüzü
259
+ def create_interface():
260
+ geo_system = MediumScaleGeoSystem()
261
 
262
+ with gr.Blocks(title="🌍 Orta Ölçek Jeo-Referanslama", theme=gr.themes.Soft()) as demo:
263
  gr.Markdown("""
264
+ # 🌍 Orta Ölçek Jeo-Referanslama
265
+ **S2-NAIP datasetinin 2000 örneği ile AI koordinat tahmini**
266
 
267
+ Bu sistem, 5GB'lık S2-NAIP datasetinin küçük bir kısmını kullanarak eğitilmiştir.
268
  """)
269
 
270
+ with gr.Tab("🎯 Tekil Tahmin"):
271
+ with gr.Row():
272
+ with gr.Column():
273
+ image_input = gr.Image(
274
+ type="filepath",
275
+ label="Uydu Görüntüsü Yükle",
276
+ height=300
277
+ )
278
+ predict_btn = gr.Button("📍 Koordinatları Tahmin Et", variant="primary")
279
+
280
+ with gr.Column():
281
+ output_json = gr.JSON(label="Tahmin Sonuçları")
282
+ map_output = gr.HTML(label="Harita Görünümü")
283
+
284
+ def process_prediction(image):
285
+ result = geo_system.predict(image)
286
+ if 'error' not in result:
287
+ map_path = geo_system.create_map(result['latitude'], result['longitude'])
288
+ if map_path:
289
+ with open(map_path, 'r') as f:
290
+ map_html = f.read()
291
+ os.unlink(map_path)
292
+ return result, map_html
293
+ return result, "<p>Harita oluşturulamadı</p>"
294
+
295
+ predict_btn.click(
296
+ fn=process_prediction,
297
  inputs=image_input,
298
+ outputs=[output_json, map_output]
299
  )
300
 
301
+ with gr.Tab("🛠️ Model Eğitimi"):
302
+ with gr.Row():
303
+ with gr.Column():
304
+ epochs = gr.Slider(1, 10, value=3, label="Epoch Sayısı")
305
+ batch_size = gr.Slider(8, 32, value=16, step=8, label="Batch Size")
306
+ train_btn = gr.Button("🚀 Modeli Eğit", variant="primary")
307
+
308
+ with gr.Column():
309
+ train_output = gr.JSON(label="Eğitim Sonuçları")
310
+ loss_plot = gr.Plot(label="Kayıp Grafiği")
311
 
312
+ def train_model(epochs, batch_size):
313
+ result = geo_system.train(epochs=int(epochs), batch_size=int(batch_size))
314
+
315
+ if 'losses' in result:
316
+ # Kayıp grafiği oluştur
317
+ plt.figure(figsize=(10, 6))
318
+ plt.plot(result['losses'])
319
+ plt.title('Eğitim Kaybı')
320
+ plt.xlabel('Epoch')
321
+ plt.ylabel('Loss')
322
+ plt.grid(True)
323
+
324
+ return result, plt
325
+
326
+ return result, None
327
+
328
+ train_btn.click(
329
+ fn=train_model,
330
+ inputs=[epochs, batch_size],
331
+ outputs=[train_output, loss_plot]
332
+ )
333
+
334
+ with gr.Tab("📊 Dataset Bilgisi"):
335
+ gr.Markdown("""
336
+ ### S2-NAIP Dataset (Orta Ölçek)
337
+
338
+ **Kullanılan:** 2000 örnek (~1-2GB)
339
 
340
  **Özellikler:**
341
  - Sentinel-2 (10m çözünürlük) görüntüleri
342
+ - NAIP (1m çözünürlük) görüntüleri
343
  - Koordinat metadata'sı
344
  - ABD genelinde çeşitli lokasyonlar
345
 
346
+ **Model:** DINOv2-small (Hafif)
347
+ - Özellik boyutu: 384
348
+ - Giriş çözünürlük: 224x224
349
+ - Çıktı: Enlem, Boylam
350
+
351
+ **Performans Beklentisi:**
352
+ - Eğitim süresi: 5-15 dakika
353
+ - Model boyutu: ~150MB
354
+ - Tahmin süresi: <1 saniye
355
  """)
356
+
357
+ # Dataset istatistikleri
358
+ if geo_system.dataset:
359
+ gr.Markdown(f"""
360
+ **Yüklenen Örnek:** {len(geo_system.dataset)}
361
+ """)
362
 
363
+ gr.Markdown("""
364
+ ---
365
+ **Not:** Bu orta ölçekli sistem Hugging Face Spaces'te çalışacak şekilde optimize edilmiştir.
366
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
367
 
368
+ return demo
369
 
370
  if __name__ == "__main__":
371
+ demo = create_interface()
372
  demo.launch(
373
  server_name="0.0.0.0",
374
  server_port=7860,