          # mapx, mapy = np.float32(np.meshgrid(range_,range_)) # instead of broadcast
  
          pad = int(1.25 * self.input_size)
          slices = slice(pad // 10, -pad // 10)
          dst_slice = slice(0, (self.output_size + 1), (self.output_size // 4))
          interp = np.empty((2, self.input_size, self.input_size), dtype='float32')
          ####
  
          for i, map_ in enumerate([mapx, mapy]):
              map_ = map_ + np.random.normal(size=(5, 5), scale=self.scale)
 
</s> remove         ####
 </s> add  </s> remove         self.output_size = output_size
 </s> add         self.output_sizes = [shape[1] for shape in output_shapes if shape[2] == 3]
        logger.debug("Output sizes: %s", self.output_sizes) </s> remove             (batchsize, self.model_input_size, self.model_input_size, 3),
            (batchsize, self.model_output_size, self.model_output_size, 3)))
        if self.mask_class:
            batch_shape.append((self.batchsize, self.model_output_size, self.model_output_size, 1))
 </s> add             (batchsize, self.model_input_size, self.model_input_size, 3)))
        # Add the output shapes
        batch_shape.extend(tuple([(batchsize, ) + shape for shape in self.model_output_shapes]))
        logger.debug("Batch shapes: %s", batch_shape) </s> remove         target_image = cv2.resize(  # pylint:disable=no-member
            target_image[slices, slices, :], (self.output_size, self.output_size),
            cv2.INTER_AREA)  # pylint:disable=no-member
        logger.trace("Target image shape: %s", target_image.shape)

        warped_image, warped_mask = self.separate_mask(warped_image)
        target_image, target_mask = self.separate_mask(target_image)

        if target_mask is None:
            logger.trace("Randomly warped image")
            return [warped_image, target_image]

        logger.trace("Target mask shape: %s", target_mask.shape)
        logger.trace("Randomly warped image and mask")
        return [warped_image, target_image, target_mask]
 </s> add         target_images = [cv2.resize(target_image[slices, slices, :],  # pylint:disable=no-member
                                    (size, size),
                                    cv2.INTER_AREA)  # pylint:disable=no-member
                         for size in self.output_sizes]

        logger.trace("Target image shapea: %s", [img.shape for img in target_images])
        return self.compile_images(warped_image, target_images)

    def compile_images(self, warped_image, target_images):
        """ Compile the warped images, target images and mask for feed """
        warped_image, _ = self.separate_mask(warped_image)
        final_target_images = list()
        target_mask = None
        for target_image in target_images:
            image, mask = self.separate_mask(target_image)
            final_target_images.append(image)
            # Add the mask if it exists and is the same size as our largest output
            if mask is not None and mask.shape[1] == max(self.output_sizes):
                target_mask = mask

        retval = [warped_image] + final_target_images
        if target_mask is not None:
            logger.trace("Target mask shape: %s", target_mask.shape)
            retval.append(target_mask)

        logger.trace("Final shapes: %s", [img.shape for img in retval])
        return retval </s> remove         dst_points = np.mgrid[dst_slice, dst_slice]
        mat = umeyama(src_points, True, dst_points.T.reshape(-1, 2))[0:2]
        target_image = cv2.warpAffine(  # pylint:disable=no-member
            image, mat, (self.output_size, self.output_size))
        logger.trace("Target image shape: %s", target_image.shape)

        warped_image, warped_mask = self.separate_mask(warped_image)
        target_image, target_mask = self.separate_mask(target_image)
 </s> add         dst_points = [np.mgrid[dst_slice, dst_slice] for dst_slice in dst_slices]
        mats = [umeyama(src_points, True, dst_pts.T.reshape(-1, 2))[0:2]
                for dst_pts in dst_points]
        dst_slices = [slice(0, (size + 1), (size // 4)) for size in self.output_sizes]
          # mapx, mapy = np.float32(np.meshgrid(range_,range_)) # instead of broadcast
  
          pad = int(1.25 * self.input_size)
          slices = slice(pad // 10, -pad // 10)
        dst_slices = [slice(0, (size + 1), (size // 4)) for size in self.output_sizes]
          interp = np.empty((2, self.input_size, self.input_size), dtype='float32')
          ####
  
          for i, map_ in enumerate([mapx, mapy]):
              map_ = map_ + np.random.normal(size=(5, 5), scale=self.scale)
keep keep keep keep replace keep keep keep keep keep
 Training: Add Multi-Output Support

- Name output nodes of models
- Add support for multiple outputs in models and in training
- Update loss output format for cli and gui
- Sort graphs tabs on training
- Fix analysis graph for new loss names
- Multi output support in convert 
lib/training_data.py