class_docstr: Image signature generator.
  
  Based on the method of Goldberg, et al. Available at http://www.cs.cmu.edu/~hcwong/Pdfs/icip02.ps
docstr: Crops an image, removing featureless border regions.
  
  Corresponds to the first part of 'step 2' in Goldberg's paper
  
  Args:
      image (numpy.ndarray): n x m array of floats -- the greyscale image. Typically, the
          output of preprocess_image
      lower_percentile (Optional[int]): crop image by percentage of difference (default 5)
      upper_percentile (Optional[int]): as lower_percentile (default 95)
      fix_ratio (Optional[boolean]): use the larger ratio for both directions. This is useful
          for using the fast signature transforms on sparse but very similar images (e.g.
          renderings from fixed directions). Use with care -- only use if you can guarantee the
          incoming image is square (default False).
  
  Returns:
      A pair of tuples describing the 'window' of the image to use in analysis: [(top, bottom), (left, right)]
  
  Examples:
      >>> img = gis.preprocess_image('https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg')
      >>> gis.crop_image(img)
      [(36, 684), (24, 452)]
docstr_tok: ["Crops","an","image",",","removing","featureless","border","regions",".","Corresponds","to","the","first","part","of","'step","2","'","in","Goldberg","'s","paper","Args",":","image","(","numpy.ndarray",")",":","n","x","m","array","of","floats","--","the","greyscale","image",".","Typically",",","the","output","of","preprocess_image","lower_percentile","(","Optional","[","int","]",")",":","crop","image","by","percentage","of","difference","(","default","5",")","upper_percentile","(","Optional","[","int","]",")",":","as","lower_percentile","(","default","95",")","fix_ratio","(","Optional","[","boolean","]",")",":","use","the","larger","ratio","for","both","directions",".","This","is","useful","for","using","the","fast","signature","transforms","on","sparse","but","very","similar","images","(","e.g",".","renderings","from","fixed","directions",")",".","Use","with","care","--","only","use","if","you","can","guarantee","the","incoming","image","is","square","(","default","False",")",".","Returns",":","A","pair","of","tuples","describing","the","'window","'","of","the","image","to","use","in","analysis",":","[","(","top",",","bottom",")",",","(","left",",","right",")","]","Examples",":",">",">",">","img","=","gis.preprocess_image","(","'https",":","\/\/pixabay.com\/static\/uploads\/photo\/2012\/11\/28\/08\/56\/mona-lisa-67506_960_720.jpg","'",")",">",">",">","gis.crop_image","(","img",")","[","(","36",",","684",")",",","(","24",",","452",")","]"]
code: def crop_image(
      image, lower_percentile=5, upper_percentile=95, fix_ratio=False
  ):
      """Crops an image, removing featureless border regions.
  
      Corresponds to the first part of 'step 2' in Goldberg's paper
  
      Args:
          image (numpy.ndarray): n x m array of floats -- the greyscale image. Typically, the
              output of preprocess_image
          lower_percentile (Optional[int]): crop image by percentage of difference (default 5)
          upper_percentile (Optional[int]): as lower_percentile (default 95)
          fix_ratio (Optional[boolean]): use the larger ratio for both directions. This is useful
              for using the fast signature transforms on sparse but very similar images (e.g.
              renderings from fixed directions). Use with care -- only use if you can guarantee the
              incoming image is square (default False).
  
      Returns:
          A pair of tuples describing the 'window' of the image to use in analysis: [(top, bottom), (left, right)]
  
      Examples:
          >>> img = gis.preprocess_image('https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg')
          >>> gis.crop_image(img)
          [(36, 684), (24, 452)]
  
      """
      # row-wise differences
      rw = np.cumsum(np.sum(np.abs(np.diff(image, axis=1)), axis=1))
      # column-wise differences
      cw = np.cumsum(np.sum(np.abs(np.diff(image, axis=0)), axis=0))
  
      # compute percentiles
      upper_column_limit = np.searchsorted(
          cw, np.percentile(cw, upper_percentile), side="left"
      )
      lower_column_limit = np.searchsorted(
          cw, np.percentile(cw, lower_percentile), side="right"
      )
      upper_row_limit = np.searchsorted(
          rw, np.percentile(rw, upper_percentile), side="left"
      )
      lower_row_limit = np.searchsorted(
          rw, np.percentile(rw, lower_percentile), side="right"
      )
  
      # if image is nearly featureless, use default region
      if lower_row_limit > upper_row_limit:
          lower_row_limit = int(
              lower_percentile / 100.0 * image.shape[0]
          )
          upper_row_limit = int(
              upper_percentile / 100.0 * image.shape[0]
          )
      if lower_column_limit > upper_column_limit:
          lower_column_limit = int(
              lower_percentile / 100.0 * image.shape[1]
          )
          upper_column_limit = int(
              upper_percentile / 100.0 * image.shape[1]
          )
  
      # if fix_ratio, return both limits as the larger range
      if fix_ratio:
          if (upper_row_limit - lower_row_limit) > (
              upper_column_limit - lower_column_limit
          ):
              return [
                  (lower_row_limit, upper_row_limit),
                  (lower_row_limit, upper_row_limit),
              ]
          else:
              return [
                  (lower_column_limit, upper_column_limit),
                  (lower_column_limit, upper_column_limit),
              ]
  
      # otherwise, proceed as normal
      return [
          (lower_row_limit, upper_row_limit),
          (lower_column_limit, upper_column_limit),
      ]
  
imports: from skimage.color import rgb2gray
  from skimage.io import imread
  from PIL import Image
  from PIL.MpoImagePlugin import MpoImageFile
  from six import string_types, text_type
  from io import BytesIO
  import numpy
  import xml.etree
  import xml.etree.ElementTree
label_desc: Use image node_id 4 for calling the ImageSignature obj's underlying member method code with example usage: obj.crop_image(image, lower_percentile, upper_percentile, fix_ratio) and returns: list, list, list