Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Upload 55 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- README.md +42 -0
- app.py +545 -0
- custom.ttf +0 -0
- images/1117948158689819.jpg +0 -0
- images/1131929937219152.jpg +0 -0
- images/132981045530287.jpg +0 -0
- images/1373307973052511.jpg +0 -0
- images/175745731085288.jpg +0 -0
- images/1906611242827635.jpg +0 -0
- images/2569566893353047.jpg +0 -0
- images/262995582382853.jpg +0 -0
- images/2688573051442365.jpg +0 -0
- images/2815113128739763.jpg +0 -0
- images/2926954904217999.jpg +0 -0
- images/296619375337754.jpg +0 -0
- images/2967574993525954.jpg +0 -0
- images/297765091851450.jpg +0 -0
- images/298997258922815.jpg +0 -0
- images/312137333614311.jpg +0 -0
- images/314603156759488.jpg +0 -0
- images/316183296688571.jpg +0 -0
- images/320045362820818.jpg +0 -0
- images/3295650104022182.jpg +0 -0
- images/3741052562672207.jpg +0 -0
- images/374123653951353.jpg +0 -0
- images/393835759099320.jpg +0 -0
- images/4065883540137904.jpg +0 -0
- images/474703873606185.jpg +0 -0
- images/477541399978996.jpg +0 -0
- images/479790613361193.jpg +0 -0
- images/4887875507910938.jpg +0 -0
- images/4898606693529789.jpg +0 -0
- images/495204901603170.jpg +0 -0
- images/503058357484613.jpg +0 -0
- images/509010086792207.jpg +0 -0
- images/517681129360654.jpg +0 -0
- images/521919388810193.jpg +0 -0
- images/524652062251031.jpg +0 -0
- images/529442031384910.jpg +0 -0
- images/537681453897872.jpg +0 -0
- images/546314506564628.jpg +0 -0
- images/688692811847809.jpg +0 -0
- images/732681614433401.jpg +0 -0
- images/743171673023530.jpg +0 -0
- images/744683329529751.jpg +0 -0
- images/797108350987275.jpg +0 -0
- images/803654143860113.jpg +0 -0
- images/810457353224255.jpg +0 -0
- images/827026111505364.jpg +0 -0
- images/900447860688305.jpg +0 -0
README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Plonk
|
| 3 |
+
emoji: 👀
|
| 4 |
+
colorFrom: yellow
|
| 5 |
+
colorTo: purple
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 3.44.0
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
| 14 |
+

