Source code for giant.image_processing.denoising.tvl1

from dataclasses import dataclass

import numpy as np
from numpy.typing import NDArray

import cv2


from giant.image_processing.utilities.image_validation_mixin import ImageValidationMixin
from giant.utilities.mixin_classes import AttributeEqualityComparison, AttributePrinting, UserOptionConfigured
from giant.utilities.options import UserOptions


[docs] @dataclass class TVL1DenoisingOptions(UserOptions): lambda_p: float = 1.0 """ Lower values leads to more noise removal but more bluring. Must be > 0 """ n_iter: int = 30 """ The number of iterations to run """
[docs] class TVL1Denoising(UserOptionConfigured[TVL1DenoisingOptions], TVL1DenoisingOptions, AttributeEqualityComparison, AttributePrinting, ImageValidationMixin): r""" Implements denoising using the total variation approach with a prime dual algorithm. Essentially we minimize the following .. math:: \left\|\left\|\nabla \mathbf{I}\right\|\right\| + \lambda\sum_i\left\|\left\|\mathbf{I}-\mathbf{N}_i\right\|\right\| where :math:`\mathbf{I}` is the denoised image, :math:`\mathbf{N}_i` are the input images, :math:`\nabla \mathbf{I}` is the gradient of the smoothed image, :math:`\lambda` is a tuning parameter balancing between smooth images (smaller) and crisp images (higher), and :math:`\left\|\left\|\bullet\right\|\right\|` is the :math:`L_2` norm operator. Generally, this works ok for denoising but can easily mistake dim point sources for noise and can produce weird ring artifacts around point sources, therefore, for star/point source only images it is probably preferable to use something like the GaussianDenoising. For more details on the algorithm see https://hal.science/hal-00437581v1 """ allowed_dtypes = [np.uint8] """ The allowed datatype. """ def __init__(self, options: TVL1DenoisingOptions | None = None) -> None: """ :param options: the options to configure the class with""" super().__init__(TVL1DenoisingOptions, options=options)
[docs] def __call__(self, image: NDArray) -> NDArray[np.uint8]: out = np.zeros(image.shape, dtype=np.uint8) cv2.denoise_TVL1([self._validate_and_convert_image(image)], out, self.lambda_p, self.n_iter) return out