Exemple #1
0
    def onClientProcessData(self, data):
        filename_path = Path( data[0] )

        image = cv2.imread( str(filename_path) )
        if image is None:
            print ( 'Failed to extract %s, reason: cv2.imread() fail.' % ( str(filename_path) ) )
        else:
            if self.type == 'rects':
                rects = self.e.extract_from_bgr (image)
                return [str(filename_path), rects]

            elif self.type == 'landmarks':
                rects = data[1]   
                landmarks = self.e.extract_from_bgr (image, rects)                    
                return [str(filename_path), landmarks]

            elif self.type == 'final':     
                result = []
                faces = data[1]
                
                if self.debug:
                    debug_output_file = '{}_{}'.format( str(Path(str(self.output_path) + '_debug') / filename_path.stem),  'debug.png')
                    debug_image = image.copy()
                    
                for (face_idx, face) in enumerate(faces):         
                    output_file = '{}_{}{}'.format(str(self.output_path / filename_path.stem), str(face_idx), '.png')
                    
                    rect = face[0]
                    image_landmarks = np.array(face[1])

                    if self.debug:
                        facelib.LandmarksProcessor.draw_rect_landmarks (debug_image, rect, image_landmarks, self.image_size, self.face_type)

                    if self.face_type == FaceType.MARK_ONLY:                        
                        face_image = image
                        face_image_landmarks = image_landmarks
                    else:
                        image_to_face_mat = facelib.LandmarksProcessor.get_transform_mat (image_landmarks, self.image_size, self.face_type)       
                        face_image = cv2.warpAffine(image, image_to_face_mat, (self.image_size, self.image_size), cv2.INTER_LANCZOS4)
                        face_image_landmarks = facelib.LandmarksProcessor.transform_points (image_landmarks, image_to_face_mat)
                    
                    cv2.imwrite(output_file, face_image)

                    DFLPNG.embed_data(output_file, face_type = FaceType.toString(self.face_type),
                                                   landmarks = face_image_landmarks.tolist(),
                                                   yaw_value = facelib.LandmarksProcessor.calc_face_yaw (face_image_landmarks),
                                                   pitch_value = facelib.LandmarksProcessor.calc_face_pitch (face_image_landmarks),
                                                   source_filename = filename_path.name,
                                                   source_rect=  rect,
                                                   source_landmarks = image_landmarks.tolist()
                                        )  
                        
                    result.append (output_file)
                    
                if self.debug:
                    cv2.imwrite(debug_output_file, debug_image )
                    
                return result       
        return None
