code: def equalize_image(image: torch.Tensor) -> torch.Tensor:
      if image.numel() == 0:
          return image
  
      # 1. The algorithm below can easily be extended to support arbitrary integer dtypes. However, the histogram that
      #    would be needed to computed will have at least `torch.iinfo(dtype).max + 1` values. That is perfectly fine for
      #    `torch.int8`, `torch.uint8`, and `torch.int16`, at least questionable for `torch.int32` and completely
      #    unfeasible for `torch.int64`.
      # 2. Floating point inputs need to be binned for this algorithm. Apart from converting them to an integer dtype, we
      #    could also use PyTorch's builtin histogram functionality. However, that has its own set of issues: in addition
      #    to being slow in general, PyTorch's implementation also doesn't support batches. In total, that makes it slower
      #    and more complicated to implement than a simple conversion and a fast histogram implementation for integers.
      # Since we need to convert in most cases anyway and out of the acceptable dtypes mentioned in 1. `torch.uint8` is
      # by far the most common, we choose it as base.
      output_dtype = image.dtype
      image = to_dtype_image(image, torch.uint8, scale=True)
  
      # The histogram is computed by using the flattened image as index. For example, a pixel value of 127 in the image
      # corresponds to adding 1 to index 127 in the histogram.
      batch_shape = image.shape[:-2]
      flat_image = image.flatten(start_dim=-2).to(torch.long)
      hist = flat_image.new_zeros(
          batch_shape + (256,), dtype=torch.int32
      )
      hist.scatter_add_(
          dim=-1,
          index=flat_image,
          src=hist.new_ones(1).expand_as(flat_image),
      )
      cum_hist = hist.cumsum(dim=-1)
  
      # The simplest form of lookup-table (LUT) that also achieves histogram equalization is
      # `lut = cum_hist / flat_image.shape[-1] * 255`
      # However, PIL uses a more elaborate scheme:
      # https://github.com/python-pillow/Pillow/blob/eb59cb61d5239ee69cbbf12709a0c6fd7314e6d7/src/PIL/ImageOps.py#L368-L385
      # `lut = ((cum_hist + num_non_max_pixels // (2 * 255)) // num_non_max_pixels) * 255`
  
      # The last non-zero element in the histogram is the first element in the cumulative histogram with the maximum
      # value. Thus, the "max" in `num_non_max_pixels` does not refer to 255 as the maximum value of uint8 images, but
      # rather the maximum value in the image, which might be or not be 255.
      index = cum_hist.argmax(dim=-1)
      num_non_max_pixels = flat_image.shape[-1] - hist.gather(
          dim=-1, index=index.unsqueeze_(-1)
      )
  
      # This is performance optimization that saves us one multiplication later. With this, the LUT computation simplifies
      # to `lut = (cum_hist + step // 2) // step` and thus saving the final multiplication by 255 while keeping the
      # division count the same. PIL uses the variable name `step` for this, so we keep that for easier comparison.
      step = num_non_max_pixels.div_(255, rounding_mode="floor")
  
      # Although it looks like we could return early if we find `step == 0` like PIL does, that is unfortunately not as
      # easy due to our support for batched images. We can only return early if `(step == 0).all()` holds. If it doesn't,
      # we have to go through the computation below anyway. Since `step == 0` is an edge case anyway, it makes no sense to
      # pay the runtime cost for checking it every time.
      valid_equalization = step.ne(0).unsqueeze_(-1)
  
      # `lut[k]` is computed with `cum_hist[k-1]` with `lut[0] == (step // 2) // step == 0`. Thus, we perform the
      # computation only for `lut[1:]` with `cum_hist[:-1]` and add `lut[0] == 0` afterwards.
      cum_hist = cum_hist[..., :-1]
      (
          cum_hist.add_(step // 2)
          # We need the `clamp_`(min=1) call here to avoid zero division since they fail for integer dtypes. This has no
          # effect on the returned result of this kernel since images inside the batch with `step == 0` are returned as is
          # instead of equalized version.
          .div_(step.clamp_(min=1), rounding_mode="floor")
          # We need the `clamp_` call here since PILs LUT computation scheme can produce values outside the valid value
          # range of uint8 images
          .clamp_(0, 255)
      )
      lut = cum_hist.to(torch.uint8)
      lut = torch.cat(
          [lut.new_zeros(1).expand(batch_shape + (1,)), lut], dim=-1
      )
      equalized_image = lut.gather(dim=-1, index=flat_image).view_as(
          image
      )
  
      output = torch.where(valid_equalization, equalized_image, image)
      return to_dtype_image(output, output_dtype, scale=True)
  
imports: from typing import List
  import PIL.Image
  import torch
  from torch.nn.functional import conv2d
  from torchvision import tv_tensors
  from torchvision.transforms import _functional_pil
  from torchvision.transforms._functional_tensor import _max_value
  from torchvision.utils import _log_api_usage_once
  from ._misc import _num_value_bits, to_dtype_image
  from ._type_conversion import pil_to_tensor, to_pil_image
  from ._utils import _get_kernel, _register_kernel_internal
label_desc: Use image node_id 37 for calling a global function with example usage: equalize_image(image) and returns: to_dtype_image, image