  
          logger.trace("Item out: %s", {key: val.shape if isinstance(val, np.ndarray) else val
                                        for key, val in batch.items()})
  
          for filename, face in zip(batch["filename"], batch["detected_faces"]):
              self._output_faces.append(face)
              if len(self._output_faces) != self._faces_per_filename[filename]:
                  continue
  
              output = self._extract_media.pop(filename)
 
</s> remove         logger.trace("Item out: %s", {key: val.shape if isinstance(val, np.ndarray) else val
                                      for key, val in batch.items()})
 </s> add         logger.trace("Item out: %s", {key: val.shape  # type:ignore
                                      if isinstance(val, np.ndarray) else val
                                      for key, val in batch.__dict__.items()}) </s> remove         for face, landmarks in zip(batch["detected_faces"], batch["landmarks"]):
 </s> add         for face, landmarks in zip(batch.detected_faces, batch.landmarks): </s> remove             subbatch = {key: val
                        for key, val in batch.items()
                        if key not in ["feed", "prediction"] + self._additional_keys}
            subbatch["prediction"] = batch["prediction"][idx]
            for key in self._additional_keys:
                subbatch[key] = batch[key][idx]
 </s> add             # Create a pseudo object that only populates the data, feed and prediction slots with
            # the current re-feed iteration
            subbatch = AlignerBatch(image=batch.image,
                                    detected_faces=batch.detected_faces,
                                    filename=batch.filename,
                                    feed=[batch.feed[idx]],
                                    prediction=batch.prediction[idx],
                                    data=[batch.data[idx]]) </s> remove             logger.trace("Returning batch: %s", {k: v.shape if isinstance(v, np.ndarray) else v
                                                 for k, v in batch.items()})
 </s> add             logger.trace("Returning batch: %s", {k: v.shape  # type:ignore
                                                 if isinstance(v, np.ndarray) else v
                                                 for k, v in batch.__dict__.items()})
        for frame, filename, face in zip(batch.image, batch.filename, batch.detected_faces):
  
          logger.trace("Item out: %s", {key: val.shape if isinstance(val, np.ndarray) else val
                                        for key, val in batch.items()})
  
        for frame, filename, face in zip(batch.image, batch.filename, batch.detected_faces):
              self._output_faces.append(face)
              if len(self._output_faces) != self._faces_per_filename[filename]:
                  continue
  
              output = self._extract_media.pop(filename)
keep keep keep keep replace keep keep keep keep keep
 Extract updates:
  - Default CPU detector to MTCNN
  - add basic Aligner false positive filters
  - Typing: align + plugins
  - Use specific AlignerBatch class for alignment
  - 
plugins/extract/align/_base.py