def apply_fixes(self, original, face, mask, landmarks): """ Apply fixes """ #TODO copies aren't likey neccesary and will slow calc... used when isolating issues new_image = face[:, :, :3].copy() image_mask = mask[:, :, :3].copy() frame = original[:, :, :3].copy() #TODO - force default for args.sharpen_image to ensure it isn't None if self.args.sharpen_image is not None and self.args.sharpen_image.lower( ) != "none": new_image = self.sharpen(new_image, self.args.sharpen_image) if self.args.avg_color_adjust: new_image = self.color_adjust(new_image, frame, image_mask) if self.args.match_histogram: new_image = self.color_hist_match(new_image, frame, image_mask) if self.args.seamless_clone: blended = self.seamless_clone(new_image, frame, image_mask) else: foreground = new_image * image_mask background = frame * (1.0 - image_mask) blended = foreground + background np.clip(blended, 0.0, 255.0, out=blended) if self.args.draw_transparent: # Adding a 4th channel should happen after all other channel operations # Add mask as 4th channel for saving as alpha on supported output formats blended = dfl_full(landmarks, blended, channels=4) return np.rint(blended).astype('uint8')
def dfl(self, **kwargs): """ DFaker Mask """ logger.trace("Getting mask") dummy = np.zeros((kwargs["image_size"][1], kwargs["image_size"][0], 3), dtype='float32') mask = dfl_full(kwargs["landmarks"], dummy, channels=3) mask = self.intersect_rect(mask, **kwargs) return mask
def patch_image(self, image, detected_face): """ Patch the image """ logger.trace("Patching image") image = image.astype('float32') image_size = (image.shape[1], image.shape[0]) coverage = int(self.training_coverage_ratio * self.training_size) padding = (self.training_size - coverage) // 2 logger.trace("coverage: %s, padding: %s", coverage, padding) self.crop = slice(padding, self.training_size - padding) if not self.mask: # Init the mask on first image self.mask = Mask(self.args.mask_type, self.training_size, padding, self.crop) detected_face.load_aligned(image, size=self.training_size, align_eyes=False) new_image = self.get_new_image(image, detected_face, coverage, image_size) image_mask = self.get_image_mask(detected_face, image_size) if self.args.draw_transparent: new_image = dfl_full( detected_face.landmarks_as_xy, new_image, channels=4 ) #Add mask as 4th channel for saving as alpha on supported output formats #This make sure that all the arrays match in size for later actions despite not actually using alpha in any way. image_mask = cv2.cvtColor(image_mask, cv2.COLOR_RGB2RGBA) image = cv2.cvtColor(image, cv2.COLOR_RGB2RGBA) patched_face = self.apply_fixes(image, new_image, image_mask, image_size) logger.trace("Patched image") return patched_face
def apply_fixes(self, original, face, mask, image_size, landmarks): """ Apply fixes """ new_image = face[:, :, :3].copy() image_mask = mask[:, :, :3].copy() frame = original[:, :, :3].copy() if self.args.sharpen_image is not None and self.args.sharpen_image.lower( ) != "none": np.clip(new_image, 0.0, 255.0, out=new_image) if self.args.sharpen_image == "box_filter": kernel = np.ones((3, 3)) * (-1) kernel[1, 1] = 9 new_image = cv2.filter2D(new_image, -1, kernel) # pylint: disable=no-member elif self.args.sharpen_image == "gaussian_filter": blur = cv2.GaussianBlur(new_image, (0, 0), 3.0) # pylint: disable=no-member new_image = cv2.addWeighted( new_image, # pylint: disable=no-member 1.5, blur, -0.5, 0, new_image) if self.args.avg_color_adjust: for _ in [0, 1]: np.clip(new_image, 0.0, 255.0, out=new_image) diff = frame - new_image avg_diff = np.sum(diff * image_mask, axis=(0, 1)) adjustment = avg_diff / np.sum(image_mask, axis=(0, 1)) new_image = new_image + adjustment if self.args.match_histogram: np.clip(new_image, 0.0, 255.0, out=new_image) new_image = self.color_hist_match(new_image, frame, image_mask) if self.args.seamless_clone: h, w, _ = frame.shape h = h // 2 w = w // 2 y_indices, x_indices, _ = np.nonzero(image_mask) y_crop = slice(np.min(y_indices), np.max(y_indices)) x_crop = slice(np.min(x_indices), np.max(x_indices)) y_center = int( np.rint((np.max(y_indices) + np.min(y_indices)) / 2) + h) x_center = int( np.rint((np.max(x_indices) + np.min(x_indices)) / 2) + w) ''' # test with average of centroid rather than the h /2 , w/2 center y_center = int(np.rint(np.average(y_indices) + h) x_center = int(np.rint(np.average(x_indices) + w) ''' insertion = np.rint(new_image[y_crop, x_crop, :]).astype('uint8') insertion_mask = image_mask[y_crop, x_crop, :] insertion_mask[insertion_mask != 0] = 255 insertion_mask = insertion_mask.astype('uint8') prior = np.pad(frame, ((h, h), (w, w), (0, 0)), 'constant').astype('uint8') blended = cv2.seamlessClone( insertion, # pylint: disable=no-member prior, insertion_mask, (x_center, y_center), cv2.NORMAL_CLONE) # pylint: disable=no-member blended = blended[h:-h, w:-w] else: foreground = new_image * image_mask background = frame * (1.0 - image_mask) blended = foreground + background np.clip(blended, 0.0, 255.0, out=blended) if self.args.draw_transparent: # Adding a 4th channel should happen after all other channel operations # Add mask as 4th channel for saving as alpha on supported output formats blended = dfl_full(landmarks, blended, channels=4) return np.rint(blended).astype('uint8')