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
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, )