          height = int(width / 4.5)
          total_width = width * 3
          logger.debug("height: %s, total_width: %s", height, total_width)
          font = cv2.FONT_HERSHEY_SIMPLEX
          texts = [f"{titles[0]} ({side})",
                   f"{titles[0]} > {titles[0]}",
                   f"{titles[0]} > {titles[1]}"]
          scaling = (width / 144) * 0.45
          text_sizes = [cv2.getTextSize(texts[idx], font, scaling, 1)[0]
                        for idx in range(len(texts))]
 
</s> remove         side = side.upper()
 </s> add  </s> remove         amount_l = self._config.get("color_lightness", 30) / 100
        amount_ab = self._config.get("color_ab", 8) / 100
        adjust = np.array([amount_l, amount_ab, amount_ab], dtype="float32")
        randoms = (
            (np.random.rand(self._batchsize, 1, 1, 3).astype("float32") * (adjust * 2)) - adjust)
        logger.trace("Random LAB adjustments: %s", randoms)

 </s> add         randoms = np.random.uniform(-self._constants.lab_adjust,
                                    self._constants.lab_adjust,
                                    size=(self._batchsize, 1, 1, 3)).astype("float32")
        logger.trace("Random LAB adjustments: %s", randoms)  # type: ignore
        # Iterating through the images and channels is much faster than numpy.where and slightly
        # faster than numexpr.where. </s> remove 
        for side, samples in self.images.items():
            other_side = "a" if side == "b" else "b"
            predictions = [preds[f"{side}_{side}"],
                           preds[f"{other_side}_{side}"]]
            display = self._to_full_frame(side, samples, predictions)
            headers[side] = self._get_headers(side, display[0].shape[1])
            figures[side] = np.stack([display[0], display[1], display[2], ], axis=1)
            if self.images[side][0].shape[0] % 2 == 1:
                figures[side] = np.concatenate([figures[side],
                                                np.expand_dims(figures[side][0], 0)])

        width = 4
        side_cols = width // 2
        if side_cols != 1:
            headers = self._duplicate_headers(headers, side_cols)

        header = np.concatenate([headers["a"], headers["b"]], axis=1)
        figure = np.concatenate([figures["a"], figures["b"]], axis=0)
        height = int(figure.shape[0] / width)
        figure = figure.reshape((width, height) + figure.shape[1:])
        figure = _stack_images(figure)
        figure = np.concatenate((header, figure), axis=0)

        logger.debug("Compiled sample")
        return np.clip(figure * 255, 0, 255).astype('uint8')
 </s> add         return self._compile_preview(preds) </s> remove         self._coverage_ratio = coverage_ratio
        self._scale = 5  # Normal random variable scale
 </s> add         self._warp_scale = 5 / 256 * self._processing_size  # Normal random variable scale
        self._warp_lm_scale = 2 / 256 * self._processing_size  # Normal random variable scale
        texts = [f"{titles[0]} ({side.upper()})",
          height = int(width / 4.5)
          total_width = width * 3
          logger.debug("height: %s, total_width: %s", height, total_width)
          font = cv2.FONT_HERSHEY_SIMPLEX
        texts = [f"{titles[0]} ({side.upper()})",
                   f"{titles[0]} > {titles[0]}",
                   f"{titles[0]} > {titles[1]}"]
          scaling = (width / 144) * 0.45
          text_sizes = [cv2.getTextSize(texts[idx], font, scaling, 1)[0]
                        for idx in range(len(texts))]
keep keep keep keep replace keep keep keep keep keep
 Data Augmentation update (#1263)

- lib.detected_face
    - Subclass Masks for Landmark based masks
    - Add training mask propery + methods to DetectedFace
  - lib.training_training
    - subclass TrainingDataGenerator for training and preview data
    - Split cache into own module
    - Reduce thread count to 1 to prevent image corruption + data re-use
    - Process on largest model input/output size rather than stored image size
    - Size and crop masks during caching stage
    - Implement ring buffer for data flow
    - Fix preview reload bug
  - augmentation
    - typing
    - switch color aug order
    - better initialization
    - Fix warp + landmark warp to correctly apply at different image scales
    - Slightly improved warp caching
    - Don't store whether image is_preview. Handle all data as training images implicitly
  - plugins.trainer: Typing and fixes to work with trainingdata refactor 
plugins/train/trainer/_base.py