Exemplo n.º 1
0
 def __init__(self, interface, verbose):
     self.interface = interface
     self.alignments = interface.alignments
     self.frames = interface.frames
     self.extract = Extract(None, "manual",
                            initialize_only=True, verbose=verbose)
     self.mouse_state = None
     self.last_move = None
     self.center = None
     self.dims = None
     self.media = {"frame_id": None,
                   "image": None,
                   "bounding_box": list(),
                   "bounding_last": list(),
                   "bounding_box_orig": list()}
Exemplo n.º 2
0
class MouseHandler():
    """ Manual Extraction """
    def __init__(self, interface, verbose):
        self.interface = interface
        self.alignments = interface.alignments
        self.frames = interface.frames
        self.extract = Extract(None,
                               "manual",
                               initialize_only=True,
                               verbose=verbose)
        self.mouse_state = None
        self.last_move = None
        self.center = None
        self.dims = None
        self.media = {
            "frame_id": None,
            "image": None,
            "bounding_box": list(),
            "bounding_box_orig": list()
        }

    def on_event(self, event, x, y, flags, param):
        """ Handle the mouse events """
        if self.interface.get_edit_mode() != "Edit":
            return
        elif not self.mouse_state and event not in (cv2.EVENT_LBUTTONDOWN,
                                                    cv2.EVENT_MBUTTONDOWN):
            return

        self.initialize()

        if event in (cv2.EVENT_LBUTTONUP, cv2.EVENT_MBUTTONUP):
            self.mouse_state = None
            self.last_move = None
        elif event == cv2.EVENT_LBUTTONDOWN:
            self.mouse_state = "left"
            self.set_bounding_box(x, y)
        elif event == cv2.EVENT_MBUTTONDOWN:
            self.mouse_state = "middle"
        elif event == cv2.EVENT_MOUSEMOVE:
            if self.mouse_state == "left":
                self.move_bounding_box(x, y)
            elif self.mouse_state == "middle":
                self.resize_bounding_box(x, y)

    def initialize(self):
        """ Update changed parameters """
        frame = self.interface.get_frame_name()
        if frame == self.media["frame_id"]:
            return
        self.media["frame_id"] = frame
        self.media["image"] = self.frames.load_image(frame)

    def set_bounding_box(self, pt_x, pt_y):
        """ Select or create bounding box """
        if self.interface.get_selected_face_id() is None:
            self.check_click_location(pt_x, pt_y)

        if self.interface.get_selected_face_id() is not None:
            self.dims_from_alignment()
        else:
            self.dims_from_image()

        self.move_bounding_box(pt_x, pt_y)

    def check_click_location(self, pt_x, pt_y):
        """ Check whether the point clicked is within an existing
            bounding box and set face_id """
        frame = self.media["frame_id"]
        alignments = self.alignments.get_alignments_for_frame(frame)

        for idx, alignment in enumerate(alignments):
            left = alignment["x"]
            right = alignment["x"] + alignment["w"]
            top = alignment["y"]
            bottom = alignment["y"] + alignment["h"]

            if left <= pt_x <= right and top <= pt_y <= bottom:
                self.interface.set_state_value("edit", "selected", idx)
                break

    def dims_from_alignment(self):
        """ Set the height and width of bounding box from alignment """
        frame = self.media["frame_id"]
        face_id = self.interface.get_selected_face_id()
        alignment = self.alignments.get_alignments_for_frame(frame)[face_id]
        self.dims = (alignment["w"], alignment["h"])

    def dims_from_image(self):
        """ Set the height and width of bounding
            box at 10% of longest axis """
        size = max(self.media["image"].shape[:2])
        dim = int(size / 10.00)
        self.dims = (dim, dim)

    def bounding_from_center(self):
        """ Get bounding X Y from center """
        pt_x, pt_y = self.center
        width, height = self.dims
        scale = self.interface.get_frame_scaling()
        self.media["bounding_box"] = [
            int((pt_x / scale) - width / 2),
            int((pt_y / scale) - height / 2),
            int((pt_x / scale) + width / 2),
            int((pt_y / scale) + height / 2)
        ]

    def move_bounding_box(self, pt_x, pt_y):
        """ Move the bounding box """
        self.center = (pt_x, pt_y)
        self.bounding_from_center()
        self.update_landmarks()

    def resize_bounding_box(self, pt_x, pt_y):
        """ Resize the bounding box """
        if not self.dims:
            return
        if not self.last_move:
            self.last_move = (pt_x, pt_y)
            self.media["bounding_box_orig"] = self.media["bounding_box"]

        move_x = int(pt_x - self.last_move[0])
        move_y = int(self.last_move[1] - pt_y)

        original = self.media["bounding_box_orig"]
        updated = self.media["bounding_box"]

        updated[0] = min(self.center[0] - 10, original[0] - move_x)
        updated[1] = min(self.center[1] - 10, original[1] - move_y)
        updated[2] = max(self.center[0] + 10, original[2] + move_x)
        updated[3] = max(self.center[1] + 10, original[3] + move_y)
        self.update_landmarks()
        self.last_move = (pt_x, pt_y)

    def update_landmarks(self):
        """ Update the landmarks """
        self.extract.execute(self.media["image"],
                             manual_face=self.media["bounding_box"])
        landmarks = self.extract.landmarks[0][1]
        left, top, right, bottom = self.media["bounding_box"]
        alignment = {
            "x": left,
            "w": right - left,
            "y": top,
            "h": bottom - top,
            "landmarksXY": landmarks
        }
        frame = self.media["frame_id"]

        if self.interface.get_selected_face_id() is None:
            idx = self.alignments.add_alignment(frame, alignment)
            self.interface.set_state_value("edit", "selected", idx)
        else:
            self.alignments.update_alignment(
                frame, self.interface.get_selected_face_id(), alignment)
            self.interface.set_redraw(True)

        self.interface.state["edit"]["updated"] = True
        self.interface.state["edit"]["update_faces"] = True