def anonymize_image(self, image, detection_thresholds, cubemap=False): assert set(self.detectors.keys()) == set(detection_thresholds.keys()),\ 'Detector names must match detection threshold names' detected_boxes = [] if cubemap: w, h, _ = np.shape(image) # Split cubemap into pieces piecesRects = [ [0, 0, w/3, h], # Large front face [w/3, 0, 2*w/3, h/2], # Back face [2*w/3, 0, w, h/2], # Top face (Superman!) [w/3, h/2, 2*w/3, h], # Right face [2*w/3, h/2, w, h] # Left face ] for idx, rect in enumerate(piecesRects): print(np.shape(image)) piece = image[round(rect[1]):round(rect[3]), round(rect[0]):round(rect[2])] obfuscated_piece, piece_detected_boxes = self.anonymize_image(piece, detection_thresholds, False) print(piece_detected_boxes) import pdb; pdb.set_trace(); detected_boxes = detected_boxes + [box + Box(rect[1], rect[0], rect[1], rect[0], 0.0, "face") for box in piece_detected_boxes] # TODO Remove this and change! return self.obfuscator.obfuscate(image, detected_boxes), detected_boxes else: for kind, detector in self.detectors.items(): new_boxes = detector.detect(image, detection_threshold=detection_thresholds[kind]) detected_boxes.extend(new_boxes) return self.obfuscator.obfuscate(image, detected_boxes), detected_boxes
def test_it_anonymizes_multiple_images(tmp_path): np.random.seed(42) # to avoid flaky tests input_images = [ np.random.rand(128, 64, 3), np.random.rand(128, 64, 3), np.random.rand(128, 64, 3) ] obfuscator = MockObfuscator() mock_detector = MockDetector([ Box(y_min=0, x_min=10, y_max=20, x_max=30, score=0.5, kind=''), Box(y_min=100, x_min=10, y_max=120, x_max=30, score=0.9, kind='') ]) expected_anonymized_images = list(map(np.copy, input_images)) for i, _ in enumerate(expected_anonymized_images): expected_anonymized_images[i] = (expected_anonymized_images[i] * 255).astype(np.uint8) expected_anonymized_images[i][0:20, 10:30] = 0 expected_anonymized_images[i][100:120, 10:30] = 0 # write input images to disk input_path = tmp_path / 'input' input_path.mkdir() output_path = tmp_path / 'output' for i, input_image in enumerate(input_images): image_path = input_path / f'{i}.png' pil_image = Image.fromarray((input_image * 255).astype(np.uint8), mode='RGB') pil_image.save(image_path) anonymizer = Anonymizer(detectors={'face': mock_detector}, obfuscator=obfuscator) anonymizer.anonymize_images(str(input_path), output_path=str(output_path), detection_thresholds={'face': 0.1}, file_types=['jpg', 'png'], write_json=False) anonymized_images = [] for image_path in sorted(output_path.glob('**/*.png')): anonymized_images.append(load_np_image(image_path)) for i, expected_anonymized_image in enumerate( expected_anonymized_images): assert np.all( np.isclose(expected_anonymized_image, anonymized_images[i]))
def test_it_detects_obvious_faces(tmp_path): weights_directory = tmp_path / 'weights' face_weights_path = get_weights_path(weights_directory, kind='face') download_weights(weights_directory) detector = Detector(kind='face', weights_path=face_weights_path) np_image = load_np_image('./test/detection/face_test_image.jpg') left_face = Box(x_min=267, y_min=64, x_max=311, y_max=184, score=0.0, kind='face') right_face = Box(x_min=369, y_min=68, x_max=420, y_max=152, score=0.0, kind='face') boxes = detector.detect(np_image, detection_threshold=0.2) assert len(boxes) >= 2 for box in boxes: assert box.score >= 0.2 assert boxes[0].score >= 0.5 and boxes[1].score >= 0.5 assert ((box_covers_box(boxes[0], left_face) and box_covers_box(boxes[1], right_face)) or (box_covers_box(boxes[1], left_face) and box_covers_box(boxes[0], right_face)))
def test_it_obfuscates_regions(): obfuscator = Obfuscator() np.random.seed(42) # to avoid flaky tests image = np.random.rand(128, 64, 3) # height, width, channels boxes = [ Box(y_min=0, x_min=10, y_max=20, x_max=30, score=0, kind=''), Box(y_min=100, x_min=10, y_max=120, x_max=30, score=0, kind='') ] # copy to make sure the input image does not change obfuscated_image = obfuscator.obfuscate(np.copy(image), boxes) assert obfuscated_image.shape == (128, 64, 3) assert not np.any( np.isclose(obfuscated_image[0:20, 10:30, :], image[0:20, 10:30, :])) assert not np.any( np.isclose(obfuscated_image[100:120, 10:30, :], image[100:120, 10:30, :])) assert np.all( np.isclose(obfuscated_image[30:90, :, :], image[30:90, :, :]))
def test_it_anonymizes_a_single_image(): np.random.seed(42) # to avoid flaky tests input_image = np.random.rand(128, 64, 3) # height, width, channels obfuscator = MockObfuscator() mock_detector = MockDetector([ Box(y_min=0, x_min=10, y_max=20, x_max=30, score=0.5, kind=''), Box(y_min=100, x_min=10, y_max=120, x_max=30, score=0.9, kind='') ]) expected_anonymized_image = np.copy(input_image) expected_anonymized_image[0:20, 10:30] = 0.0 expected_anonymized_image[100:120, 10:30] = 0.0 anonymizer = Anonymizer(detectors={'face': mock_detector}, obfuscator=obfuscator) anonymized_image, detected_boxes = anonymizer.anonymize_image( input_image, detection_thresholds={'face': 0.1}) assert np.all(np.isclose(expected_anonymized_image, anonymized_image)) assert detected_boxes == [ Box(y_min=0, x_min=10, y_max=20, x_max=30, score=0.5, kind=''), Box(y_min=100, x_min=10, y_max=120, x_max=30, score=0.9, kind='') ]
def test_it_has_coordinates_a_score_and_a_kind(): box = Box(x_min=1.0, y_min=2.0, x_max=3.0, y_max=4.0, score=0.9, kind='face') assert box.x_min == 1.0 assert box.y_min == 2.0 assert box.x_max == 3.0 assert box.y_max == 4.0 assert box.score == 0.9 assert box.kind == 'face'
def _convert_boxes(self, num_boxes, scores, boxes, image_height, image_width, detection_threshold): assert detection_threshold >= 0.001, 'Threshold can not be too close to "0".' result_boxes = [] for i in range(int(num_boxes)): score = float(scores[i]) if score < detection_threshold: continue y_min, x_min, y_max, x_max = map(float, boxes[i].tolist()) box = Box(y_min=y_min * image_height, x_min=x_min * image_width, y_max=y_max * image_height, x_max=x_max * image_width, score=score, kind=self.kind) result_boxes.append(box) return result_boxes