|
| 15 |
+
# OpenStreetView-5M <br><sub>The Many Roads to Global Visual Geolocation 📍🌍</sub>
|
| 16 |
+
|
| 17 |
+
OpenStreetView-5M is hosted at [huggingface/datasets/osv5m/osv5m](https://huggingface.co/datasets/osv5m/osv5m)
|
| 18 |
+
Demo for [OpenStreetView-5M: The Many Roads to Global Visual Geolocation](https://imagine.enpc.fr/~guillaume-astruc/osv-5m).
|
| 19 |
+
|
| 20 |
+
**First authors:** [Guillaume Astruc](https://gastruc.github.io/), [Nicolas Dufour](https://nicolas-dufour.github.io/), [Ioannis Siglidis](https://imagine.enpc.fr/~siglidii/)
|
| 21 |
+
**Second authors:** [Constantin Aronssohn](), Nacim Bouia, [Stephanie Fu](https://stephanie-fu.github.io/), [Romain Loiseau](https://romainloiseau.fr/), [Van Nguyen Nguyen](https://nv-nguyen.github.io/), [Charles Raude](https://imagine.enpc.fr/~raudec/), [Elliot Vincent](https://imagine.enpc.fr/~vincente/), Lintao XU, Hongyu Zhou
|
| 22 |
+
**Last author:** [Loic Landrieu](https://loiclandrieu.com/)
|
| 23 |
+
**Research Institute:** [Imagine](https://imagine.enpc.fr/), _LIGM, Ecole des Ponts, Univ Gustave Eiffel, CNRS, Marne-la-Vallée, France_
|
| 24 |
+
|
| 25 |
+
OpenStreetView-5M is the first large-scale open geolocation benchmark of streetview images.
|
| 26 |
+
To get a sense of the difficulty of the benchmark, you can play our [demo](https://huggingface.co/spaces/osv5m/plonk).
|
| 27 |
+
Our dataset was used in an extensive benchmark of which we provide the best model.
|
| 28 |
+
For more details and results, please check out our [paper](arxiv) and [project page](https://imagine.enpc.fr/~guillaume-astruc/osv-5m).
|
| 29 |
+
|
| 30 |
+
### Citing 💫
|
| 31 |
+
|
| 32 |
+
```bibtex
|
| 33 |
+
@article{osv5m,
|
| 34 |
+
title = {{OpenStreetView-5M}: {T}he Many Roads to Global Visual Geolocation},
|
| 35 |
+
author = {Astruc, Guillaume and Dufour, Nicolas and Siglidis, Ioannis
|
| 36 |
+
and Aronssohn, Constantin and Bouia, Nacim and Fu, Stephanie and Loiseau, Romain
|
| 37 |
+
and Nguyen, Van Nguyen and Raude, Charles and Vincent, Elliot and Xu, Lintao
|
| 38 |
+
and Zhou, Hongyu and Landrieu, Loic},
|
| 39 |
+
journal = {CVPR},
|
| 40 |
+
year = {2024},
|
| 41 |
+
}
|
| 42 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,545 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Requires gradio==4.27.0"""
|
| 2 |
+
import io
|
| 3 |
+
import shutil
|
| 4 |
+
import os
|
| 5 |
+
import json
|
| 6 |
+
import uuid
|
| 7 |
+
import time
|
| 8 |
+
import math
|
| 9 |
+
import datetime
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
from uuid import uuid4
|
| 13 |
+
from PIL import Image
|
| 14 |
+
from math import radians, sin, cos, sqrt, asin, exp
|
| 15 |
+
from os.path import join
|
| 16 |
+
from collections import defaultdict
|
| 17 |
+
from itertools import tee
|
| 18 |
+
|
| 19 |
+
import matplotlib.style as mplstyle
|
| 20 |
+
mplstyle.use(['fast'])
|
| 21 |
+
import pandas as pd
|
| 22 |
+
|
| 23 |
+
import gradio as gr
|
| 24 |
+
import reverse_geocoder as rg
|
| 25 |
+
import cartopy.crs as ccrs
|
| 26 |
+
import cartopy.feature as cfeature
|
| 27 |
+
import matplotlib.pyplot as plt
|
| 28 |
+
|
| 29 |
+
from gradio_folium import Folium
|
| 30 |
+
from geographiclib.geodesic import Geodesic
|
| 31 |
+
from folium import Map, Element, LatLngPopup, Marker, Icon, PolyLine, FeatureGroup
|
| 32 |
+
from folium.map import LayerControl
|
| 33 |
+
from folium.plugins import BeautifyIcon
|
| 34 |
+
from huggingface_hub import CommitScheduler
|
| 35 |
+
|
| 36 |
+
MPL = False
|
| 37 |
+
IMAGE_FOLDER = './images'
|
| 38 |
+
CSV_FILE = './select.csv'
|
| 39 |
+
BASE_LOCATION = [0, 23]
|
| 40 |
+
RULES = """<h1>OSV-5M (plonk)</h1>
|
| 41 |
+
<center><img width="256" alt="Rotating globe" src="https://upload.wikimedia.org/wikipedia/commons/6/6b/Rotating_globe.gif"></center>
|
| 42 |
+
<h2> Instructions </h2>
|
| 43 |
+
<h3> Click on the map 🗺️ (left) to the location at which you think the image 🖼️ (right) was captured! </h3>
|
| 44 |
+
<h3> Click "Select" to finalize your selection and then "Next" to move to the next image. </h3>
|
| 45 |
+
"""
|
| 46 |
+
css = """
|
| 47 |
+
@font-face {
|
| 48 |
+
font-family: custom;
|
| 49 |
+
src: url("/file=custom.ttf");
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
h1 {
|
| 53 |
+
text-align: center;
|
| 54 |
+
display:block;
|
| 55 |
+
font-family: custom;
|
| 56 |
+
}
|
| 57 |
+
img {
|
| 58 |
+
text-align: center;
|
| 59 |
+
display:block;
|
| 60 |
+
}
|
| 61 |
+
h2 {
|
| 62 |
+
text-align: center;
|
| 63 |
+
display:block;
|
| 64 |
+
font-family: custom;
|
| 65 |
+
}
|
| 66 |
+
h3 {
|
| 67 |
+
text-align: center;
|
| 68 |
+
display:block;
|
| 69 |
+
font-family: custom;
|
| 70 |
+
font-weight: normal;
|
| 71 |
+
}
|
| 72 |
+
"""
|
| 73 |
+
|
| 74 |
+
space_js = """
|
| 75 |
+
<script src="https://cdn.jsdelivr.net/npm/@rapideditor/[email protected]/dist/country-coder.iife.min.js"></script>
|
| 76 |
+
<script>
|
| 77 |
+
function shortcuts(e) {
|
| 78 |
+
var event = document.all ? window.event : e;
|
| 79 |
+
switch (e.target.tagName.toLowerCase()) {
|
| 80 |
+
case "input":
|
| 81 |
+
case "textarea":
|
| 82 |
+
break;
|
| 83 |
+
default:
|
| 84 |
+
if (e.key.toLowerCase() == " " && !e.shiftKey) {
|
| 85 |
+
document.getElementById("latlon_btn").click();
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
function shortcuts_exit(e) {
|
| 91 |
+
var event = document.all ? window.event : e;
|
| 92 |
+
switch (e.target.tagName.toLowerCase()) {
|
| 93 |
+
case "input":
|
| 94 |
+
case "textarea":
|
| 95 |
+
break;
|
| 96 |
+
default:
|
| 97 |
+
if (e.key.toLowerCase() == "e" && e.shiftKey) {
|
| 98 |
+
document.getElementById("exit_btn").click();
|
| 99 |
+
}
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
document.addEventListener('keypress', shortcuts, false);
|
| 103 |
+
document.addEventListener('keypress', shortcuts_exit, false);
|
| 104 |
+
</script>
|
| 105 |
+
"""
|
| 106 |
+
|
| 107 |
+
def sample_points_along_geodesic(start_lat, start_lon, end_lat, end_lon, min_length_km=2000, segment_length_km=5000, num_samples=None):
|
| 108 |
+
geod = Geodesic.WGS84
|
| 109 |
+
distance = geod.Inverse(start_lat, start_lon, end_lat, end_lon)['s12']
|
| 110 |
+
if distance < min_length_km:
|
| 111 |
+
return [(start_lat, start_lon), (end_lat, end_lon)]
|
| 112 |
+
|
| 113 |
+
if num_samples is None:
|
| 114 |
+
num_samples = min(int(distance / segment_length_km) + 1, 1000)
|
| 115 |
+
point_distance = np.linspace(0, distance, num_samples)
|
| 116 |
+
points = []
|
| 117 |
+
for pd in point_distance:
|
| 118 |
+
line = geod.InverseLine(start_lat, start_lon, end_lat, end_lon)
|
| 119 |
+
g_point = line.Position(pd, Geodesic.STANDARD | Geodesic.LONG_UNROLL)
|
| 120 |
+
points.append((g_point['lat2'], g_point['lon2']))
|
| 121 |
+
return points
|
| 122 |
+
|
| 123 |
+
class GeodesicPolyLine(PolyLine):
|
| 124 |
+
def __init__(self, locations, min_length_km=2000, segment_length_km=1000, num_samples=None, **kwargs):
|
| 125 |
+
kwargs1 = dict(min_length_km=min_length_km, segment_length_km=segment_length_km, num_samples=num_samples)
|
| 126 |
+
assert len(locations) == 2, "A polyline must have at least two locations"
|
| 127 |
+
start, end = locations
|
| 128 |
+
geodesic_locs = sample_points_along_geodesic(start[0], start[1], end[0], end[1], **kwargs1)
|
| 129 |
+
super().__init__(geodesic_locs, **kwargs)
|
| 130 |
+
|
| 131 |
+
def inject_javascript(folium_map):
|
| 132 |
+
js = """
|
| 133 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 134 |
+
map_name_1.on('click', function(e) {
|
| 135 |
+
window.state_data = e.latlng
|
| 136 |
+
});
|
| 137 |
+
});
|
| 138 |
+
"""
|
| 139 |
+
folium_map.get_root().html.add_child(Element(f'<script>{js}</script>'))
|
| 140 |
+
|
| 141 |
+
def make_map_(name="map_name", id="1"):
|
| 142 |
+
map = Map(location=BASE_LOCATION, zoom_start=1)
|
| 143 |
+
map._name, map._id = name, id
|
| 144 |
+
|
| 145 |
+
LatLngPopup().add_to(map)
|
| 146 |
+
inject_javascript(map)
|
| 147 |
+
return map
|
| 148 |
+
|
| 149 |
+
def make_map(name="map_name", id="1", height=500):
|
| 150 |
+
map = make_map_(name, id)
|
| 151 |
+
fol = Folium(value=map, height=height, visible=False, elem_id='map-fol')
|
| 152 |
+
return fol
|
| 153 |
+
|
| 154 |
+
def map_js():
|
| 155 |
+
return """
|
| 156 |
+
(a, textBox) => {
|
| 157 |
+
const iframeMap = document.getElementById('map-fol').getElementsByTagName('iframe')[0];
|
| 158 |
+
const latlng = iframeMap.contentWindow.state_data;
|
| 159 |
+
if (!latlng) { return; }
|
| 160 |
+
textBox = `${latlng.lat},${latlng.lng}`;
|
| 161 |
+
document.getElementById('coords-tbox').getElementsByTagName('textarea')[0].value = textBox;
|
| 162 |
+
var a = countryCoder.iso1A2Code([latlng.lng, latlng.lat]);
|
| 163 |
+
if (!a) { a = 'nan'; }
|
| 164 |
+
return [a, `${latlng.lat},${latlng.lng},${a}`];
|
| 165 |
+
}
|
| 166 |
+
"""
|
| 167 |
+
|
| 168 |
+
def haversine(lat1, lon1, lat2, lon2):
|
| 169 |
+
if (lat1 is None) or (lon1 is None) or (lat2 is None) or (lon2 is None):
|
| 170 |
+
return 0
|
| 171 |
+
R = 6371 # radius of the earth in km
|
| 172 |
+
dLat = radians(lat2 - lat1)
|
| 173 |
+
dLon = radians(lon2 - lon1)
|
| 174 |
+
a = (
|
| 175 |
+
sin(dLat / 2.0) ** 2
|
| 176 |
+
+ cos(radians(lat1)) * cos(radians(lat2)) * sin(dLon / 2.0) ** 2
|
| 177 |
+
)
|
| 178 |
+
c = 2 * asin(sqrt(a))
|
| 179 |
+
distance = R * c
|
| 180 |
+
return distance
|
| 181 |
+
|
| 182 |
+
def geoscore(d):
|
| 183 |
+
return 5000 * exp(-d / 1492.7)
|
| 184 |
+
|
| 185 |
+
def compute_scores(csv_file):
|
| 186 |
+
df = pd.read_csv(csv_file)
|
| 187 |
+
if 'accuracy_country' not in df.columns:
|
| 188 |
+
print('Computing scores... (this may take a while)')
|
| 189 |
+
geocoders = rg.search([(row.true_lat, row.true_lon) for row in df.itertuples(name='Pandas')])
|
| 190 |
+
df['city'] = [geocoder['name'] for geocoder in geocoders]
|
| 191 |
+
df['area'] = [geocoder['admin2'] for geocoder in geocoders]
|
| 192 |
+
df['region'] = [geocoder['admin1'] for geocoder in geocoders]
|
| 193 |
+
df['country'] = [geocoder['cc'] for geocoder in geocoders]
|
| 194 |
+
|
| 195 |
+
df['city_val'] = df['city'].apply(lambda x: 0 if pd.isna(x) or x == 'nan' else 1)
|
| 196 |
+
df['area_val'] = df['area'].apply(lambda x: 0 if pd.isna(x) or x == 'nan' else 1)
|
| 197 |
+
df['region_val'] = df['region'].apply(lambda x: 0 if pd.isna(x) or x == 'nan' else 1)
|
| 198 |
+
df['country_val'] = df['country'].apply(lambda x: 0 if pd.isna(x) or x == 'nan' else 1)
|
| 199 |
+
|
| 200 |
+
df['distance'] = df.apply(lambda row: haversine(row['true_lat'], row['true_lon'], row['pred_lat'], row['pred_lon']), axis=1)
|
| 201 |
+
df['score'] = df.apply(lambda row: geoscore(row['distance']), axis=1)
|
| 202 |
+
df['distance_base'] = df.apply(lambda row: haversine(row['true_lat'], row['true_lon'], row['pred_lat_base'], row['pred_lon_base']), axis=1)
|
| 203 |
+
df['score_base'] = df.apply(lambda row: geoscore(row['distance_base']), axis=1)
|
| 204 |
+
|
| 205 |
+
print('Computing geocoding accuracy (base)...')
|
| 206 |
+
geocoders_base = rg.search([(row.pred_lat_base, row.pred_lon_base) for row in df.itertuples(name='Pandas')])
|
| 207 |
+
df['pred_city_base'] = [geocoder['name'] for geocoder in geocoders_base]
|
| 208 |
+
df['pred_area_base'] = [geocoder['admin2'] for geocoder in geocoders_base]
|
| 209 |
+
df['pred_region_base'] = [geocoder['admin1'] for geocoder in geocoders_base]
|
| 210 |
+
df['pred_country_base'] = [geocoder['cc'] for geocoder in geocoders_base]
|
| 211 |
+
|
| 212 |
+
df['city_hit_base'] = [df['city'].iloc[i] != 'nan' and df['pred_city_base'].iloc[i] == df['city'].iloc[i] for i in range(len(df))]
|
| 213 |
+
df['area_hit_base'] = [df['area'].iloc[i] != 'nan' and df['pred_area_base'].iloc[i] == df['area'].iloc[i] for i in range(len(df))]
|
| 214 |
+
df['region_hit_base'] = [df['region'].iloc[i] != 'nan' and df['pred_region_base'].iloc[i] == df['region'].iloc[i] for i in range(len(df))]
|
| 215 |
+
df['country_hit_base'] = [df['country'].iloc[i] != 'nan' and df['pred_country_base'].iloc[i] == df['country'].iloc[i] for i in range(len(df))]
|
| 216 |
+
|
| 217 |
+
df['accuracy_city_base'] = [(0 if df['city_val'].iloc[:i].sum() == 0 else df['city_hit_base'].iloc[:i].sum()/df['city_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 218 |
+
df['accuracy_area_base'] = [(0 if df['area_val'].iloc[:i].sum() == 0 else df['area_hit_base'].iloc[:i].sum()/df['area_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 219 |
+
df['accuracy_region_base'] = [(0 if df['region_val'].iloc[:i].sum() == 0 else df['region_hit_base'].iloc[:i].sum()/df['region_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 220 |
+
df['accuracy_country_base'] = [(0 if df['country_val'].iloc[:i].sum() == 0 else df['country_hit_base'].iloc[:i].sum()/df['country_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 221 |
+
|
| 222 |
+
print('Computing geocoding accuracy (best)...')
|
| 223 |
+
geocoders = rg.search([(row.pred_lat, row.pred_lon) for row in df.itertuples()])
|
| 224 |
+
df['pred_city'] = [geocoder['name'] for geocoder in geocoders]
|
| 225 |
+
df['pred_area'] = [geocoder['admin2'] for geocoder in geocoders]
|
| 226 |
+
df['pred_region'] = [geocoder['admin1'] for geocoder in geocoders]
|
| 227 |
+
df['pred_country'] = [geocoder['cc'] for geocoder in geocoders]
|
| 228 |
+
|
| 229 |
+
df['city_hit'] = [df['city'].iloc[i] != 'nan' and df['pred_city'].iloc[i] == df['city'].iloc[i] for i in range(len(df))]
|
| 230 |
+
df['area_hit'] = [df['area'].iloc[i] != 'nan' and df['pred_area'].iloc[i] == df['area'].iloc[i] for i in range(len(df))]
|
| 231 |
+
df['region_hit'] = [df['region'].iloc[i] != 'nan' and df['pred_region'].iloc[i] == df['region'].iloc[i] for i in range(len(df))]
|
| 232 |
+
df['country_hit'] = [df['country'].iloc[i] != 'nan' and df['pred_country'].iloc[i] == df['country'].iloc[i] for i in range(len(df))]
|
| 233 |
+
|
| 234 |
+
df['accuracy_city'] = [(0 if df['city_val'].iloc[:i].sum() == 0 else df['city_hit'].iloc[:i].sum()/df['city_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 235 |
+
df['accuracy_area'] = [(0 if df['area_val'].iloc[:i].sum() == 0 else df['area_hit'].iloc[:i].sum()/df['area_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 236 |
+
df['accuracy_region'] = [(0 if df['region_val'].iloc[:i].sum() == 0 else df['region_hit'].iloc[:i].sum()/df['region_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 237 |
+
df['accuracy_country'] = [(0 if df['country_val'].iloc[:i].sum() == 0 else df['country_hit'].iloc[:i].sum()/df['country_val'].iloc[:i].sum())*100 for i in range(len(df))]
|
| 238 |
+
df.to_csv(csv_file, index=False)
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
if __name__ == "__main__":
|
| 242 |
+
JSON_DATASET_DIR = 'results'
|
| 243 |
+
scheduler = CommitScheduler(
|
| 244 |
+
repo_id="osv5m/humeval",
|
| 245 |
+
repo_type="dataset",
|
| 246 |
+
folder_path=JSON_DATASET_DIR,
|
| 247 |
+
path_in_repo=f"raw_data",
|
| 248 |
+
every=2
|
| 249 |
+
)
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
class Engine(object):
|
| 253 |
+
def __init__(self, image_folder, csv_file, mpl=True):
|
| 254 |
+
self.image_folder = image_folder
|
| 255 |
+
self.csv_file = csv_file
|
| 256 |
+
self.load_images_and_coordinates(csv_file)
|
| 257 |
+
|
| 258 |
+
# Initialize the score and distance lists
|
| 259 |
+
self.index = 0
|
| 260 |
+
self.stats = defaultdict(list)
|
| 261 |
+
|
| 262 |
+
# Create the figure and canvas only once
|
| 263 |
+
self.fig = plt.Figure(figsize=(10, 6))
|
| 264 |
+
self.mpl = mpl
|
| 265 |
+
if mpl:
|
| 266 |
+
self.ax = self.fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
|
| 267 |
+
|
| 268 |
+
self.tag = str(uuid4()) + datetime.datetime.now().strftime("__%Y_%m_%d_%H_%M_%S")
|
| 269 |
+
|
| 270 |
+
def load_images_and_coordinates(self, csv_file):
|
| 271 |
+
# Load the CSV
|
| 272 |
+
df = pd.read_csv(csv_file)
|
| 273 |
+
|
| 274 |
+
# Get the image filenames and their coordinates
|
| 275 |
+
self.images = [os.path.join(self.image_folder, f"{img_path}.jpg") for img_path in df['id'].tolist()[:]]
|
| 276 |
+
self.coordinates = df[['true_lon', 'true_lat']].values.tolist()[:]
|
| 277 |
+
|
| 278 |
+
# compute the admins
|
| 279 |
+
self.df = df
|
| 280 |
+
self.admins = self.df[['city', 'area', 'region', 'country']].values.tolist()[:]
|
| 281 |
+
self.preds = self.df[['pred_lon', 'pred_lat']].values.tolist()[:]
|
| 282 |
+
|
| 283 |
+
def isfinal(self):
|
| 284 |
+
return self.index == len(self.images)-1
|
| 285 |
+
|
| 286 |
+
def load_image(self):
|
| 287 |
+
if self.index > len(self.images)-1:
|
| 288 |
+
self.master.update_idletasks()
|
| 289 |
+
self.finish()
|
| 290 |
+
|
| 291 |
+
self.set_clock()
|
| 292 |
+
return self.images[self.index], '### ' + str(self.index + 1) + '/' + str(len(self.images))
|
| 293 |
+
|
| 294 |
+
def get_figure(self):
|
| 295 |
+
if self.mpl:
|
| 296 |
+
img_buf = io.BytesIO()
|
| 297 |
+
self.fig.savefig(img_buf, format='png', bbox_inches='tight', pad_inches=0, dpi=300)
|
| 298 |
+
pil = Image.open(img_buf)
|
| 299 |
+
self.width, self.height = pil.size
|
| 300 |
+
return pil
|
| 301 |
+
else:
|
| 302 |
+
pred_lon, pred_lat, true_lon, true_lat, click_lon, click_lat = self.info
|
| 303 |
+
map = Map(location=BASE_LOCATION, zoom_start=1)
|
| 304 |
+
map._name, map._id = 'visu', '1'
|
| 305 |
+
|
| 306 |
+
icon_star = BeautifyIcon(
|
| 307 |
+
icon='star',
|
| 308 |
+
inner_icon_style='color:red;font-size:30px;',
|
| 309 |
+
background_color='transparent',
|
| 310 |
+
border_color='transparent',
|
| 311 |
+
)
|
| 312 |
+
feature_group = FeatureGroup(name='Ground Truth')
|
| 313 |
+
Marker(
|
| 314 |
+
location=[true_lat, true_lon],
|
| 315 |
+
popup="True location",
|
| 316 |
+
icon=icon_star,
|
| 317 |
+
).add_to(feature_group)
|
| 318 |
+
map.add_child(feature_group)
|
| 319 |
+
|
| 320 |
+
icon_square = BeautifyIcon(
|
| 321 |
+
icon_shape='rectangle-dot',
|
| 322 |
+
border_color='green',
|
| 323 |
+
border_width=10,
|
| 324 |
+
)
|
| 325 |
+
feature_group_best = FeatureGroup(name='Best Model')
|
| 326 |
+
Marker(
|
| 327 |
+
location=[pred_lat, pred_lon],
|
| 328 |
+
popup="Best Model",
|
| 329 |
+
icon=icon_square,
|
| 330 |
+
).add_to(feature_group_best)
|
| 331 |
+
GeodesicPolyLine([[true_lat, true_lon], [pred_lat, pred_lon]], color='green').add_to(feature_group_best)
|
| 332 |
+
map.add_child(feature_group_best)
|
| 333 |
+
|
| 334 |
+
icon_circle = BeautifyIcon(
|
| 335 |
+
icon_shape='circle-dot',
|
| 336 |
+
border_color='blue',
|
| 337 |
+
border_width=10,
|
| 338 |
+
)
|
| 339 |
+
feature_group_user = FeatureGroup(name='User')
|
| 340 |
+
Marker(
|
| 341 |
+
location=[click_lat, click_lon],
|
| 342 |
+
popup="Human",
|
| 343 |
+
icon=icon_circle,
|
| 344 |
+
).add_to(feature_group_user)
|
| 345 |
+
GeodesicPolyLine([[true_lat, true_lon], [click_lat, click_lon]], color='blue').add_to(feature_group_user)
|
| 346 |
+
map.add_child(feature_group_user)
|
| 347 |
+
|
| 348 |
+
map.add_child(LayerControl())
|
| 349 |
+
|
| 350 |
+
return map
|
| 351 |
+
|
| 352 |
+
def set_clock(self):
|
| 353 |
+
self.time = time.time()
|
| 354 |
+
|
| 355 |
+
def get_clock(self):
|
| 356 |
+
return time.time() - self.time
|
| 357 |
+
|
| 358 |
+
def mpl_style(self, pred_lon, pred_lat, true_lon, true_lat, click_lon, click_lat):
|
| 359 |
+
if self.mpl:
|
| 360 |
+
self.ax.clear()
|
| 361 |
+
self.ax.set_global()
|
| 362 |
+
self.ax.stock_img()
|
| 363 |
+
self.ax.add_feature(cfeature.COASTLINE)
|
| 364 |
+
self.ax.add_feature(cfeature.BORDERS, linestyle=':')
|
| 365 |
+
|
| 366 |
+
self.ax.plot(pred_lon, pred_lat, 'gv', transform=ccrs.Geodetic(), label='model')
|
| 367 |
+
self.ax.plot([true_lon, pred_lon], [true_lat, pred_lat], color='green', linewidth=1, transform=ccrs.Geodetic())
|
| 368 |
+
self.ax.plot(click_lon, click_lat, 'bo', transform=ccrs.Geodetic(), label='user')
|
| 369 |
+
self.ax.plot([true_lon, click_lon], [true_lat, click_lat], color='blue', linewidth=1, transform=ccrs.Geodetic())
|
| 370 |
+
self.ax.plot(true_lon, true_lat, 'rx', transform=ccrs.Geodetic(), label='g.t.')
|
| 371 |
+
legend = self.ax.legend(ncol=3, loc='lower center') #, bbox_to_anchor=(0.5, -0.15), borderaxespad=0.
|
| 372 |
+
legend.get_frame().set_alpha(None)
|
| 373 |
+
self.fig.canvas.draw()
|
| 374 |
+
else:
|
| 375 |
+
self.info = [pred_lon, pred_lat, true_lon, true_lat, click_lon, click_lat]
|
| 376 |
+
|
| 377 |
+
|
| 378 |
+
def click(self, click_lon, click_lat, country):
|
| 379 |
+
time_elapsed = self.get_clock()
|
| 380 |
+
self.stats['times'].append(time_elapsed)
|
| 381 |
+
|
| 382 |
+
# convert click_lon, click_lat to lat, lon (given that you have the borders of the image)
|
| 383 |
+
# click_lon and click_lat is in pixels
|
| 384 |
+
# lon and lat is in degrees
|
| 385 |
+
self.stats['clicked_locations'].append((click_lat, click_lon))
|
| 386 |
+
true_lon, true_lat = self.coordinates[self.index]
|
| 387 |
+
pred_lon, pred_lat = self.preds[self.index]
|
| 388 |
+
self.mpl_style(pred_lon, pred_lat, true_lon, true_lat, click_lon, click_lat)
|
| 389 |
+
|
| 390 |
+
distance = haversine(true_lat, true_lon, click_lat, click_lon)
|
| 391 |
+
score = geoscore(distance)
|
| 392 |
+
self.stats['scores'].append(score)
|
| 393 |
+
self.stats['distances'].append(distance)
|
| 394 |
+
self.stats['country'].append(int(self.admins[self.index][3] != 'nan' and country == self.admins[self.index][3]))
|
| 395 |
+
|
| 396 |
+
df = pd.DataFrame([self.get_model_average(who) for who in ['user', 'best', 'base']], columns=['who', 'GeoScore', 'Distance', 'Accuracy (country)']).round(2)
|
| 397 |
+
result_text = (f"### GeoScore: {score:.0f}, distance: {distance:.0f} km")
|
| 398 |
+
|
| 399 |
+
self.cache(self.index+1, score, distance, (click_lat, click_lon), time_elapsed)
|
| 400 |
+
return self.get_figure(), result_text, df
|
| 401 |
+
|
| 402 |
+
def next_image(self):
|
| 403 |
+
# Go to the next image
|
| 404 |
+
self.index += 1
|
| 405 |
+
return self.load_image()
|
| 406 |
+
|
| 407 |
+
def get_model_average(self, which, all=False):
|
| 408 |
+
aux, i = [], self.index+1
|
| 409 |
+
if which == 'user':
|
| 410 |
+
avg_score = sum(self.stats['scores']) / len(self.stats['scores']) if self.stats['scores'] else 0
|
| 411 |
+
avg_distance = sum(self.stats['distances']) / len(self.stats['distances']) if self.stats['distances'] else 0
|
| 412 |
+
avg_country_accuracy = (0 if self.df['country_val'].iloc[:i].sum() == 0 else sum(self.stats['country'])/self.df['country_val'].iloc[:i].sum())*100
|
| 413 |
+
if all:
|
| 414 |
+
avg_city_accuracy = (0 if self.df['city_val'].iloc[:i].sum() == 0 else sum(self.stats['city'])/self.df['city_val'].iloc[:i].sum())*100
|
| 415 |
+
avg_area_accuracy = (0 if self.df['area_val'].iloc[:i].sum() == 0 else sum(self.stats['area'])/self.df['area_val'].iloc[:i].sum())*100
|
| 416 |
+
avg_region_accuracy = (0 if self.df['region_val'].iloc[:i].sum() == 0 else sum(self.stats['region'])/self.df['region_val'].iloc[:i].sum())*100
|
| 417 |
+
aux = [avg_city_accuracy, avg_area_accuracy, avg_region_accuracy]
|
| 418 |
+
elif which == 'base':
|
| 419 |
+
avg_score = np.mean(self.df[['score_base']].iloc[:i])
|
| 420 |
+
avg_distance = np.mean(self.df[['distance_base']].iloc[:i])
|
| 421 |
+
avg_country_accuracy = self.df['accuracy_country_base'].iloc[i]
|
| 422 |
+
if all:
|
| 423 |
+
aux = [self.df['accuracy_city_base'].iloc[i], self.df['accuracy_area_base'].iloc[i], self.df['accuracy_region_base'].iloc[i]]
|
| 424 |
+
elif which == 'best':
|
| 425 |
+
avg_score = np.mean(self.df[['score']].iloc[:i])
|
| 426 |
+
avg_distance = np.mean(self.df[['distance']].iloc[:i])
|
| 427 |
+
avg_country_accuracy = self.df['accuracy_country'].iloc[i]
|
| 428 |
+
if all:
|
| 429 |
+
aux = [self.df['accuracy_city_base'].iloc[i], self.df['accuracy_area_base'].iloc[i], self.df['accuracy_region_base'].iloc[i]]
|
| 430 |
+
return [which, avg_score, avg_distance, avg_country_accuracy] + aux
|
| 431 |
+
|
| 432 |
+
def update_average_display(self):
|
| 433 |
+
# Calculate the average values
|
| 434 |
+
avg_score = sum(self.stats['scores']) / len(self.stats['scores']) if self.stats['scores'] else 0
|
| 435 |
+
avg_distance = sum(self.stats['distances']) / len(self.stats['distances']) if self.stats['distances'] else 0
|
| 436 |
+
|
| 437 |
+
# Update the text box
|
| 438 |
+
return f"GeoScore: {avg_score:.0f}, Distance: {avg_distance:.0f} km"
|
| 439 |
+
|
| 440 |
+
def finish(self):
|
| 441 |
+
clicks = rg.search(self.stats['clicked_locations'])
|
| 442 |
+
self.stats['city'] = [(int(self.admins[self.index][0] != 'nan' and click['name'] == self.admins[self.index][0])) for click in clicks]
|
| 443 |
+
self.stats['area'] = [(int(self.admins[self.index][1] != 'nan' and click['admin2'] == self.admins[self.index][1])) for click in clicks]
|
| 444 |
+
self.stats['region'] = [(int(self.admins[self.index][2] != 'nan' and click['admin1'] == self.admins[self.index][2])) for click in clicks]
|
| 445 |
+
|
| 446 |
+
df = pd.DataFrame([self.get_model_average(who, True) for who in ['user', 'best', 'base']], columns=['who', 'GeoScore', 'Distance', 'Accuracy (country)', 'Accuracy (city)', 'Accuracy (area)', 'Accuracy (region)'])
|
| 447 |
+
return df
|
| 448 |
+
|
| 449 |
+
# Function to save the game state
|
| 450 |
+
def cache(self, index, score, distance, location, time_elapsed):
|
| 451 |
+
with scheduler.lock:
|
| 452 |
+
os.makedirs(join(JSON_DATASET_DIR, self.tag), exist_ok=True)
|
| 453 |
+
with open(join(JSON_DATASET_DIR, self.tag, f'{index}.json'), 'w') as f:
|
| 454 |
+
json.dump({"lat": location[0], "lon": location[1], "time": time_elapsed, "user": self.tag}, f)
|
| 455 |
+
f.write('\n')
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
if __name__ == "__main__":
|
| 459 |
+
# login with the key from secret
|
| 460 |
+
if 'csv' in os.environ:
|
| 461 |
+
csv_str = os.environ['csv']
|
| 462 |
+
with open(CSV_FILE, 'w') as f:
|
| 463 |
+
f.write(csv_str)
|
| 464 |
+
|
| 465 |
+
compute_scores(CSV_FILE)
|
| 466 |
+
import gradio as gr
|
| 467 |
+
def click(state, coords):
|
| 468 |
+
if coords == '-1' or state['clicked']:
|
| 469 |
+
return gr.update(), gr.update(), gr.update(), gr.update()
|
| 470 |
+
lat, lon, country = coords.split(',')
|
| 471 |
+
state['clicked'] = True
|
| 472 |
+
image, text, df = state['engine'].click(float(lon), float(lat), country)
|
| 473 |
+
df = df.sort_values(by='GeoScore', ascending=False)
|
| 474 |
+
return gr.update(visible=False), gr.update(value=image, visible=True), gr.update(value=text, visible=True), gr.update(value=df, visible=True)
|
| 475 |
+
|
| 476 |
+
def exit_(state):
|
| 477 |
+
if state['engine'].index > 0:
|
| 478 |
+
df = state['engine'].finish()
|
| 479 |
+
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value='', visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(value=df, visible=True), gr.update(value="-1", visible=False), gr.update(value="<h1 style='margin-top: 4em;'> Your stats on OSV-5M🌍 </h1>", visible=True), gr.update(value="<h3 style='margin-top: 1em;'>Thanks for playing ❤️</h3>", visible=True), gr.update(visible=False)
|
| 480 |
+
else:
|
| 481 |
+
return gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
| 482 |
+
|
| 483 |
+
def next_(state):
|
| 484 |
+
if state['clicked']:
|
| 485 |
+
if state['engine'].isfinal():
|
| 486 |
+
return exit_(state)
|
| 487 |
+
else:
|
| 488 |
+
image, text = state['engine'].next_image()
|
| 489 |
+
state['clicked'] = False
|
| 490 |
+
return gr.update(value=make_map_(), visible=True), gr.update(visible=False), gr.update(value=image), gr.update(value=text), gr.update(visible=False), gr.update(), gr.update(visible=False), gr.update(value="-1"), gr.update(), gr.update(), gr.update()
|
| 491 |
+
else:
|
| 492 |
+
return gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
| 493 |
+
|
| 494 |
+
def start(state):
|
| 495 |
+
# create a unique random temporary name under CACHE_DIR
|
| 496 |
+
# generate random hex and make sure it doesn't exist under CACHE_DIR
|
| 497 |
+
state['engine'] = Engine(IMAGE_FOLDER, CSV_FILE, MPL)
|
| 498 |
+
state['clicked'] = False
|
| 499 |
+
image, text = state['engine'].load_image()
|
| 500 |
+
|
| 501 |
+
return (
|
| 502 |
+
gr.update(visible=True),
|
| 503 |
+
gr.update(visible=False),
|
| 504 |
+
gr.update(value=image, visible=True),
|
| 505 |
+
gr.update(value=text, visible=True),
|
| 506 |
+
gr.update(visible=True),
|
| 507 |
+
gr.update(visible=True),
|
| 508 |
+
gr.update(value="<h1>OSV-5M (plonk)</h1>"),
|
| 509 |
+
gr.update(visible=False),
|
| 510 |
+
gr.update(visible=False),
|
| 511 |
+
gr.update(value="-1"),
|
| 512 |
+
gr.update(visible=True),
|
| 513 |
+
)
|
| 514 |
+
|
| 515 |
+
with gr.Blocks(css=css, head=space_js) as demo:
|
| 516 |
+
state = gr.State({})
|
| 517 |
+
rules = gr.Markdown(RULES, visible=True)
|
| 518 |
+
|
| 519 |
+
exit_button = gr.Button("Exit", visible=False, elem_id='exit_btn')
|
| 520 |
+
start_button = gr.Button("Start", visible=True)
|
| 521 |
+
with gr.Row():
|
| 522 |
+
map_ = make_map(height=512)
|
| 523 |
+
if MPL:
|
| 524 |
+
results = gr.Image(label='Results', visible=False)
|
| 525 |
+
else:
|
| 526 |
+
results = Folium(height=512, visible=False)
|
| 527 |
+
image_ = gr.Image(label='Image', visible=False, height=512)
|
| 528 |
+
|
| 529 |
+
with gr.Row():
|
| 530 |
+
text = gr.Markdown("", visible=False)
|
| 531 |
+
text_count = gr.Markdown("", visible=False)
|
| 532 |
+
|
| 533 |
+
with gr.Row():
|
| 534 |
+
select_button = gr.Button("Select", elem_id='latlon_btn', visible=False)
|
| 535 |
+
next_button = gr.Button("Next", visible=False, elem_id='next')
|
| 536 |
+
perf = gr.Dataframe(value=None, visible=False)
|
| 537 |
+
text_end = gr.Markdown("", visible=False)
|
| 538 |
+
|
| 539 |
+
coords = gr.Textbox(value="-1", label="Latitude, Longitude", visible=False, elem_id='coords-tbox')
|
| 540 |
+
start_button.click(start, inputs=[state], outputs=[map_, results, image_, text_count, text, next_button, rules, state, start_button, coords, select_button])
|
| 541 |
+
select_button.click(click, inputs=[state, coords], outputs=[map_, results, text, perf], js=map_js())
|
| 542 |
+
next_button.click(next_, inputs=[state], outputs=[map_, results, image_, text_count, text, next_button, perf, coords, rules, text_end, select_button])
|
| 543 |
+
exit_button.click(exit_, inputs=[state], outputs=[map_, results, image_, text_count, text, next_button, perf, coords, rules, text_end, select_button])
|
| 544 |
+
|
| 545 |
+
demo.launch(allowed_paths=["custom.ttf"], debug=True)
|
custom.ttf
ADDED
|
Binary file (97.8 kB). View file
|
|
|
images/1117948158689819.jpg
ADDED
|
images/1131929937219152.jpg
ADDED
|
images/132981045530287.jpg
ADDED
|
images/1373307973052511.jpg
ADDED
|
images/175745731085288.jpg
ADDED
|
images/1906611242827635.jpg
ADDED
|
images/2569566893353047.jpg
ADDED
|
images/262995582382853.jpg
ADDED
|
images/2688573051442365.jpg
ADDED
|
images/2815113128739763.jpg
ADDED
|
images/2926954904217999.jpg
ADDED
|
images/296619375337754.jpg
ADDED
|
images/2967574993525954.jpg
ADDED
|
images/297765091851450.jpg
ADDED
|
images/298997258922815.jpg
ADDED
|
images/312137333614311.jpg
ADDED
|
images/314603156759488.jpg
ADDED
|
images/316183296688571.jpg
ADDED
|
images/320045362820818.jpg
ADDED
|
images/3295650104022182.jpg
ADDED
|
images/3741052562672207.jpg
ADDED
|
images/374123653951353.jpg
ADDED
|
images/393835759099320.jpg
ADDED
|
images/4065883540137904.jpg
ADDED
|
images/474703873606185.jpg
ADDED
|
images/477541399978996.jpg
ADDED
|
images/479790613361193.jpg
ADDED
|
images/4887875507910938.jpg
ADDED
|
images/4898606693529789.jpg
ADDED
|
images/495204901603170.jpg
ADDED
|
images/503058357484613.jpg
ADDED
|
images/509010086792207.jpg
ADDED
|
images/517681129360654.jpg
ADDED
|
images/521919388810193.jpg
ADDED
|
images/524652062251031.jpg
ADDED
|
images/529442031384910.jpg
ADDED
|
images/537681453897872.jpg
ADDED
|
images/546314506564628.jpg
ADDED
|
images/688692811847809.jpg
ADDED
|
images/732681614433401.jpg
ADDED
|
images/743171673023530.jpg
ADDED
|
images/744683329529751.jpg
ADDED
|
images/797108350987275.jpg
ADDED
|
images/803654143860113.jpg
ADDED
|
images/810457353224255.jpg
ADDED
|
images/827026111505364.jpg
ADDED
|
images/900447860688305.jpg
ADDED
|