def inverse(self, name=None):
    """Returns a `sonnet` module to compute inverse affine transforms.

      The function first assembles a network that given the constraints of the
      current AffineGridWarper and a set of input parameters, retrieves the
      coefficients of the corresponding inverse affine transform, then feeds its
      output into a new AffineGridWarper setup to correctly warp the `output`
      space into the `source` space.

    Args:
      name: Name of module implementing the inverse grid transformation.

    Returns:
      A `sonnet` module performing the inverse affine transform of a reference
      grid of points via an AffineGridWarper module.

    Raises:
      tf.errors.UnimplementedError: If the function is called on a non 2D
        instance of AffineGridWarper.
    """
    if self._num_coeff != 6:
      raise tf.errors.UnimplementedError('AffineGridWarper currently supports'
                                         'inversion only for the 2D case.')
    def _affine_grid_warper_inverse(inputs):
      """Assembles network to compute inverse affine transformation.

      Each `inputs` row potentially contains [a, b, tx, c, d, ty]
      corresponding to an affine matrix:

        A = [a, b, tx],
            [c, d, ty]

      We want to generate a tensor containing the coefficients of the
      corresponding inverse affine transformation in a constraints-aware
      fashion.
      Calling M:

        M = [a, b]
            [c, d]

      the affine matrix for the inverse transform is:

         A_in = [M^(-1), M^-1 * [-tx, -tx]^T]

      where

        M^(-1) = (ad - bc)^(-1) * [ d, -b]
                                  [-c,  a]

      Args:
        inputs: Tensor containing a batch of transformation parameters.

      Returns:
        A tensorflow graph performing the inverse affine transformation
        parametrized by the input coefficients.
      """
      batch_size = tf.expand_dims(tf.shape(inputs)[0], 0)
      constant_shape = tf.concat([batch_size, tf.convert_to_tensor((1,))], 0)

      index = iter(range(6))
      def get_variable(constraint):
        if constraint is None:
          i = next(index)
          return inputs[:, i:i+1]
        else:
          return tf.fill(constant_shape, tf.constant(constraint,
                                                     dtype=inputs.dtype))

      constraints = chain.from_iterable(self.constraints)
      a, b, tx, c, d, ty = (get_variable(constr) for constr in constraints)

      det = a * d - b * c
      a_inv = d / det
      b_inv = -b / det
      c_inv = -c / det
      d_inv = a / det

      m_inv = basic.BatchReshape(
          [2, 2])(tf.concat([a_inv, b_inv, c_inv, d_inv], 1))

      txy = tf.expand_dims(tf.concat([tx, ty], 1), 2)

      txy_inv = basic.BatchFlatten()(tf.matmul(m_inv, txy))
      tx_inv = txy_inv[:, 0:1]
      ty_inv = txy_inv[:, 1:2]

      inverse_gw_inputs = tf.concat(
          [a_inv, b_inv, -tx_inv, c_inv, d_inv, -ty_inv], 1)

      agw = AffineGridWarper(self.output_shape,
                             self.source_shape)


      return agw(inverse_gw_inputs)  # pylint: disable=not-callable

    if name is None:
      name = self.module_name + '_inverse'
    return base.Module(_affine_grid_warper_inverse, name=name)
def inverse ( self , name = None ) : if self . _num_coeff != 6 : raise tf . errors . UnimplementedError ( 'AffineGridWarper currently supports' 'inversion only for the 2D case.' ) def _affine_grid_warper_inverse ( inputs ) : batch_size = tf . expand_dims ( tf . shape ( inputs ) [ 0 ] , 0 ) constant_shape = tf . concat ( [ batch_size , tf . convert_to_tensor ( ( 1 , ) ) ] , 0 ) index = iter ( range ( 6 ) ) def get_variable ( constraint ) : if constraint is None : i = next ( index ) return inputs [ : , i : i + 1 ] else : return tf . fill ( constant_shape , tf . constant ( constraint , dtype = inputs . dtype ) ) constraints = chain . from_iterable ( self . constraints ) a , b , tx , c , d , ty = ( get_variable ( constr ) for constr in constraints ) det = a * d - b * c a_inv = d / det b_inv = - b / det c_inv = - c / det d_inv = a / det m_inv = basic . BatchReshape ( [ 2 , 2 ] ) ( tf . concat ( [ a_inv , b_inv , c_inv , d_inv ] , 1 ) ) txy = tf . expand_dims ( tf . concat ( [ tx , ty ] , 1 ) , 2 ) txy_inv = basic . BatchFlatten ( ) ( tf . matmul ( m_inv , txy ) ) tx_inv = txy_inv [ : , 0 : 1 ] ty_inv = txy_inv [ : , 1 : 2 ] inverse_gw_inputs = tf . concat ( [ a_inv , b_inv , - tx_inv , c_inv , d_inv , - ty_inv ] , 1 ) agw = AffineGridWarper ( self . output_shape , self . source_shape ) return agw ( inverse_gw_inputs ) if name is None : name = self . module_name + '_inverse' return base . Module ( _affine_grid_warper_inverse , name = name )
Returns a `sonnet` module to compute inverse affine transforms.

      The function first assembles a network that given the constraints of the
      current AffineGridWarper and a set of input parameters, retrieves the
      coefficients of the corresponding inverse affine transform, then feeds its
      output into a new AffineGridWarper setup to correctly warp the `output`
      space into the `source` space.

    Args:
      name: Name of module implementing the inverse grid transformation.

    Returns:
      A `sonnet` module performing the inverse affine transform of a reference
      grid of points via an AffineGridWarper module.

    Raises:
      tf.errors.UnimplementedError: If the function is called on a non 2D
        instance of AffineGridWarper.