Exemple #1
0
    def get_data(self, host_dict):
        if self.type == 'landmarks-manual':
            need_remark_face = False
            redraw_needed = False
            while len(self.input_data) > 0:
                data = self.input_data[0]
                filepath, data_rects, data_landmarks = data.filepath, data.rects, data.landmarks
                is_frame_done = False

                if need_remark_face:  # need remark image from input data that already has a marked face?
                    need_remark_face = False
                    if len(
                            data_rects
                    ) != 0:  # If there was already a face then lock the rectangle to it until the mouse is clicked
                        self.rect = data_rects.pop()
                        self.landmarks = data_landmarks.pop()
                        data_rects.clear()
                        data_landmarks.clear()
                        redraw_needed = True
                        self.rect_locked = True
                        self.rect_size = (self.rect[2] - self.rect[0]) / 2
                        self.x = (self.rect[0] + self.rect[2]) / 2
                        self.y = (self.rect[1] + self.rect[3]) / 2

                if len(data_rects) == 0:
                    if self.cache_original_image[0] == filepath:
                        self.original_image = self.cache_original_image[1]
                    else:
                        self.original_image = imagelib.normalize_channels(
                            cv2_imread(filepath), 3)

                        self.cache_original_image = (filepath,
                                                     self.original_image)

                    (h, w, c) = self.original_image.shape
                    self.view_scale = 1.0 if self.manual_window_size == 0 else self.manual_window_size / (
                        h * (16.0 / 9.0))

                    if self.cache_image[0] == (h, w, c) + (self.view_scale,
                                                           filepath):
                        self.image = self.cache_image[1]
                    else:
                        self.image = cv2.resize(self.original_image, (int(
                            w * self.view_scale), int(h * self.view_scale)),
                                                interpolation=cv2.INTER_LINEAR)
                        self.cache_image = ((h, w, c) +
                                            (self.view_scale, filepath),
                                            self.image)

                    (h, w, c) = self.image.shape

                    sh = (0, 0, w, min(100, h))
                    if self.cache_text_lines_img[0] == sh:
                        self.text_lines_img = self.cache_text_lines_img[1]
                    else:
                        self.text_lines_img = (imagelib.get_draw_text_lines(
                            self.image, sh, [
                                '[Mouse click] - lock/unlock selection',
                                '[Mouse wheel] - change rect',
                                '[Enter] / [Space] - confirm / skip frame',
                                '[,] [.]- prev frame, next frame. [Q] - skip remaining frames',
                                '[a] - accuracy on/off (more fps)',
                                '[h] - hide this help'
                            ], (1, 1, 1)) * 255).astype(np.uint8)

                        self.cache_text_lines_img = (sh, self.text_lines_img)

                    while True:
                        io.process_messages(0.0001)

                        new_x = self.x
                        new_y = self.y
                        new_rect_size = self.rect_size

                        mouse_events = io.get_mouse_events(self.wnd_name)
                        for ev in mouse_events:
                            (x, y, ev, flags) = ev
                            if ev == io.EVENT_MOUSEWHEEL and not self.rect_locked:
                                mod = 1 if flags > 0 else -1
                                diff = 1 if new_rect_size <= 40 else np.clip(
                                    new_rect_size / 10, 1, 10)
                                new_rect_size = max(5,
                                                    new_rect_size + diff * mod)
                            elif ev == io.EVENT_LBUTTONDOWN:
                                self.rect_locked = not self.rect_locked
                                self.extract_needed = True
                            elif not self.rect_locked:
                                new_x = np.clip(x, 0, w - 1) / self.view_scale
                                new_y = np.clip(y, 0, h - 1) / self.view_scale

                        key_events = io.get_key_events(self.wnd_name)
                        key, chr_key, ctrl_pressed, alt_pressed, shift_pressed = key_events[
                            -1] if len(key_events) > 0 else (0, 0, False,
                                                             False, False)

                        if key == ord('\r') or key == ord('\n'):
                            #confirm frame
                            is_frame_done = True
                            data_rects.append(self.rect)
                            data_landmarks.append(self.landmarks)
                            break
                        elif key == ord(' '):
                            #confirm skip frame
                            is_frame_done = True
                            break
                        elif key == ord(',') and len(self.result) > 0:
                            #go prev frame

                            if self.rect_locked:
                                self.rect_locked = False
                                # Only save the face if the rect is still locked
                                data_rects.append(self.rect)
                                data_landmarks.append(self.landmarks)

                            self.input_data.insert(0, self.result.pop())
                            io.progress_bar_inc(-1)
                            need_remark_face = True

                            break
                        elif key == ord('.'):
                            #go next frame

                            if self.rect_locked:
                                self.rect_locked = False
                                # Only save the face if the rect is still locked
                                data_rects.append(self.rect)
                                data_landmarks.append(self.landmarks)

                            need_remark_face = True
                            is_frame_done = True
                            break
                        elif key == ord('q'):
                            #skip remaining

                            if self.rect_locked:
                                self.rect_locked = False
                                data_rects.append(self.rect)
                                data_landmarks.append(self.landmarks)

                            while len(self.input_data) > 0:
                                self.result.append(self.input_data.pop(0))
                                io.progress_bar_inc(1)

                            break

                        elif key == ord('h'):
                            self.hide_help = not self.hide_help
                            break
                        elif key == ord('a'):
                            self.landmarks_accurate = not self.landmarks_accurate
                            break

                        if self.x != new_x or \
                           self.y != new_y or \
                           self.rect_size != new_rect_size or \
                           self.extract_needed or \
                           redraw_needed:
                            self.x = new_x
                            self.y = new_y
                            self.rect_size = new_rect_size
                            self.rect = (int(self.x - self.rect_size),
                                         int(self.y - self.rect_size),
                                         int(self.x + self.rect_size),
                                         int(self.y + self.rect_size))

                            if redraw_needed:
                                redraw_needed = False
                                return ExtractSubprocessor.Data(
                                    filepath,
                                    landmarks_accurate=self.landmarks_accurate)
                            else:
                                return ExtractSubprocessor.Data(
                                    filepath,
                                    rects=[self.rect],
                                    landmarks_accurate=self.landmarks_accurate)

                else:
                    is_frame_done = True

                if is_frame_done:
                    self.result.append(data)
                    self.input_data.pop(0)
                    io.progress_bar_inc(1)
                    self.extract_needed = True
                    self.rect_locked = False
        else:
            if len(self.input_data) > 0:
                return self.input_data.pop(0)

        return None