Exemple #2
0
        def process_data(self, data):
            filename_path = Path(data.filename)

            filename_path_str = str(filename_path)
            if self.cached_image[0] == filename_path_str:
                image = self.cached_image[
                    1]  #cached image for manual extractor
            else:
                image = cv2_imread(filename_path_str)

                if image is None:
                    self.log_err(
                        'Failed to extract %s, reason: cv2_imread() fail.' %
                        (str(filename_path)))
                    return data

                image = imagelib.normalize_channels(image, 3)
                h, w, ch = image.shape

                wm, hm = w % 2, h % 2
                if wm + hm != 0:  #fix odd image
                    image = image[0:h - hm, 0:w - wm, :]
                self.cached_image = (filename_path_str, image)

            src_dflimg = None
            h, w, ch = image.shape
            if h == w:
                #extracting from already extracted jpg image?
                if filename_path.suffix == '.png':
                    src_dflimg = DFLPNG.load(str(filename_path))
                if filename_path.suffix == '.jpg':
                    src_dflimg = DFLJPG.load(str(filename_path))

            if 'rects' in self.type:
                if min(w, h) < 128:
                    self.log_err('Image is too small %s : [%d, %d]' %
                                 (str(filename_path), w, h))
                    data.rects = []
                else:
                    for rot in ([0, 90, 270, 180]):
                        data.rects_rotation = rot
                        if rot == 0:
                            rotated_image = image
                        elif rot == 90:
                            rotated_image = image.swapaxes(0, 1)[:, ::-1, :]
                        elif rot == 180:
                            rotated_image = image[::-1, ::-1, :]
                        elif rot == 270:
                            rotated_image = image.swapaxes(0, 1)[::-1, :, :]

                        rects = data.rects = self.e.extract(rotated_image,
                                                            is_bgr=True)
                        if len(rects) != 0:
                            break

                return data

            elif self.type == 'landmarks':

                if data.rects_rotation == 0:
                    rotated_image = image
                elif data.rects_rotation == 90:
                    rotated_image = image.swapaxes(0, 1)[:, ::-1, :]
                elif data.rects_rotation == 180:
                    rotated_image = image[::-1, ::-1, :]
                elif data.rects_rotation == 270:
                    rotated_image = image.swapaxes(0, 1)[::-1, :, :]

                data.landmarks = self.e.extract(
                    rotated_image,
                    data.rects,
                    self.second_pass_e if
                    (src_dflimg is None and data.landmarks_accurate) else None,
                    is_bgr=True)
                if data.rects_rotation != 0:
                    for i, (rect,
                            lmrks) in enumerate(zip(data.rects,
                                                    data.landmarks)):
                        new_rect, new_lmrks = rect, lmrks
                        (l, t, r, b) = rect
                        if data.rects_rotation == 90:
                            new_rect = (t, h - l, b, h - r)
                            if lmrks is not None:
                                new_lmrks = lmrks[:, ::-1].copy()
                                new_lmrks[:, 1] = h - new_lmrks[:, 1]
                        elif data.rects_rotation == 180:
                            if lmrks is not None:
                                new_rect = (w - l, h - t, w - r, h - b)
                                new_lmrks = lmrks.copy()
                                new_lmrks[:, 0] = w - new_lmrks[:, 0]
                                new_lmrks[:, 1] = h - new_lmrks[:, 1]
                        elif data.rects_rotation == 270:
                            new_rect = (w - b, l, w - t, r)
                            if lmrks is not None:
                                new_lmrks = lmrks[:, ::-1].copy()
                                new_lmrks[:, 0] = w - new_lmrks[:, 0]
                        data.rects[i], data.landmarks[i] = new_rect, new_lmrks

                return data

            elif self.type == 'final':
                data.final_output_files = []
                rects = data.rects
                landmarks = data.landmarks

                if self.debug_dir is not None:
                    debug_output_file = str(
                        Path(self.debug_dir) / (filename_path.stem + '.jpg'))
                    debug_image = image.copy()

                if src_dflimg is not None and len(rects) != 1:
                    # if re-extracting from dflimg and more than 1 or zero faces detected:
                    # don't process and just copy it
                    print("src_dflimg is not None and len(rects) != 1",
                          str(filename_path))
                    output_file = str(self.final_output_path /
                                      filename_path.name)
                    if str(filename_path) != str(output_file):
                        shutil.copy(str(filename_path), str(output_file))
                    data.final_output_files.append(output_file)
                else:
                    face_idx = 0
                    for rect, image_landmarks in zip(rects, landmarks):
                        if src_dflimg is not None and face_idx > 1:
                            #cannot extract more than 1 face from dflimg
                            break

                        if image_landmarks is None:
                            continue

                        rect = np.array(rect)
                        rect_area = mathlib.polygon_area(
                            np.array(rect[[0, 2, 2, 0]]),
                            np.array(rect[[1, 1, 3, 3]]))

                        # `self.image_size` is the output size for the entire process,
                        # we don't want to overwrite it
                        face_image_size = self.image_size
                        if face_image_size == 0 and self.face_type != FaceType.MARK_ONLY:
                            face_image_size = LandmarksProcessor.calc_image_size_for_unscaled(
                                image_landmarks, self.face_type)
                            # if landmarks are bad, could get HUGE scale...
                            # ...so set a max size, same as input image biggest
                            # dimension
                            face_image_size = min(face_image_size, max(w, h))

                        if self.face_type == FaceType.MARK_ONLY:
                            image_to_face_mat = None
                            face_image = image
                            face_image_landmarks = image_landmarks
                        else:
                            image_to_face_mat = LandmarksProcessor.get_transform_mat(
                                image_landmarks, face_image_size,
                                self.face_type)
                            face_image = cv2.warpAffine(
                                image, image_to_face_mat,
                                (face_image_size, face_image_size),
                                cv2.INTER_LANCZOS4)
                            face_image_landmarks = LandmarksProcessor.transform_points(
                                image_landmarks, image_to_face_mat)
                            landmarks_bbox = LandmarksProcessor.transform_points(
                                [(0, 0), (0, face_image_size - 1),
                                 (face_image_size - 1, face_image_size - 1),
                                 (face_image_size - 1, 0)], image_to_face_mat,
                                True)
                            landmarks_area = mathlib.polygon_area(
                                landmarks_bbox[:, 0], landmarks_bbox[:, 1])

                            # get rid of faces which umeyama-landmark-area > 4*detector-rect-area
                            if self.face_type not in (
                                    FaceType.HEAD, FaceType.HEAD_NO_ALIGN
                            ) and landmarks_area > 4 * rect_area:
                                continue

                            if self.debug_dir is not None:
                                LandmarksProcessor.draw_rect_landmarks(
                                    debug_image,
                                    rect,
                                    image_landmarks,
                                    face_image_size,
                                    self.face_type,
                                    transparent_mask=True)

                        if filename_path.suffix == '.jpg':
                            #if extracting from dflimg and jpg copy it in order not to lose quality
                            output_file = '{}_{}{}'.format(
                                str(self.final_output_path /
                                    filename_path.stem), str(face_idx), '.jpg')
                            if str(filename_path) != str(output_file):
                                shutil.copy(str(filename_path),
                                            str(output_file))
                            cv2_imwrite(output_file, face_image,
                                        [int(cv2.IMWRITE_JPEG_QUALITY), 95])
                            DFLJPG.embed_data(
                                output_file,
                                face_type=FaceType.toString(self.face_type),
                                landmarks=face_image_landmarks.tolist(),
                                source_filename=filename_path.name,
                                source_rect=rect,
                                source_landmarks=image_landmarks.tolist(),
                                image_to_face_mat=image_to_face_mat,
                                pitch_yaw_roll=data.pitch_yaw_roll)
                        else:
                            output_file = '{}_{}{}'.format(
                                str(self.final_output_path /
                                    filename_path.stem), str(face_idx), '.png')
                            cv2_imwrite(output_file, face_image,
                                        [int(cv2.IMWRITE_PNG_COMPRESSION), 3])
                            DFLPNG.embed_data(
                                output_file,
                                face_type=FaceType.toString(self.face_type),
                                landmarks=face_image_landmarks.tolist(),
                                source_filename=filename_path.name,
                                source_rect=rect,
                                source_landmarks=image_landmarks.tolist(),
                                image_to_face_mat=image_to_face_mat,
                                pitch_yaw_roll=data.pitch_yaw_roll)

                        data.final_output_files.append(output_file)
                        face_idx += 1
                    data.faces_detected = face_idx

                if self.debug_dir is not None:
                    cv2_imwrite(debug_output_file, debug_image,
                                [int(cv2.IMWRITE_JPEG_QUALITY), 50])

                return data

            elif self.type == 'fanseg':
                if src_dflimg is not None:
                    fanseg_mask = self.e.extract(image / 255.0)
                    src_dflimg.embed_and_set(
                        filename_path_str,
                        fanseg_mask=fanseg_mask,
                        #fanseg_mask_ver=FANSegmentator.VERSION,
                    )