diff --git a/mel/cmd/rotomapedit.py b/mel/cmd/rotomapedit.py index 9875418f..ba96c483 100644 --- a/mel/cmd/rotomapedit.py +++ b/mel/cmd/rotomapedit.py @@ -16,6 +16,7 @@ Press '2' for mask edit mode. Press '3' for bounding area mode. Press '4' for mole marking mode. + Press '5' for mole compare boundary mode. Press '0' for auto-mole debug mode. In 'mole edit' mode: @@ -409,6 +410,41 @@ def on_key(self, editor, key): editor.show_current() +class MoleCompareBoundaryController: + def __init__(self): + pass + + def on_mouse_event(self, editor, event): + # Import pygame as late as possible, to avoid displaying its + # startup-text where it is not actually used. + import pygame + + if event.type != pygame.MOUSEBUTTONDOWN: + return + + key_mods = pygame.key.get_mods() + mouse_x, mouse_y = pygame.mouse.get_pos() + + if event.button == 1: + if key_mods & pygame.KMOD_SHIFT: + editor.remove_mole(mouse_x, mouse_y) + else: + editor.add_mole(mouse_x, mouse_y) + + def pre_key(self, editor, key): + pass + + def on_key(self, editor, key): + # Import pygame as late as possible, to avoid displaying its + # startup-text where it is not actually used. + import pygame + + if key == pygame.K_a: + is_alt = editor.marked_mole_overlay.is_accentuate_marked_mode + editor.marked_mole_overlay.is_accentuate_marked_mode = not is_alt + editor.show_current() + + class BoundingAreaController: def __init__(self): pass @@ -468,6 +504,7 @@ def __init__(self, editor, follow, copy_to_clipboard, visit_list, logger): ) self.maskedit_controller = MaskEditController() self.molemark_controller = MoleMarkController() + self.molecompareboundary_controller = MoleCompareBoundaryController() self.boundingarea_controller = BoundingAreaController() self.automoledebug_controller = AutomoleDebugController() self.current_controller = self.moleedit_controller @@ -546,6 +583,11 @@ def on_key(self, editor, key): self.current_controller = self.molemark_controller self._logger.reset(mode="molemark") editor.set_molemark_mode() + elif key == pygame.K_5: + # Switch to mole compare boundary mode + self.current_controller = self.molecompareboundary_controller + self._logger.reset(mode="molecompareboundary") + editor.set_molecompareboundary_mode() elif key == pygame.K_b: # Go back in the visit list if self._visit_list: diff --git a/mel/rotomap/display.py b/mel/rotomap/display.py index 64780a98..7d57106d 100644 --- a/mel/rotomap/display.py +++ b/mel/rotomap/display.py @@ -265,6 +265,36 @@ def _draw_markers(self, image, transform): return image +class MoleCompareBoundaryOverlay: + """An overlay to show how much context a rotomap compare window will + show.""" + + def __init__(self): + self.moles = None + + def __call__(self, image, transform): + return self._draw(image, transform) + + def _draw(self, image, transform): + # Reveal the moles that have been marked, whilst still showing + # markers. This is good for verifying that markers are actually + # positioned on moles. + + mask_radius = 50 + + image = image.copy() // 2 + mask = numpy.zeros((*image.shape[:2], 1), numpy.uint8) + + for mole in self.moles: + x, y = transform.imagexy_to_transformedxy(mole["x"], mole["y"]) + cv2.circle(mask, (x, y), mask_radius, 255, -1) + + masked_faded = cv2.bitwise_and(image, image, mask=mask) + image = cv2.add(masked_faded, image) + + return image + + class BoundingAreaOverlay: """An overlay to show the bounding area, if any.""" @@ -312,6 +342,7 @@ class EditorMode(enum.Enum): edit_mask = 2 bounding_area = 3 mole_mark = 4 + mole_compare_boundary = 5 debug_automole = 0 @@ -328,6 +359,7 @@ def __init__(self, directory_list, screen): self._follow = None self._mole_overlay = MoleMarkerOverlay(self._uuid_to_tricolour) self.marked_mole_overlay = MarkedMoleOverlay() + self.mole_compare_boundary_overlay = MoleCompareBoundaryOverlay() self.bounding_area_overlay = BoundingAreaOverlay() self._status_overlay = StatusOverlay() self.show_current() @@ -363,6 +395,10 @@ def set_molemark_mode(self): self._mode = EditorMode.mole_mark self.show_current() + def set_molecompareboundary_mode(self): + self._mode = EditorMode.mole_compare_boundary + self.show_current() + def set_status(self, text): self._status_overlay.text = text @@ -471,6 +507,11 @@ def show_current(self): elif self._mode is EditorMode.mole_mark: self.marked_mole_overlay.moles = self.moledata.moles self.display.show_current(image, self.marked_mole_overlay) + elif self._mode is EditorMode.mole_compare_boundary: + self.mole_compare_boundary_overlay.moles = self.moledata.moles + self.display.show_current( + image, self.mole_compare_boundary_overlay + ) else: raise Exception("Unknown mode", self._mode)