Spaces:
Running
Running
Paul-Edouard Sarlin
commited on
Add Gradio demo (#54)
Browse files
app.py
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import matplotlib.pyplot as plt
|
3 |
+
|
4 |
+
from maploc.demo import Demo
|
5 |
+
from maploc.osm.tiling import TileManager
|
6 |
+
from maploc.osm.viz import Colormap, GeoPlotter, plot_nodes
|
7 |
+
from maploc.utils.viz_2d import features_to_RGB, plot_images
|
8 |
+
from maploc.utils.viz_localization import (
|
9 |
+
add_circle_inset,
|
10 |
+
likelihood_overlay,
|
11 |
+
plot_dense_rotations,
|
12 |
+
)
|
13 |
+
|
14 |
+
|
15 |
+
def run(image, address, tile_size_meters, num_rotations):
|
16 |
+
image_path = image.name
|
17 |
+
demo = Demo(num_rotations=int(num_rotations))
|
18 |
+
|
19 |
+
try:
|
20 |
+
image, camera, gravity, proj, bbox = demo.read_input_image(
|
21 |
+
image_path,
|
22 |
+
prior_address=address or None,
|
23 |
+
tile_size_meters=int(tile_size_meters),
|
24 |
+
)
|
25 |
+
except ValueError as e:
|
26 |
+
raise gr.Error(str(e))
|
27 |
+
|
28 |
+
tiler = TileManager.from_bbox(proj, bbox + 10, demo.config.data.pixel_per_meter)
|
29 |
+
canvas = tiler.query(bbox)
|
30 |
+
map_viz = Colormap.apply(canvas.raster)
|
31 |
+
|
32 |
+
plot_images([image, map_viz], titles=["input image", "OpenStreetMap raster"], pad=2)
|
33 |
+
plot_nodes(1, canvas.raster[2], fontsize=6, size=10)
|
34 |
+
fig1 = plt.gcf()
|
35 |
+
|
36 |
+
# Run the inference
|
37 |
+
try:
|
38 |
+
uv, yaw, prob, neural_map, image_rectified = demo.localize(
|
39 |
+
image, camera, canvas, gravity=gravity
|
40 |
+
)
|
41 |
+
except RuntimeError as e:
|
42 |
+
raise gr.Error(str(e))
|
43 |
+
|
44 |
+
# Visualize the predictions
|
45 |
+
overlay = likelihood_overlay(prob.numpy().max(-1), map_viz.mean(-1, keepdims=True))
|
46 |
+
(neural_map_rgb,) = features_to_RGB(neural_map.numpy())
|
47 |
+
plot_images([overlay, neural_map_rgb], titles=["heatmap", "neural map"], pad=2)
|
48 |
+
ax = plt.gcf().axes[0]
|
49 |
+
ax.scatter(*canvas.to_uv(bbox.center), s=5, c="red")
|
50 |
+
plot_dense_rotations(ax, prob, w=0.005, s=1 / 25)
|
51 |
+
add_circle_inset(ax, uv)
|
52 |
+
fig2 = plt.gcf()
|
53 |
+
|
54 |
+
# Plot as interactive figure
|
55 |
+
latlon = proj.unproject(canvas.to_xy(uv))
|
56 |
+
bbox_latlon = proj.unproject(canvas.bbox)
|
57 |
+
plot = GeoPlotter(zoom=16.5)
|
58 |
+
plot.raster(map_viz, bbox_latlon, opacity=0.5)
|
59 |
+
plot.raster(likelihood_overlay(prob.numpy().max(-1)), proj.unproject(bbox))
|
60 |
+
plot.points(proj.latlonalt[:2], "red", name="location prior", size=10)
|
61 |
+
plot.points(latlon, "black", name="argmax", size=10, visible="legendonly")
|
62 |
+
plot.bbox(bbox_latlon, "blue", name="map tile")
|
63 |
+
|
64 |
+
coordinates = f"(latitude, longitude) = {tuple(latlon)}\nheading angle = {yaw:.2f}°"
|
65 |
+
return fig1, fig2, plot.fig, coordinates
|
66 |
+
|
67 |
+
|
68 |
+
examples = [
|
69 |
+
["assets/query_zurich_1.JPG", "ETH CAB Zurich", 128, 256],
|
70 |
+
["assets/query_vancouver_1.JPG", "Vancouver Waterfront Station", 128, 256],
|
71 |
+
["assets/query_vancouver_2.JPG", None, 128, 256],
|
72 |
+
["assets/query_vancouver_3.JPG", None, 128, 256],
|
73 |
+
]
|
74 |
+
|
75 |
+
description = """
|
76 |
+
<h1 align="center">
|
77 |
+
<ins>OrienterNet</ins>
|
78 |
+
<br>
|
79 |
+
Visual Localization in 2D Public Maps
|
80 |
+
<br>
|
81 |
+
with Neural Matching</h1>
|
82 |
+
<h3 align="center">
|
83 |
+
<a href="https://psarlin.com/orienternet" target="_blank">Project Page</a> |
|
84 |
+
<a href="https://arxiv.org/pdf/2304.02009.pdf" target="_blank">Paper</a> |
|
85 |
+
<a href="https://github.com/facebookresearch/OrienterNet" target="_blank">Code</a> |
|
86 |
+
<a href="https://youtu.be/wglW8jnupSs" target="_blank">Video</a>
|
87 |
+
</h3>
|
88 |
+
<p align="center">
|
89 |
+
OrienterNet finds the position and orientation of any image using OpenStreetMap.
|
90 |
+
Click on one of the provided examples or upload your own image!
|
91 |
+
</p>
|
92 |
+
"""
|
93 |
+
|
94 |
+
app = gr.Interface(
|
95 |
+
fn=run,
|
96 |
+
inputs=[
|
97 |
+
gr.File(file_types=["image"]),
|
98 |
+
gr.Textbox(
|
99 |
+
label="Prior location (optional)",
|
100 |
+
info="Required if the image metadata (EXIF) does not contain a GPS prior. "
|
101 |
+
"Enter an address or a street or building name.",
|
102 |
+
),
|
103 |
+
gr.Radio(
|
104 |
+
[64, 128, 256, 512],
|
105 |
+
value=128,
|
106 |
+
label="Search radius (meters)",
|
107 |
+
info="Depends on how coarse the prior location is.",
|
108 |
+
),
|
109 |
+
gr.Radio(
|
110 |
+
[64, 128, 256, 360],
|
111 |
+
value=256,
|
112 |
+
label="Number of rotations",
|
113 |
+
info="Reduce to scale to larger areas.",
|
114 |
+
),
|
115 |
+
],
|
116 |
+
outputs=[
|
117 |
+
gr.Plot(label="Inputs"),
|
118 |
+
gr.Plot(label="Outputs"),
|
119 |
+
gr.Plot(label="Interactive map"),
|
120 |
+
gr.Textbox(label="Predicted coordinates"),
|
121 |
+
],
|
122 |
+
description=description,
|
123 |
+
examples=examples,
|
124 |
+
cache_examples=True,
|
125 |
+
)
|
126 |
+
|
127 |
+
app.launch(share=False)
|