def recognize_faces(self, image):
     # First, detect faces in the image
     face_boxes = self._detect_faces(image)
     # Crop and search for each face in the active registry
     rec_result = []
     for face_box in face_boxes:
         box = face_box['box']
         face_crop = image[box[1]:box[3], box[0]:box[2], :]
         bin_face_crop = opencv_image_to_binary_image(face_crop)
         try:
             resp = self._aws_client.search_faces_by_image(
                 CollectionId=self._active_face_registry,
                 Image={'Bytes': bin_face_crop},
                 MaxFaces=1,
                 FaceMatchThreshold=self._matching_threshold)
             if len(resp['FaceMatches']) >= 1:
                 match = resp['FaceMatches'][0]
                 rec_result.append({
                     'face_id':
                     match['Face']['FaceId'],
                     'face_name':
                     match['Face']['ExternalImageId'],
                     'recognition_score':
                     match['Similarity'],
                     'box':
                     box,
                     'detection_score':
                     face_box['detection_score']
                 })
             else:
                 rec_result.append({
                     'face_id':
                     None,
                     'face_name':
                     'Unknown',
                     'recognition_score':
                     None,
                     'box':
                     box,
                     'detection_score':
                     face_box['detection_score']
                 })
         except Exception as e:
             logger.warning(
                 'Some error occured when searching for the face. '
                 'Skipping this face. {}'.format(e))
             rec_result.append({
                 'face_id':
                 None,
                 'face_name':
                 'Unknown',
                 'recognition_score':
                 None,
                 'box':
                 box,
                 'detection_score':
                 face_box['detection_score']
             })
     return rec_result
 def delete_face_registry(self, registry_name):
     if registry_name not in self._face_registries:
         logger.warning(
             'Looks like there is no such registry to delete.'.format(
                 registry_name))
         raise ValueError('No such face registry {}'.format(registry_name))
     else:
         registry_path = self._get_face_registry_path(registry_name)
         os.remove(registry_path)
         if registry_name == self._active_face_registry:
             self._registry_face_names = []
             self._registry_faces = []
             self._registry_face_ids = []
             self._registry_face_encodings = []
             self._active_face_registry = None
         logger.info('Removed face registry {}'.format(registry_name))
         return registry_name
 def _load_face_registry(self, registry_name):
     reg_path = self._get_face_registry_path(registry_name)
     if os.path.exists(reg_path):
         with open(reg_path, 'rb') as f:
             try:
                 data = pickle.load(f)
                 self._registry_face_encodings = data['face_encodings']
                 self._registry_faces = data['face_images']
                 self._registry_face_names = data['face_names']
                 self._registry_face_ids = data['face_ids']
                 self._active_face_registry = registry_name
                 logger.info(
                     'Loaded face registry {}. Set it as active face '
                     'registry'.format(registry_name))
             except Exception as e:
                 logger.warning(
                     'Falied to load the face registry {}'.format(e))
    def register_face(self, registry_name, image, name):
        if registry_name not in self._face_registries:
            raise ValueError('No such face registry {}'.format(registry_name))
        if isinstance(image, str):
            image = face_recognition.load_image_file(image)

        face_boxes = face_recognition.face_locations(
            image,
            number_of_times_to_upsample=self._num_upsamples,
            model='cnn')
        if len(face_boxes) == 0:
            logger.warning('No faces found in the image')
            return None
        elif len(face_boxes) == 1:
            target_face_box = face_boxes[0]
            logger.info(
                'Found one face in the image {}'.format(target_face_box))
        else:
            target_face_box = EdgeFaceRecognizer._get_largest_face(face_boxes)
            logger.info(
                'Found multiple faces in the image. Taking the largest one {}'
                ''.format(target_face_box))

        face_crop = image[target_face_box[0]:target_face_box[2],
                          target_face_box[3]:target_face_box[1], :]
        encoding = face_recognition.face_encodings(
            image, known_face_locations=[target_face_box])
        new_face_id = self._get_new_face_id()

        if registry_name != self._active_face_registry:
            active_reg = self._active_face_registry
            self._load_face_registry(registry_name)
            assert registry_name == self._active_face_registry
        self._registry_faces.append(face_crop)
        self._registry_face_names.append(name)
        assert len(encoding) == 1
        self._registry_face_encodings.append(encoding[0])
        self._registry_face_ids.append(new_face_id)
        self._save_active_face_registry()

        # Restore active registry
        if registry_name != self._active_face_registry:
            self._load_face_registry(active_reg)

        return new_face_id
 def delete_face_registry(self, registry_name):
     try:
         if registry_name not in self._face_registries:
             logger.warning(
                 'Looks like there is no such registry to delete.'
                 'Still trying with AWS'.format(registry_name))
         resp = self._aws_client.delete_collection(
             CollectionId=registry_name)
         if registry_name in self._face_registries:
             self._face_registries.remove(registry_name)
         status_code = resp['StatusCode']
     except ClientError as e:
         if e.response['Error']['Code'] == 'ResourceNotFoundException':
             logger.warning('Registry {} not found'.format(registry_name))
         else:
             logger.error('Error occured: {}'.format(
                 e.response['Error']['Message']))
         status_code = e.response['ResponseMetadata']['HTTPStatusCode']
     logger.info('Delete face registry status: {}'.format(status_code))
 def _detect_faces(self, image):
     binary_image = opencv_image_to_binary_image(image)
     face_boxes = []
     try:
         resp = self._aws_client.detect_faces(
             Image={'Bytes': binary_image},
             Attributes=self._detection_attributes)
         for face_detail in resp['FaceDetails']:
             if face_detail['Confidence'] >= self._detection_threshold:
                 face_box = AwsFaceRecognizer._decode_aws_bounding_box(
                     face_detail['BoundingBox'], image.shape[1],
                     image.shape[0])
                 score = face_detail['Confidence']
                 face_boxes.append({
                     'detection_score': score,
                     'box': face_box
                 })
     except Exception as e:
         logger.warning('Error occured when detecting faces. {}'.format(e))
     return face_boxes
 def deregister_face(self, registry_name, face_id):
     try:
         resp = self._aws_client.delete_faces(CollectionId=registry_name,
                                              FaceIds=[face_id])
         assert len(resp['DeletedFaces']) == 1
         deleted_face_id = resp['DeletedFaces'][0]
         deleted_face_name = None
         logger.warning('Deleted face: {}'.format(deleted_face_id))
         if registry_name == self._active_face_registry:
             idx = self._registry_face_ids.index(face_id)
             deleted_face_name = self._registry_face_names[idx]
             del self._registry_face_ids[idx]
             del self._registry_face_names[idx]
             del self._registry_faces[idx]
         return deleted_face_id, deleted_face_name
     except Exception as e:
         logger.warning('Error occured. Could not de-register face.')
         logger.warning(e)
         return None, None