code: def distance_transform_cdt(
      input,
      metric="chessboard",
      return_distances=True,
      return_indices=False,
      distances=None,
      indices=None,
  ):
      """
      Distance transform for chamfer type of transforms.
  
      In addition to the distance transform, the feature transform can
      be calculated. In this case the index of the closest background
      element to each foreground element is returned in a separate array.
  
      Parameters
      ----------
      input : array_like
          Input
      metric : {'chessboard', 'taxicab'} or array_like, optional
          The `metric` determines the type of chamfering that is done. If the
          `metric` is equal to 'taxicab' a structure is generated using
          generate_binary_structure with a squared distance equal to 1. If
          the `metric` is equal to 'chessboard', a `metric` is generated
          using generate_binary_structure with a squared distance equal to
          the dimensionality of the array. These choices correspond to the
          common interpretations of the 'taxicab' and the 'chessboard'
          distance metrics in two dimensions.
          A custom metric may be provided, in the form of a matrix where
          each dimension has a length of three.
          'cityblock' and 'manhattan' are also valid, and map to 'taxicab'.
          The default is 'chessboard'.
      return_distances : bool, optional
          Whether to calculate the distance transform.
          Default is True.
      return_indices : bool, optional
          Whether to calculate the feature transform.
          Default is False.
      distances : int32 ndarray, optional
          An output array to store the calculated distance transform, instead of
          returning it.
          `return_distances` must be True.
          It must be the same shape as `input`.
      indices : int32 ndarray, optional
          An output array to store the calculated feature transform, instead of
          returning it.
          `return_indicies` must be True.
          Its shape must be `(input.ndim,) + input.shape`.
  
      Returns
      -------
      distances : int32 ndarray, optional
          The calculated distance transform. Returned only when
          `return_distances` is True, and `distances` is not supplied.
          It will have the same shape as the input array.
      indices : int32 ndarray, optional
          The calculated feature transform. It has an input-shaped array for each
          dimension of the input. See distance_transform_edt documentation for an
          example.
          Returned only when `return_indices` is True, and `indices` is not
          supplied.
  
      """
      ft_inplace = isinstance(indices, numpy.ndarray)
      dt_inplace = isinstance(distances, numpy.ndarray)
      _distance_tranform_arg_check(
          dt_inplace, ft_inplace, return_distances, return_indices
      )
      input = numpy.asarray(input)
      if metric in ["taxicab", "cityblock", "manhattan"]:
          rank = input.ndim
          metric = generate_binary_structure(rank, 1)
      elif metric == "chessboard":
          rank = input.ndim
          metric = generate_binary_structure(rank, rank)
      else:
          try:
              metric = numpy.asarray(metric)
          except Exception as e:
              raise RuntimeError("invalid metric provided") from e
          for s in metric.shape:
              if s != 3:
                  raise RuntimeError("metric sizes must be equal to 3")
  
      if not metric.flags.contiguous:
          metric = metric.copy()
      if dt_inplace:
          if distances.dtype.type != numpy.int32:
              raise RuntimeError("distances must be of int32 type")
          if distances.shape != input.shape:
              raise RuntimeError("distances has wrong shape")
          dt = distances
          dt[...] = numpy.where(input, -1, 0).astype(numpy.int32)
      else:
          dt = numpy.where(input, -1, 0).astype(numpy.int32)
  
      rank = dt.ndim
      if return_indices:
          sz = numpy.prod(dt.shape, axis=0)
          ft = numpy.arange(sz, dtype=numpy.int32)
          ft.shape = dt.shape
      else:
          ft = None
  
      _nd_image.distance_transform_op(metric, dt, ft)
      dt = dt[tuple([slice(None, None, -1)] * rank)]
      if return_indices:
          ft = ft[tuple([slice(None, None, -1)] * rank)]
      _nd_image.distance_transform_op(metric, dt, ft)
      dt = dt[tuple([slice(None, None, -1)] * rank)]
      if return_indices:
          ft = ft[tuple([slice(None, None, -1)] * rank)]
          ft = numpy.ravel(ft)
          if ft_inplace:
              if indices.dtype.type != numpy.int32:
                  raise RuntimeError("indices array must be int32")
              if indices.shape != (dt.ndim,) + dt.shape:
                  raise RuntimeError("indices array has wrong shape")
              tmp = indices
          else:
              tmp = numpy.indices(dt.shape, dtype=numpy.int32)
          for ii in range(tmp.shape[0]):
              rtmp = numpy.ravel(tmp[ii, ...])[ft]
              rtmp.shape = dt.shape
              tmp[ii, ...] = rtmp
          ft = tmp
  
      # construct and return the result
      result = []
      if return_distances and not dt_inplace:
          result.append(dt)
      if return_indices and not ft_inplace:
          result.append(ft)
  
      if len(result) == 2:
          return tuple(result)
      elif len(result) == 1:
          return result[0]
      else:
          return None
  
imports: import warnings
  import operator
  import numpy
  from .None import _ni_support
  from .None import _nd_image
  from .None import filters
label_desc: Use image node_id 21 for calling a global function with example usage: distance_transform_cdt(input, metric, return_distances, return_indices, distances, indices) and returns: tuple, result, None