Exemple #2
0
    def get_data(self, host_dict):
        if self.type == 'landmarks-manual':
            need_remark_face = False
            while len(self.input_data) > 0:
                data = self.input_data[0]
                filepath, data_rects, data_landmarks = data.filepath, data.rects, data.landmarks
                is_frame_done = False

                if self.image_filepath != filepath:
                    self.image_filepath = filepath
                    if self.cache_original_image[0] == filepath:
                        self.original_image = self.cache_original_image[1]
                    else:
                        self.original_image = imagelib.normalize_channels(
                            cv2_imread(filepath), 3)

                        self.cache_original_image = (filepath,
                                                     self.original_image)

                    (h, w, c) = self.original_image.shape
                    self.view_scale = 1.0 if self.manual_window_size == 0 else self.manual_window_size / (
                        h * (16.0 / 9.0))

                    if self.cache_image[0] == (h, w, c) + (self.view_scale,
                                                           filepath):
                        self.image = self.cache_image[1]
                    else:
                        self.image = cv2.resize(self.original_image, (int(
                            w * self.view_scale), int(h * self.view_scale)),
                                                interpolation=cv2.INTER_LINEAR)
                        self.cache_image = ((h, w, c) +
                                            (self.view_scale, filepath),
                                            self.image)

                    (h, w, c) = self.image.shape

                    sh = (0, 0, w, min(100, h))
                    if self.cache_text_lines_img[0] == sh:
                        self.text_lines_img = self.cache_text_lines_img[1]
                    else:
                        self.text_lines_img = (imagelib.get_draw_text_lines(
                            self.image, sh, [
                                '[L Mouse click] - lock/unlock selection. [Mouse wheel] - change rect',
                                '[R Mouse Click] - manual face rectangle',
                                '[Enter] / [Space] - confirm / skip frame',
                                '[,] [.]- prev frame, next frame. [Q] - skip remaining frames',
                                '[a] - accuracy on/off (more fps)',
                                '[h] - hide this help'
                            ], (1, 1, 1)) * 255).astype(np.uint8)

                        self.cache_text_lines_img = (sh, self.text_lines_img)

                if need_remark_face:  # need remark image from input data that already has a marked face?
                    need_remark_face = False
                    if len(
                            data_rects
                    ) != 0:  # If there was already a face then lock the rectangle to it until the mouse is clicked
                        self.rect = data_rects.pop()
                        self.landmarks = data_landmarks.pop()
                        data_rects.clear()
                        data_landmarks.clear()

                        self.rect_locked = True
                        self.rect_size = (self.rect[2] - self.rect[0]) / 2
                        self.x = (self.rect[0] + self.rect[2]) / 2
                        self.y = (self.rect[1] + self.rect[3]) / 2
                        self.redraw()

                if len(data_rects) == 0:
                    (h, w, c) = self.image.shape
                    while True:
                        io.process_messages(0.0001)
                        self.ea.loop()

                        if not self.force_landmarks:
                            new_x = self.x
                            new_y = self.y

                        new_rect_size = self.rect_size

                        mouse_events = io.get_mouse_events(self.wnd_name)
                        for ev in mouse_events:
                            (x, y, ev, flags) = ev
                            if ev == io.EVENT_MOUSEWHEEL and not self.rect_locked:
                                mod = 1 if flags > 0 else -1
                                diff = 1 if new_rect_size <= 40 else np.clip(
                                    new_rect_size / 10, 1, 10)
                                new_rect_size = max(5,
                                                    new_rect_size + diff * mod)
                            elif ev == io.EVENT_LBUTTONDOWN:
                                if self.force_landmarks:
                                    self.x = new_x
                                    self.y = new_y
                                    self.force_landmarks = False
                                    self.rect_locked = True
                                    self.redraw()
                                else:
                                    self.rect_locked = not self.rect_locked
                                    self.extract_needed = True
                            elif ev == io.EVENT_RBUTTONDOWN:
                                self.ea.right_btn_down = True
                                # self.force_landmarks = not self.force_landmarks
                                # if self.force_landmarks:
                                #     self.rect_locked = False
                            elif not self.rect_locked:
                                new_x = np.clip(x, 0, w - 1) / self.view_scale
                                new_y = np.clip(y, 0, h - 1) / self.view_scale

                        key_events = io.get_key_events(self.wnd_name)
                        key, chr_key, ctrl_pressed, alt_pressed, shift_pressed = key_events[
                            -1] if len(key_events) > 0 else (0, 0, False,
                                                             False, False)

                        if self.ea.right_btn_down and self.rect_locked:
                            is_frame_done = True
                            data_rects.append(self.rect)
                            data_landmarks.append(self.landmarks)
                            self.ea.last_outer = self.ea.cur_outer
                            self.ea.last_landmarks = self.ea.cur_landmarks
                            self.ea.auto = True
                            break
                        elif key == ord('s'):
                            self.ea.auto = False
                            break
                        elif self.ea.auto and len(
                                self.ea.last_outer) > 0 and len(
                                    self.ea.last_landmarks) > 0:
                            # 根据上次的外框算出这次的x/y,以及外框大小
                            border_ratio = 0.6
                            last_mid = F.mid_point_by_range(
                                self.ea.last_landmarks)
                            last_border = np.linalg.norm(
                                np.array(self.ea.last_outer[0]) -
                                np.array(self.ea.last_outer[1]))
                            last_area = F.poly_area(self.ea.last_outer)
                            x, y = last_mid
                            new_x = np.clip(x, 0, w - 1) / self.view_scale
                            new_y = np.clip(y, 0, h - 1) / self.view_scale
                            new_rect_size = last_border / 2 / self.view_scale * border_ratio
                            # make sure rect and landmarks have been refreshed
                            if len(self.ea.cur_outer) != 0:
                                # 根据本次外框大小算是否valid,通过边长,面积,角度
                                # temp_mid = F.mid_point(self.temp_outer)
                                cur_mid = F.mid_point_by_range(
                                    self.ea.cur_landmarks)
                                dist = np.linalg.norm(
                                    np.array(cur_mid) - np.array(last_mid))
                                dist_r = dist / last_border
                                temp_area = F.poly_area(self.ea.cur_outer)
                                area_r = temp_area / last_area
                                v0 = np.array(last_mid) - np.array(
                                    self.ea.last_outer[0])
                                v1 = np.array(cur_mid) - np.array(
                                    self.ea.cur_outer[0])
                                angle = math.fabs(F.angle_between(v0, v1))
                                if dist_r < 0.5 and 0.5 < area_r < 1.5 and angle < 0.7:
                                    is_frame_done = True
                                    self.ea.last_outer = self.ea.cur_outer
                                    self.ea.last_landmarks = self.ea.cur_landmarks
                                    data_rects.append(self.rect)
                                    data_landmarks.append(self.landmarks)
                                    self.ea.auto = True
                                    break
                                elif self.x != new_x or self.y != new_y:
                                    # 可以在等一轮更新后试一下
                                    pass
                                else:
                                    self.ea.auto = False
                                    F.beep()
                        elif key == ord('n') and len(self.result) > 0:
                            # go prev frame without save and clear result
                            self.rect_locked = False
                            n = 10 if shift_pressed else 1
                            while n > 0 and len(self.result) > 0:
                                self.input_data.insert(0, self.result.pop())
                                self.input_data[0].rects.clear()
                                self.input_data[0].landmarks.clear()
                                io.progress_bar_inc(-1)
                                n -= 1
                            # 直接无视之前的结果,重新标注
                            self.extract_needed = True
                            break
                        elif key == ord('m') and len(self.input_data) > 0:
                            # go next frame without save
                            self.rect_locked = False
                            n = 10 if shift_pressed else 1
                            while n > 0 and len(self.input_data) > 0:
                                self.result.append(self.input_data.pop(0))
                                io.progress_bar_inc(1)
                                n -= 1
                            # 直接无视之前的结果,重新标注
                            self.extract_needed = True
                            break
                        elif key == ord('\r') or key == ord('\n'):
                            #confirm frame
                            is_frame_done = True
                            data_rects.append(self.rect)
                            data_landmarks.append(self.landmarks)
                            break
                        elif key == ord(' '):
                            #confirm skip frame
                            is_frame_done = True
                            break
                        elif key == ord(',') and len(self.result) > 0:
                            #go prev frame

                            if self.rect_locked:
                                self.rect_locked = False
                                # Only save the face if the rect is still locked
                                data_rects.append(self.rect)
                                data_landmarks.append(self.landmarks)

                            self.input_data.insert(0, self.result.pop())
                            io.progress_bar_inc(-1)
                            need_remark_face = True

                            break
                        elif key == ord('.'):
                            #go next frame

                            if self.rect_locked:
                                self.rect_locked = False
                                # Only save the face if the rect is still locked
                                data_rects.append(self.rect)
                                data_landmarks.append(self.landmarks)

                            need_remark_face = True
                            is_frame_done = True
                            break
                        elif key == ord('q'):
                            #skip remaining

                            if self.rect_locked:
                                self.rect_locked = False
                                data_rects.append(self.rect)
                                data_landmarks.append(self.landmarks)

                            while len(self.input_data) > 0:
                                self.result.append(self.input_data.pop(0))
                                io.progress_bar_inc(1)

                            break

                        elif key == ord('h'):
                            self.hide_help = not self.hide_help
                            break
                        elif key == ord('a'):
                            self.landmarks_accurate = not self.landmarks_accurate
                            break

                        if self.force_landmarks:
                            pt2 = np.float32([new_x, new_y])
                            pt1 = np.float32([self.x, self.y])

                            pt_vec_len = npla.norm(pt2 - pt1)
                            pt_vec = pt2 - pt1
                            if pt_vec_len != 0:
                                pt_vec /= pt_vec_len

                            self.rect_size = pt_vec_len
                            self.rect = (int(self.x - self.rect_size),
                                         int(self.y - self.rect_size),
                                         int(self.x + self.rect_size),
                                         int(self.y + self.rect_size))

                            if pt_vec_len > 0:
                                lmrks = np.concatenate(
                                    (np.zeros((17, 2), np.float32),
                                     LandmarksProcessor.landmarks_2D),
                                    axis=0)
                                lmrks -= lmrks[30:31, :]
                                mat = cv2.getRotationMatrix2D(
                                    (0, 0), -np.arctan2(pt_vec[1], pt_vec[0]) *
                                    180 / math.pi, pt_vec_len)
                                mat[:, 2] += (self.x, self.y)
                                self.landmarks = LandmarksProcessor.transform_points(
                                    lmrks, mat)

                            self.redraw()

                        elif self.x != new_x or \
                           self.y != new_y or \
                           self.rect_size != new_rect_size or \
                           self.extract_needed:
                            self.x = new_x
                            self.y = new_y
                            self.rect_size = new_rect_size
                            self.rect = (int(self.x - self.rect_size),
                                         int(self.y - self.rect_size),
                                         int(self.x + self.rect_size),
                                         int(self.y + self.rect_size))

                            return ExtractSubprocessor.Data(
                                filepath,
                                rects=[self.rect],
                                landmarks_accurate=self.landmarks_accurate)

                else:
                    is_frame_done = True

                if is_frame_done:
                    self.result.append(data)
                    self.input_data.pop(0)
                    io.progress_bar_inc(1)
                    self.extract_needed = True
                    self.rect_locked = False
                    self.ea.cur_outer = []
        else:
            if len(self.input_data) > 0:
                return self.input_data.pop(0)

        return None