class_docstr: DataHandler generate augmented batches used for training or validation.
  
  Args:
      lr_dir: directory containing the Low Res images.
      hr_dir: directory containing the High Res images.
      patch_size: integer, size of the patches extracted from LR images.
      scale: integer, upscaling factor.
      n_validation_samples: integer, size of the validation set. Only provided if the
          DataHandler is used to generate validation sets.
docstr: Get random top left corners coordinates in LR space, multiply by scale to
  get HR coordinates.
  Gets batch_size + n possible coordinates.
  Accepts the batch only if the standard deviation of pixel intensities is above a given threshold, OR
  no patches can be further discarded (n have been discarded already).
  Square crops of size patch_size are taken from the selected
  top left corners.
docstr_tok: ["Get","random","top","left","corners","coordinates","in","LR","space",",","multiply","by","scale","to","get","HR","coordinates",".","Gets","batch_size","+","n","possible","coordinates",".","Accepts","the","batch","only","if","the","standard","deviation","of","pixel","intensities","is","above","a","given","threshold",",","OR","no","patches","can","be","further","discarded","(","n","have","been","discarded","already",")",".","Square","crops","of","size","patch_size","are","taken","from","the","selected","top","left","corners","."]
code: def _crop_imgs(self, imgs, batch_size, flatness):
      """
      Get random top left corners coordinates in LR space, multiply by scale to
      get HR coordinates.
      Gets batch_size + n possible coordinates.
      Accepts the batch only if the standard deviation of pixel intensities is above a given threshold, OR
      no patches can be further discarded (n have been discarded already).
      Square crops of size patch_size are taken from the selected
      top left corners.
      """
  
      slices = {}
      crops = {}
      crops["lr"] = []
      crops["hr"] = []
      accepted_slices = {}
      accepted_slices["lr"] = []
      top_left = {"x": {}, "y": {}}
      n = 50 * batch_size
      for i, axis in enumerate(["x", "y"]):
          top_left[axis]["lr"] = np.random.randint(
              0,
              imgs["lr"].shape[i] - self.patch_size["lr"] + 1,
              batch_size + n,
          )
          top_left[axis]["hr"] = top_left[axis]["lr"] * self.scale
      for res in ["lr", "hr"]:
          slices[res] = np.array(
              [
                  {
                      "x": (x, x + self.patch_size[res]),
                      "y": (y, y + self.patch_size[res]),
                  }
                  for x, y in zip(
                      top_left["x"][res], top_left["y"][res]
                  )
              ]
          )
  
      for slice_index, s in enumerate(slices["lr"]):
          candidate_crop = imgs["lr"][
              s["x"][0] : s["x"][1], s["y"][0] : s["y"][1], slice(None)
          ]
          if self._not_flat(candidate_crop, flatness) or n == 0:
              crops["lr"].append(candidate_crop)
              accepted_slices["lr"].append(slice_index)
          else:
              n -= 1
          if len(crops["lr"]) == batch_size:
              break
  
      accepted_slices["hr"] = slices["hr"][accepted_slices["lr"]]
  
      for s in accepted_slices["hr"]:
          candidate_crop = imgs["hr"][
              s["x"][0] : s["x"][1], s["y"][0] : s["y"][1], slice(None)
          ]
          crops["hr"].append(candidate_crop)
  
      crops["lr"] = np.array(crops["lr"])
      crops["hr"] = np.array(crops["hr"])
      return crops
  
file_path: image-super-resolution/ISR/utils/datahandler.py
imports: import os
  import imageio
  import numpy
  from ISR.utils.logger import get_logger
label_desc: Use image node_id 6 for calling the DataHandler obj's underlying member method code with example usage: obj._crop_imgs(imgs, batch_size, flatness) and returns: crops