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: Computes differences in greylevels for neighboring grid points.
  
  First part of 'step 4' in the paper.
  
  Returns n x n x 8 rank 3 array for an n x n grid (if diagonal_neighbors == True)
  
  The n x nth coordinate corresponds to a grid point.  The eight values are
  the differences between neighboring grid points, in this order:
  
  upper left
  upper
  upper right
  left
  right
  lower left
  lower
  lower right
  
  Args:
      grey_level_matrix (numpy.ndarray): grid of values sampled from image
      diagonal_neighbors (Optional[boolean]): whether or not to use diagonal
          neighbors (default True)
  
  Returns:
      a n x n x 8 rank 3 numpy array for an n x n grid (if diagonal_neighbors == True)
  
  Examples:
      >>> img = gis.preprocess_image('https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg')
      >>> window = gis.crop_image(img)
      >>> grid = gis.compute_grid_points(img, window=window)
      >>> grey_levels = gis.compute_mean_level(img, grid[0], grid[1])
      >>> gis.compute_differentials(grey_levels)
      array([[[  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                 0.00000000e+00,   1.82683143e-03,  -0.00000000e+00,
                 2.74085276e-01,   1.24737821e-01],
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                -1.82683143e-03,   2.15563930e-03,   2.72258444e-01,
                 1.22910990e-01,   3.48522956e-01],
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                -2.15563930e-03,   1.16963917e-01,   1.20755351e-01,
                 3.46367317e-01,   1.99638513e-01],
              [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                -1.16963917e-01,   1.32128118e-01,   2.29403399e-01,
                 8.26745956e-02,   1.16455050e-01],
              ...
docstr_tok: ["Computes","differences","in","greylevels","for","neighboring","grid","points",".","First","part","of","'step","4","'","in","the","paper",".","Returns","n","x","n","x","8","rank","3","array","for","an","n","x","n","grid","(","if","diagonal_neighbors","==","True",")","The","n","x","nth","coordinate","corresponds","to","a","grid","point",".","The","eight","values","are","the","differences","between","neighboring","grid","points",",","in","this","order",":","upper","left","upper","upper","right","left","right","lower","left","lower","lower","right","Args",":","grey_level_matrix","(","numpy.ndarray",")",":","grid","of","values","sampled","from","image","diagonal_neighbors","(","Optional","[","boolean","]",")",":","whether","or","not","to","use","diagonal","neighbors","(","default","True",")","Returns",":","a","n","x","n","x","8","rank","3","numpy","array","for","an","n","x","n","grid","(","if","diagonal_neighbors","==","True",")","Examples",":",">",">",">","img","=","gis.preprocess_image","(","'https",":","\/\/pixabay.com\/static\/uploads\/photo\/2012\/11\/28\/08\/56\/mona-lisa-67506_960_720.jpg","'",")",">",">",">","window","=","gis.crop_image","(","img",")",">",">",">","grid","=","gis.compute_grid_points","(","img",",","window=window",")",">",">",">","grey_levels","=","gis.compute_mean_level","(","img",",","grid","[","0","]",",","grid","[","1","]",")",">",">",">","gis.compute_differentials","(","grey_levels",")","array","(","[","[","[","0.00000000e+00",",","0.00000000e+00",",","0.00000000e+00",",","0.00000000e+00",",","1.82683143e-03",",","-0.00000000e+00",",","2.74085276e-01",",","1.24737821e-01","]",",","[","0.00000000e+00",",","0.00000000e+00",",","0.00000000e+00",",","-1.82683143e-03",",","2.15563930e-03",",","2.72258444e-01",",","1.22910990e-01",",","3.48522956e-01","]",",","[","0.00000000e+00",",","0.00000000e+00",",","0.00000000e+00",",","-2.15563930e-03",",","1.16963917e-01",",","1.20755351e-01",",","3.46367317e-01",",","1.99638513e-01","]",",","[","0.00000000e+00",",","0.00000000e+00",",","0.00000000e+00",",","-1.16963917e-01",",","1.32128118e-01",",","2.29403399e-01",",","8.26745956e-02",",","1.16455050e-01","]",",","..."]
code: def compute_differentials(grey_level_matrix, diagonal_neighbors=True):
      """Computes differences in greylevels for neighboring grid points.
  
      First part of 'step 4' in the paper.
  
      Returns n x n x 8 rank 3 array for an n x n grid (if diagonal_neighbors == True)
  
      The n x nth coordinate corresponds to a grid point.  The eight values are
      the differences between neighboring grid points, in this order:
  
      upper left
      upper
      upper right
      left
      right
      lower left
      lower
      lower right
  
      Args:
          grey_level_matrix (numpy.ndarray): grid of values sampled from image
          diagonal_neighbors (Optional[boolean]): whether or not to use diagonal
              neighbors (default True)
  
      Returns:
          a n x n x 8 rank 3 numpy array for an n x n grid (if diagonal_neighbors == True)
  
      Examples:
          >>> img = gis.preprocess_image('https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg')
          >>> window = gis.crop_image(img)
          >>> grid = gis.compute_grid_points(img, window=window)
          >>> grey_levels = gis.compute_mean_level(img, grid[0], grid[1])
          >>> gis.compute_differentials(grey_levels)
          array([[[  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                     0.00000000e+00,   1.82683143e-03,  -0.00000000e+00,
                     2.74085276e-01,   1.24737821e-01],
                  [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                    -1.82683143e-03,   2.15563930e-03,   2.72258444e-01,
                     1.22910990e-01,   3.48522956e-01],
                  [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                    -2.15563930e-03,   1.16963917e-01,   1.20755351e-01,
                     3.46367317e-01,   1.99638513e-01],
                  [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                    -1.16963917e-01,   1.32128118e-01,   2.29403399e-01,
                     8.26745956e-02,   1.16455050e-01],
                  ...
  
      """
      right_neighbors = -np.concatenate(
          (
              np.diff(grey_level_matrix),
              np.zeros(grey_level_matrix.shape[0]).reshape(
                  (grey_level_matrix.shape[0], 1)
              ),
          ),
          axis=1,
      )
      left_neighbors = -np.concatenate(
          (right_neighbors[:, -1:], right_neighbors[:, :-1]), axis=1
      )
  
      down_neighbors = -np.concatenate(
          (
              np.diff(grey_level_matrix, axis=0),
              np.zeros(grey_level_matrix.shape[1]).reshape(
                  (1, grey_level_matrix.shape[1])
              ),
          )
      )
  
      up_neighbors = -np.concatenate(
          (down_neighbors[-1:], down_neighbors[:-1])
      )
  
      if diagonal_neighbors:
          # this implementation will only work for a square (m x m) grid
          diagonals = np.arange(
              -grey_level_matrix.shape[0] + 1,
              grey_level_matrix.shape[0],
          )
  
          upper_left_neighbors = sum(
              [
                  np.diagflat(
                      np.insert(
                          np.diff(np.diag(grey_level_matrix, i)), 0, 0
                      ),
                      i,
                  )
                  for i in diagonals
              ]
          )
          lower_right_neighbors = -np.pad(
              upper_left_neighbors[1:, 1:], (0, 1), mode="constant"
          )
  
          # flip for anti-diagonal differences
          flipped = np.fliplr(grey_level_matrix)
          upper_right_neighbors = sum(
              [
                  np.diagflat(
                      np.insert(np.diff(np.diag(flipped, i)), 0, 0), i
                  )
                  for i in diagonals
              ]
          )
          lower_left_neighbors = -np.pad(
              upper_right_neighbors[1:, 1:], (0, 1), mode="constant"
          )
  
          return np.dstack(
              np.array(
                  [
                      upper_left_neighbors,
                      up_neighbors,
                      np.fliplr(upper_right_neighbors),
                      left_neighbors,
                      right_neighbors,
                      np.fliplr(lower_left_neighbors),
                      down_neighbors,
                      lower_right_neighbors,
                  ]
              )
          )
  
      return np.dstack(
          np.array(
              [
                  up_neighbors,
                  left_neighbors,
                  right_neighbors,
                  down_neighbors,
              ]
          )
      )
  
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 7 for calling the ImageSignature obj's underlying member method code with example usage: obj.compute_differentials(grey_level_matrix, diagonal_neighbors) and returns: np, np