annotation_gui_gcp/lib/views/image_view.py (94 lines of code) (raw):
from typing import Dict, Any
from annotation_gui_gcp.lib.views.web_view import WebView, distinct_colors
def point_color(point_id: str) -> str:
hex_color = distinct_colors[divmod(hash(point_id), 19)[1]]
return hex_color
class ImageView(WebView):
def __init__(
self,
main_ui,
web_app,
route_prefix,
image_keys,
is_geo_reference,
):
super().__init__(main_ui, web_app, route_prefix)
self.main_ui = main_ui
self.image_manager = main_ui.image_manager
self.is_geo_reference = is_geo_reference
self.image_list = image_keys
self.app.add_url_rule(
f"{route_prefix}/image/<int:max_sz>/<path:path>",
f"{route_prefix}_image",
view_func=self.get_image,
)
def get_candidate_images(self):
return self.image_list
def get_image(self, path, max_sz):
return self.image_manager.get_image(path, max_sz)
def add_remove_update_point_observation(
self,
image_id,
point_coordinates=None, # normalized pixels
precision=None, # std. deviation in px / max(w,h)
):
gcp_manager = self.main_ui.gcp_manager
active_gcp = self.main_ui.curr_point
if active_gcp is None:
print("No point selected in the main UI. Doing nothing")
return
# Remove the observation for this point if it's already there
gcp_manager.remove_point_observation(
active_gcp, image_id, remove_latlon=self.is_geo_reference
)
# Add the new observation
if point_coordinates is not None:
assert precision is not None
self.main_ui.gcp_manager.add_point_observation(
active_gcp,
image_id,
point_coordinates,
precision=precision,
geo=None,
)
self.main_ui.populate_gcp_list()
def display_points(self):
pass
def highlight_gcp_reprojection(self, *args, **kwargs):
pass
def populate_image_list(self, *args, **kwargs):
pass
def sync_to_client(self):
"""
Sends all the data required to initialize or sync the image view
"""
# All images assigned to this view
image_list = self.get_candidate_images()
# Dict of images -> points
all_points_this_view = {
image: self.main_ui.gcp_manager.get_visible_points_coords(image)
for image in image_list
}
data = {
"points": all_points_this_view,
"selected_point": self.main_ui.curr_point,
"colors": {
point_id: point_color(point_id)
for point_id in self.main_ui.gcp_manager.points
},
}
self.send_sse_message(data)
def process_client_message(self, data: Dict[str, Any]) -> None:
command = data["event"]
if command not in (
"add_or_update_point_observation",
"remove_point_observation",
):
raise ValueError(f"Unknown commmand {command}")
if data["point_id"] != self.main_ui.curr_point:
print(data["point_id"], self.main_ui.curr_point)
print("Frontend sending an update for some other point. Ignoring")
return
if command == "add_or_update_point_observation":
self.add_remove_update_point_observation(
image_id=data["image_id"],
point_coordinates=data["xy"],
precision=data["norm_precision"],
)
else: # == "remove_point_observation":
self.add_remove_update_point_observation(
image_id=data["image_id"], point_coordinates=None
)