Skip to content

odak.learn.tools

odak.learn.tools

Provides necessary definitions for general tools used across the library.

load_image(fn, normalizeby=0.0, torch_style=False)

Definition to load an image from a given location as a torch tensor.

Parameters:

  • fn
           Filename.
    
  • normalizeby
           Value to to normalize images with. Default value of zero will lead to no normalization.
    
  • torch_style
           If set True, it will load an image mxnx3 as 3xmxn.
    

Returns:

  • image ( ndarray ) –

    Image loaded as a Numpy array.

Source code in odak/learn/tools/file.py
def load_image(fn, normalizeby = 0., torch_style = False):
    """
    Definition to load an image from a given location as a torch tensor.

    Parameters
    ----------
    fn           : str
                   Filename.
    normalizeby  : float or optional
                   Value to to normalize images with. Default value of zero will lead to no normalization.
    torch_style  : bool or optional
                   If set True, it will load an image mxnx3 as 3xmxn.

    Returns
    -------
    image        :  ndarray
                    Image loaded as a Numpy array.

    """
    image = odak.tools.load_image(fn, normalizeby = normalizeby, torch_style = torch_style)
    image = torch.from_numpy(image).float()
    return image

resize(image, multiplier=0.5, mode='nearest')

Definition to resize an image.

Parameters:

  • image
            Image with MxNx3 resolution.
    
  • multiplier
            Multiplier used in resizing operation (e.g., 0.5 is half size in one axis).
    
  • mode
            Mode to be used in scaling, nearest, bilinear, etc.
    

Returns:

  • new_image ( tensor ) –

    Resized image.

Source code in odak/learn/tools/file.py
def resize(image, multiplier = 0.5, mode = 'nearest'):
    """
    Definition to resize an image.

    Parameters
    ----------
    image         : torch.tensor
                    Image with MxNx3 resolution.
    multiplier    : float
                    Multiplier used in resizing operation (e.g., 0.5 is half size in one axis).
    mode          : str
                    Mode to be used in scaling, nearest, bilinear, etc.

    Returns
    -------
    new_image     : torch.tensor
                    Resized image.

    """
    scale = torch.nn.Upsample(scale_factor = multiplier, mode = mode)
    new_image = torch.zeros((int(image.shape[0] * multiplier), int(image.shape[1] * multiplier), 3)).to(image.device)
    for i in range(3):
        cache = image[:,:,i].unsqueeze(0)
        cache = cache.unsqueeze(0)
        new_cache = scale(cache).unsqueeze(0)
        new_image[:,:,i] = new_cache.unsqueeze(0)
    return new_image

save_image(fn, img, cmin=0, cmax=255, color_depth=8)

Definition to save a torch tensor as an image.

Parameters:

  • fn
           Filename.
    
  • img
           A numpy array with NxMx3 or NxMx1 shapes.
    
  • cmin
           Minimum value that will be interpreted as 0 level in the final image.
    
  • cmax
           Maximum value that will be interpreted as 255 level in the final image.
    
  • color_depth
           Color depth of an image. Default is eight.
    

Returns:

  • bool ( bool ) –

    True if successful.

Source code in odak/learn/tools/file.py
def save_image(fn, img, cmin = 0, cmax = 255, color_depth = 8):
    """
    Definition to save a torch tensor as an image.

    Parameters
    ----------
    fn           : str
                   Filename.
    img          : ndarray
                   A numpy array with NxMx3 or NxMx1 shapes.
    cmin         : int
                   Minimum value that will be interpreted as 0 level in the final image.
    cmax         : int
                   Maximum value that will be interpreted as 255 level in the final image.
    color_depth  : int
                   Color depth of an image. Default is eight.


    Returns
    ----------
    bool         :  bool
                    True if successful.

    """
    if len(img.shape) ==  4:
        img = img.squeeze(0)
    if len(img.shape) > 2 and torch.argmin(torch.tensor(img.shape)) == 0:
        new_img = torch.zeros(img.shape[1], img.shape[2], img.shape[0]).to(img.device)
        for i in range(img.shape[0]):
            new_img[:, :, i] = img[i].detach().clone()
        img = new_img.detach().clone()
    img = img.cpu().detach().numpy()
    return odak.tools.save_image(fn, img, cmin = cmin, cmax = cmax, color_depth = color_depth)

save_torch_tensor(fn, tensor)

Definition to save a torch tensor.

Parameters:

  • fn
           Filename.
    
  • tensor
           Torch tensor to be saved.
    
Source code in odak/learn/tools/file.py
def save_torch_tensor(fn, tensor):
    """
    Definition to save a torch tensor.


    Parameters
    ----------
    fn           : str
                   Filename.
    tensor       : torch.tensor
                   Torch tensor to be saved.
    """ 
    torch.save(tensor, expanduser(fn))

torch_load(fn)

Definition to load a torch files (*.pt).

Parameters:

  • fn
           Filename.
    

Returns:

  • data ( any ) –

    See torch.load() for more.

Source code in odak/learn/tools/file.py
def torch_load(fn):
    """
    Definition to load a torch files (*.pt).

    Parameters
    ----------
    fn           : str
                   Filename.

    Returns
    -------
    data         : any
                   See torch.load() for more.
    """  
    data = torch.load(expanduser(fn))
    return data

histogram_loss(frame, ground_truth, bins=32, limits=[0.0, 1.0])

Function for evaluating a frame against a target using histogram.

Parameters:

  • frame
               Input frame [1 x 3 x m x n]  or [3 x m x n] or [1 x m x n] or [m x n].
    
  • ground_truth
               Ground truth [1 x 3 x m x n] or  [3 x m x n] or [1 x m x n] or  [m x n].
    
  • bins
               Number of bins.
    
  • limits
               Limits.
    

Returns:

  • loss ( float ) –

    Loss from evaluation.

Source code in odak/learn/tools/loss.py
def histogram_loss(frame, ground_truth, bins = 32, limits = [0., 1.]):
    """
    Function for evaluating a frame against a target using histogram.

    Parameters
    ----------
    frame            : torch.tensor
                       Input frame [1 x 3 x m x n]  or [3 x m x n] or [1 x m x n] or [m x n].
    ground_truth     : torch.tensor
                       Ground truth [1 x 3 x m x n] or  [3 x m x n] or [1 x m x n] or  [m x n].
    bins             : int
                       Number of bins.
    limits           : list
                       Limits.

    Returns
    -------
    loss             : float
                       Loss from evaluation.
    """
    if len(frame.shape) == 2:
        frame = frame.unsqueeze(0)
    if len(frame.shape) == 3:
        frame = frame.unsqueeze(0)
    histogram_frame = torch.zeros(frame.shape[1], bins).to(frame.device)
    histogram_ground_truth = torch.zeros(frame.shape[1], bins).to(frame.device)
    l2 = torch.nn.MSELoss()
    for i in range(frame.shape[1]):
        histogram_frame[i] = torch.histc(frame[:, i].flatten(), bins = bins, min = limits[0], max = limits[1])
        histogram_ground_truth[i] = torch.histc(frame[:, i].flatten(), bins = bins, min = limits[0], max = limits[1])
    loss = l2(histogram_frame, histogram_ground_truth)
    return loss

michelson_contrast(image, roi_high, roi_low)

A function to calculate michelson contrast ratio of given region of interests of the image.

Parameters:

  • image
            Image to be tested [1 x 3 x m x n] or [3 x m x n] or [m x n].
    
  • roi_high
            Corner locations of the roi for high intensity area [m_start, m_end, n_start, n_end].
    
  • roi_low
            Corner locations of the roi for low intensity area [m_start, m_end, n_start, n_end].
    

Returns:

  • result ( tensor ) –

    Michelson contrast for the given regions. [1] or [3] depending on input image.

Source code in odak/learn/tools/loss.py
def michelson_contrast(image, roi_high, roi_low):
    """
    A function to calculate michelson contrast ratio of given region of interests of the image.

    Parameters
    ----------
    image         : torch.tensor
                    Image to be tested [1 x 3 x m x n] or [3 x m x n] or [m x n].
    roi_high      : torch.tensor
                    Corner locations of the roi for high intensity area [m_start, m_end, n_start, n_end].
    roi_low       : torch.tensor
                    Corner locations of the roi for low intensity area [m_start, m_end, n_start, n_end].

    Returns
    -------
    result        : torch.tensor
                    Michelson contrast for the given regions. [1] or [3] depending on input image.
    """
    if len(image.shape) == 2:
        image = image.unsqueeze(0)
    if len(image.shape) == 3:
        image = image.unsqueeze(0)
    region_low = image[:, :, roi_low[0]:roi_low[1], roi_low[2]:roi_low[3]]
    region_high = image[:, :, roi_high[0]:roi_high[1], roi_high[2]:roi_high[3]]
    high = torch.mean(region_high, dim = (2, 3))
    low = torch.mean(region_low, dim = (2, 3))
    result = (high - low) / (high + low)
    return result.squeeze(0)

multi_scale_total_variation_loss(frame, levels=3)

Function for evaluating a frame against a target using multi scale total variation approach. Here, multi scale refers to image pyramid of an input frame, where at each level image resolution is half of the previous level.

Parameters:

  • frame
            Input frame [1 x 3 x m x n] or [3 x m x n] or [m x n].
    
  • levels
            Number of levels to go in the image pyriamid.
    

Returns:

  • loss ( float ) –

    Loss from evaluation.

Source code in odak/learn/tools/loss.py
def multi_scale_total_variation_loss(frame, levels = 3):
    """
    Function for evaluating a frame against a target using multi scale total variation approach. Here, multi scale refers to image pyramid of an input frame, where at each level image resolution is half of the previous level.

    Parameters
    ----------
    frame         : torch.tensor
                    Input frame [1 x 3 x m x n] or [3 x m x n] or [m x n].
    levels        : int
                    Number of levels to go in the image pyriamid.

    Returns
    -------
    loss          : float
                    Loss from evaluation.
    """
    if len(frame.shape) == 2:
        frame = frame.unsqueeze(0)
    if len(frame.shape) == 3:
        frame = frame.unsqueeze(0)
    scale = torch.nn.Upsample(scale_factor = 0.5, mode = 'nearest')
    level = frame
    loss = 0
    for i in range(levels):
        if i != 0:
           level = scale(level)
        loss += total_variation_loss(level) 
    return loss

psnr(image, ground_truth, peak_value=1.0)

A function to calculate peak-signal-to-noise ratio of an image with respect to a ground truth image.

Parameters:

  • image
            Image to be tested.
    
  • ground_truth
            Ground truth image.
    
  • peak_value
            Peak value that given tensors could have.
    

Returns:

  • result ( tensor ) –

    Peak-signal-to-noise ratio.

Source code in odak/learn/tools/loss.py
def psnr(image, ground_truth, peak_value = 1.0):
    """
    A function to calculate peak-signal-to-noise ratio of an image with respect to a ground truth image.

    Parameters
    ----------
    image         : torch.tensor
                    Image to be tested.
    ground_truth  : torch.tensor
                    Ground truth image.
    peak_value    : float
                    Peak value that given tensors could have.

    Returns
    -------
    result        : torch.tensor
                    Peak-signal-to-noise ratio.
    """
    mse = torch.mean((ground_truth - image)**2)
    result = 20 * torch.log10(peak_value / torch.sqrt(mse))
    return result

radial_basis_function(value, epsilon=0.5)

Function to pass a value into radial basis function with Gaussian description.

Parameters:

  • value
               Value(s) to pass to the radial basis function.
    
  • epsilon
               Epsilon used in the Gaussian radial basis function (e.g., y=e^(-(epsilon x value)^2).
    

Returns:

  • output ( tensor ) –

    Output values.

Source code in odak/learn/tools/loss.py
def radial_basis_function(value, epsilon = 0.5):
    """
    Function to pass a value into radial basis function with Gaussian description.

    Parameters
    ----------
    value            : torch.tensor
                       Value(s) to pass to the radial basis function. 
    epsilon          : float
                       Epsilon used in the Gaussian radial basis function (e.g., y=e^(-(epsilon x value)^2).

    Returns
    -------
    output           : torch.tensor
                       Output values.
    """
    output = torch.exp((-(epsilon * value)**2))
    return output

total_variation_loss(frame)

Function for evaluating a frame against a target using total variation approach.

Parameters:

  • frame
            Input frame [1 x 3 x m x n] or [3 x m x n] or [m x n].
    

Returns:

  • loss ( float ) –

    Loss from evaluation.

Source code in odak/learn/tools/loss.py
def total_variation_loss(frame):
    """
    Function for evaluating a frame against a target using total variation approach.

    Parameters
    ----------
    frame         : torch.tensor
                    Input frame [1 x 3 x m x n] or [3 x m x n] or [m x n].

    Returns
    -------
    loss          : float
                    Loss from evaluation.
    """
    if len(frame.shape) == 2:
        frame = frame.unsqueeze(0)
    if len(frame.shape) == 3:
        frame = frame.unsqueeze(0)
    diff_x = frame[:, :, :, 1:] - frame[:, :, :, :-1]
    diff_y = frame[:, :, 1:, :] - frame[:, :, :-1, :]
    pixel_count = frame.shape[0] * frame.shape[1] * frame.shape[2] * frame.shape[3]
    loss = ((diff_x ** 2).sum() + (diff_y ** 2).sum()) / pixel_count
    return loss

weber_contrast(image, roi_high, roi_low)

A function to calculate weber contrast ratio of given region of interests of the image.

Parameters:

  • image
            Image to be tested [1 x 3 x m x n] or [3 x m x n] or [m x n].
    
  • roi_high
            Corner locations of the roi for high intensity area [m_start, m_end, n_start, n_end].
    
  • roi_low
            Corner locations of the roi for low intensity area [m_start, m_end, n_start, n_end].
    

Returns:

  • result ( tensor ) –

    Weber contrast for given regions. [1] or [3] depending on input image.

Source code in odak/learn/tools/loss.py
def weber_contrast(image, roi_high, roi_low):
    """
    A function to calculate weber contrast ratio of given region of interests of the image.

    Parameters
    ----------
    image         : torch.tensor
                    Image to be tested [1 x 3 x m x n] or [3 x m x n] or [m x n].
    roi_high      : torch.tensor
                    Corner locations of the roi for high intensity area [m_start, m_end, n_start, n_end].
    roi_low       : torch.tensor
                    Corner locations of the roi for low intensity area [m_start, m_end, n_start, n_end].

    Returns
    -------
    result        : torch.tensor
                    Weber contrast for given regions. [1] or [3] depending on input image.
    """
    if len(image.shape) == 2:
        image = image.unsqueeze(0)
    if len(image.shape) == 3:
        image = image.unsqueeze(0)
    region_low = image[:, :, roi_low[0]:roi_low[1], roi_low[2]:roi_low[3]]
    region_high = image[:, :, roi_high[0]:roi_high[1], roi_high[2]:roi_high[3]]
    high = torch.mean(region_high, dim = (2, 3))
    low = torch.mean(region_low, dim = (2, 3))
    result = (high - low) / low
    return result.squeeze(0)

blur_gaussian(field, kernel_length=[21, 21], nsigma=[3, 3], padding='same')

A definition to blur a field using a Gaussian kernel.

Parameters:

  • field
            MxN field.
    
  • kernel_length (list, default: [21, 21] ) –
            Length of the Gaussian kernel along X and Y axes.
    
  • nsigma
            Sigma of the Gaussian kernel along X and Y axes.
    
  • padding
            Padding value, see torch.nn.functional.conv2d() for more.
    

Returns:

  • blurred_field ( tensor ) –

    Blurred field.

Source code in odak/learn/tools/matrix.py
def blur_gaussian(field, kernel_length = [21, 21], nsigma = [3, 3], padding = 'same'):
    """
    A definition to blur a field using a Gaussian kernel.

    Parameters
    ----------
    field         : torch.tensor
                    MxN field.
    kernel_length : list
                    Length of the Gaussian kernel along X and Y axes.
    nsigma        : list
                    Sigma of the Gaussian kernel along X and Y axes.
    padding       : int or string
                    Padding value, see torch.nn.functional.conv2d() for more.

    Returns
    ----------
    blurred_field : torch.tensor
                    Blurred field.
    """
    kernel = generate_2d_gaussian(kernel_length, nsigma).to(field.device)
    kernel = kernel.unsqueeze(0).unsqueeze(0)
    if len(field.shape) == 2:
        field = field.view(1, 1, field.shape[-2], field.shape[-1])
    blurred_field = torch.nn.functional.conv2d(field, kernel, padding='same')
    if field.shape[1] == 1:
        blurred_field = blurred_field.view(
                                           blurred_field.shape[-2],
                                           blurred_field.shape[-1]
                                          )
    return blurred_field

convolve2d(field, kernel)

Definition to convolve a field with a kernel by multiplying in frequency space.

Parameters:

  • field
          Input field with MxN shape.
    
  • kernel
          Input kernel with MxN shape.
    

Returns:

  • new_field ( tensor ) –

    Convolved field.

Source code in odak/learn/tools/matrix.py
def convolve2d(field, kernel):
    """
    Definition to convolve a field with a kernel by multiplying in frequency space.

    Parameters
    ----------
    field       : torch.tensor
                  Input field with MxN shape.
    kernel      : torch.tensor
                  Input kernel with MxN shape.

    Returns
    ----------
    new_field   : torch.tensor
                  Convolved field.
    """
    fr = torch.fft.fft2(field)
    fr2 = torch.fft.fft2(torch.flip(torch.flip(kernel, [1, 0]), [0, 1]))
    m, n = fr.shape
    new_field = torch.real(torch.fft.ifft2(fr*fr2))
    new_field = torch.roll(new_field, shifts=(int(n/2+1), 0), dims=(1, 0))
    new_field = torch.roll(new_field, shifts=(int(m/2+1), 0), dims=(0, 1))
    return new_field

crop_center(field, size=None)

Definition to crop the center of a field with 2Mx2N size. The outcome is a MxN array.

Parameters:

  • field
          Input field 2M x 2N or K x L x 2M x 2N or K x 2M x 2N x L array.
    
  • size
          Dimensions to crop with respect to center of the image (e.g., M x N or 1 x 1 x M x N).
    

Returns:

  • cropped ( ndarray ) –

    Cropped version of the input field.

Source code in odak/learn/tools/matrix.py
def crop_center(field, size = None):
    """
    Definition to crop the center of a field with 2Mx2N size. The outcome is a MxN array.

    Parameters
    ----------
    field       : ndarray
                  Input field 2M x 2N or K x L x 2M x 2N or K x 2M x 2N x L array.
    size        : list
                  Dimensions to crop with respect to center of the image (e.g., M x N or 1 x 1 x M x N).

    Returns
    ----------
    cropped     : ndarray
                  Cropped version of the input field.
    """
    orig_resolution = field.shape
    if len(field.shape) < 3:
        field = field.unsqueeze(0)
    if len(field.shape) < 4:
        field = field.unsqueeze(0)
    permute_flag = False
    if field.shape[-1] < 5:
        permute_flag = True
        field = field.permute(0, 3, 1, 2)
    if type(size) == type(None):
        qx = int(field.shape[-2] // 4)
        qy = int(field.shape[-1] // 4)
        cropped_padded = field[:, :, qx: qx + field.shape[-2] // 2, qy:qy + field.shape[-1] // 2]
    else:
        cx = int(field.shape[-2] // 2)
        cy = int(field.shape[-1] // 2)
        hx = int(size[-2] // 2)
        hy = int(size[-1] // 2)
        cropped_padded = field[:, :, cx-hx:cx+hx, cy-hy:cy+hy]
    cropped = cropped_padded
    if permute_flag:
        cropped = cropped.permute(0, 2, 3, 1)
    if len(orig_resolution) == 2:
        cropped = cropped_padded.squeeze(0).squeeze(0)
    if len(orig_resolution) == 3:
        cropped = cropped_padded.squeeze(0)
    return cropped

generate_2d_dirac_delta(kernel_length=[21, 21], a=[3, 3], mu=[0, 0], theta=0, normalize=False)

Generate 2D Dirac delta function by using Gaussian distribution. Inspired from https://en.wikipedia.org/wiki/Dirac_delta_function

Parameters:

  • kernel_length (list, default: [21, 21] ) –
            Length of the Dirac delta function along X and Y axes.
    
  • a
            The scale factor in Gaussian distribution to approximate the Dirac delta function. 
            As a approaches zero, the Gaussian distribution becomes infinitely narrow and tall at the center (x=0), approaching the Dirac delta function.
    
  • mu
            Mu of the Gaussian kernel along X and Y axes.
    
  • theta
            The rotation angle of the 2D Dirac delta function.
    
  • normalize
            If set True, normalize the output.
    

Returns:

  • kernel_2d ( tensor ) –

    Generated 2D Dirac delta function.

Source code in odak/learn/tools/matrix.py
def generate_2d_dirac_delta(
                            kernel_length = [21, 21],
                            a = [3, 3],
                            mu = [0, 0],
                            theta = 0,
                            normalize = False
                           ):
    """
    Generate 2D Dirac delta function by using Gaussian distribution.
    Inspired from https://en.wikipedia.org/wiki/Dirac_delta_function

    Parameters
    ----------
    kernel_length : list
                    Length of the Dirac delta function along X and Y axes.
    a             : list
                    The scale factor in Gaussian distribution to approximate the Dirac delta function. 
                    As a approaches zero, the Gaussian distribution becomes infinitely narrow and tall at the center (x=0), approaching the Dirac delta function.
    mu            : list
                    Mu of the Gaussian kernel along X and Y axes.
    theta         : float
                    The rotation angle of the 2D Dirac delta function.
    normalize     : bool
                    If set True, normalize the output.

    Returns
    ----------
    kernel_2d     : torch.tensor
                    Generated 2D Dirac delta function.
    """
    x = torch.linspace(-kernel_length[0] / 2., kernel_length[0] / 2., kernel_length[0])
    y = torch.linspace(-kernel_length[1] / 2., kernel_length[1] / 2., kernel_length[1])
    X, Y = torch.meshgrid(x, y, indexing='ij')
    X = X - mu[0]
    Y = Y - mu[1]
    X_rot = X * np.cos(theta) - Y * np.sin(theta)
    Y_rot = X * np.sin(theta) + Y * np.cos(theta)
    kernel_2d = (1 / (abs(a[0] * a[1]) * np.pi)) * np.exp(-((X_rot / a[0]) ** 2 + (Y_rot / a[1]) ** 2))
    if normalize:
        kernel_2d = kernel_2d / kernel_2d.max()
    return kernel_2d

generate_2d_gaussian(kernel_length=[21, 21], nsigma=[3, 3], mu=[0, 0], normalize=False)

Generate 2D Gaussian kernel. Inspired from https://stackoverflow.com/questions/29731726/how-to-calculate-a-gaussian-kernel-matrix-efficiently-in-numpy

Parameters:

  • kernel_length (list, default: [21, 21] ) –
            Length of the Gaussian kernel along X and Y axes.
    
  • nsigma
            Sigma of the Gaussian kernel along X and Y axes.
    
  • mu
            Mu of the Gaussian kernel along X and Y axes.
    
  • normalize
            If set True, normalize the output.
    

Returns:

  • kernel_2d ( tensor ) –

    Generated Gaussian kernel.

Source code in odak/learn/tools/matrix.py
def generate_2d_gaussian(kernel_length = [21, 21], nsigma = [3, 3], mu = [0, 0], normalize = False):
    """
    Generate 2D Gaussian kernel. Inspired from https://stackoverflow.com/questions/29731726/how-to-calculate-a-gaussian-kernel-matrix-efficiently-in-numpy

    Parameters
    ----------
    kernel_length : list
                    Length of the Gaussian kernel along X and Y axes.
    nsigma        : list
                    Sigma of the Gaussian kernel along X and Y axes.
    mu            : list
                    Mu of the Gaussian kernel along X and Y axes.
    normalize     : bool
                    If set True, normalize the output.

    Returns
    ----------
    kernel_2d     : torch.tensor
                    Generated Gaussian kernel.
    """
    x = torch.linspace(-kernel_length[0]/2., kernel_length[0]/2., kernel_length[0])
    y = torch.linspace(-kernel_length[1]/2., kernel_length[1]/2., kernel_length[1])
    X, Y = torch.meshgrid(x, y, indexing='ij')
    if nsigma[0] == 0:
        nsigma[0] = 1e-5
    if nsigma[1] == 0:
        nsigma[1] = 1e-5
    kernel_2d = 1. / (2. * np.pi * nsigma[0] * nsigma[1]) * torch.exp(-((X - mu[0])**2. / (2. * nsigma[0]**2.) + (Y - mu[1])**2. / (2. * nsigma[1]**2.)))
    if normalize:
        kernel_2d = kernel_2d / kernel_2d.max()
    return kernel_2d

quantize(image_field, bits=8, limits=[0.0, 1.0])

Definition to quantize a image field (0-255, 8 bit) to a certain bits level.

Parameters:

  • image_field (tensor) –
          Input image field between any range.
    
  • bits
          A value in between one to eight.
    
  • limits
          The minimum and maximum of the image_field variable.
    

Returns:

  • new_field ( tensor ) –

    Quantized image field.

Source code in odak/learn/tools/matrix.py
def quantize(image_field, bits = 8, limits = [0., 1.]):
    """ 
    Definition to quantize a image field (0-255, 8 bit) to a certain bits level.

    Parameters
    ----------
    image_field : torch.tensor
                  Input image field between any range.
    bits        : int
                  A value in between one to eight.
    limits      : list
                  The minimum and maximum of the image_field variable.

    Returns
    ----------
    new_field   : torch.tensor
                  Quantized image field.
    """
    normalized_field = (image_field - limits[0]) / (limits[1] - limits[0])
    divider = 2 ** bits
    new_field = normalized_field * divider
    new_field = new_field.int()
    return new_field

zero_pad(field, size=None, method='center')

Definition to zero pad a MxN array to 2Mx2N array.

Parameters:

  • field
                Input field MxN or KxJxMxN or KxMxNxJ array.
    
  • size
                Size to be zeropadded (e.g., [m, n], last two dimensions only).
    
  • method
                Zeropad either by placing the content to center or to the left.
    

Returns:

  • field_zero_padded ( ndarray ) –

    Zeropadded version of the input field.

Source code in odak/learn/tools/matrix.py
def zero_pad(field, size = None, method = 'center'):
    """
    Definition to zero pad a MxN array to 2Mx2N array.

    Parameters
    ----------
    field             : ndarray
                        Input field MxN or KxJxMxN or KxMxNxJ array.
    size              : list
                        Size to be zeropadded (e.g., [m, n], last two dimensions only).
    method            : str
                        Zeropad either by placing the content to center or to the left.

    Returns
    ----------
    field_zero_padded : ndarray
                        Zeropadded version of the input field.
    """
    orig_resolution = field.shape
    if len(field.shape) < 3:
        field = field.unsqueeze(0)
    if len(field.shape) < 4:
        field = field.unsqueeze(0)
    permute_flag = False
    if field.shape[-1] < 5:
        permute_flag = True
        field = field.permute(0, 3, 1, 2)
    if type(size) == type(None):
        resolution = [field.shape[0], field.shape[1], 2 * field.shape[-2], 2 * field.shape[-1]]
    else:
        resolution = [field.shape[0], field.shape[1], size[0], size[1]]
    field_zero_padded = torch.zeros(resolution, device = field.device, dtype = field.dtype)
    if method == 'center':
       start = [
                resolution[-2] // 2 - field.shape[-2] // 2,
                resolution[-1] // 2 - field.shape[-1] // 2
               ]
       field_zero_padded[
                         :, :,
                         start[0] : start[0] + field.shape[-2],
                         start[1] : start[1] + field.shape[-1]
                         ] = field
    elif method == 'left':
       field_zero_padded[
                         :, :,
                         0: field.shape[-2],
                         0: field.shape[-1]
                        ] = field
    if permute_flag == True:
        field_zero_padded = field_zero_padded.permute(0, 2, 3, 1)
    if len(orig_resolution) == 2:
        field_zero_padded = field_zero_padded.squeeze(0).squeeze(0)
    if len(orig_resolution) == 3:
        field_zero_padded = field_zero_padded.squeeze(0)
    return field_zero_padded

grid_sample(no=[10, 10], size=[100.0, 100.0], center=[0.0, 0.0, 0.0], angles=[0.0, 0.0, 0.0])

Definition to generate samples over a surface.

Parameters:

  • no
          Number of samples.
    
  • size
          Physical size of the surface.
    
  • center
          Center location of the surface.
    
  • angles
          Tilt of the surface.
    

Returns:

  • samples ( tensor ) –

    Samples generated.

  • rotx ( tensor ) –

    Rotation matrix at X axis.

  • roty ( tensor ) –

    Rotation matrix at Y axis.

  • rotz ( tensor ) –

    Rotation matrix at Z axis.

Source code in odak/learn/tools/sample.py
def grid_sample(
                no = [10, 10],
                size = [100., 100.], 
                center = [0., 0., 0.], 
                angles = [0., 0., 0.]):
    """
    Definition to generate samples over a surface.

    Parameters
    ----------
    no          : list
                  Number of samples.
    size        : list
                  Physical size of the surface.
    center      : list
                  Center location of the surface.
    angles      : list
                  Tilt of the surface.

    Returns
    -------
    samples     : torch.tensor
                  Samples generated.
    rotx        : torch.tensor
                  Rotation matrix at X axis.
    roty        : torch.tensor
                  Rotation matrix at Y axis.
    rotz        : torch.tensor
                  Rotation matrix at Z axis.
    """
    center = torch.tensor(center)
    angles = torch.tensor(angles)
    size = torch.tensor(size)
    samples = torch.zeros((no[0], no[1], 3))
    step = [size[0] / (no[0] - 1), size[1] / (no[1] - 1)]
    x = torch.linspace(-size[0] / 2., size[0] / 2., no[0])
    y = torch.linspace(-size[1] / 2., size[1] / 2., no[1])
    X, Y = torch.meshgrid(x, y, indexing='ij')
    samples[:, :, 0] = X.detach().clone()
    samples[:, :, 1] = Y.detach().clone()
    samples = samples.reshape((samples.shape[0] * samples.shape[1], samples.shape[2]))
    samples, rotx, roty, rotz = rotate_points(samples, angles = angles, offset = center)
    return samples, rotx, roty, rotz

get_rotation_matrix(tilt_angles=[0.0, 0.0, 0.0], tilt_order='XYZ')

Function to generate rotation matrix for given tilt angles and tilt order.

Parameters:

  • tilt_angles
                 Tilt angles in degrees along XYZ axes.
    
  • tilt_order
                 Rotation order (e.g., XYZ, XZY, ZXY, YXZ, ZYX).
    

Returns:

  • rotmat ( tensor ) –

    Rotation matrix.

Source code in odak/learn/tools/transformation.py
def get_rotation_matrix(tilt_angles = [0., 0., 0.], tilt_order = 'XYZ'):
    """
    Function to generate rotation matrix for given tilt angles and tilt order.


    Parameters
    ----------
    tilt_angles        : list
                         Tilt angles in degrees along XYZ axes.
    tilt_order         : str
                         Rotation order (e.g., XYZ, XZY, ZXY, YXZ, ZYX).

    Returns
    -------
    rotmat             : torch.tensor
                         Rotation matrix.
    """
    rotx = rotmatx(tilt_angles[0])
    roty = rotmaty(tilt_angles[1])
    rotz = rotmatz(tilt_angles[2])
    if tilt_order =='XYZ':
        rotmat = torch.mm(rotz,torch.mm(roty, rotx))
    elif tilt_order == 'XZY':
        rotmat = torch.mm(roty,torch.mm(rotz, rotx))
    elif tilt_order == 'ZXY':
        rotmat = torch.mm(roty,torch.mm(rotx, rotz))
    elif tilt_order == 'YXZ':
        rotmat = torch.mm(rotz,torch.mm(rotx, roty))
    elif tilt_order == 'ZYX':
         rotmat = torch.mm(rotx,torch.mm(roty, rotz))
    return rotmat

rotate_points(point, angles=torch.tensor([[0, 0, 0]]), mode='XYZ', origin=torch.tensor([[0, 0, 0]]), offset=torch.tensor([[0, 0, 0]]))

Definition to rotate a given point. Note that rotation is always with respect to 0,0,0.

Parameters:

  • point
           A point with size of [3] or [1, 3] or [m, 3].
    
  • angles
           Rotation angles in degrees.
    
  • mode
           Rotation mode determines ordering of the rotations at each axis.
           There are XYZ,YXZ,ZXY and ZYX modes.
    
  • origin
           Reference point for a rotation.
           Expected size is [3] or [1, 3].
    
  • offset
           Shift with the given offset.
           Expected size is [3] or [1, 3] or [m, 3].
    

Returns:

  • result ( tensor ) –

    Result of the rotation [1 x 3] or [m x 3].

  • rotx ( tensor ) –

    Rotation matrix along X axis [3 x 3].

  • roty ( tensor ) –

    Rotation matrix along Y axis [3 x 3].

  • rotz ( tensor ) –

    Rotation matrix along Z axis [3 x 3].

Source code in odak/learn/tools/transformation.py
def rotate_points(
                 point,
                 angles = torch.tensor([[0, 0, 0]]), 
                 mode='XYZ', 
                 origin = torch.tensor([[0, 0, 0]]), 
                 offset = torch.tensor([[0, 0, 0]])
                ):
    """
    Definition to rotate a given point. Note that rotation is always with respect to 0,0,0.

    Parameters
    ----------
    point        : torch.tensor
                   A point with size of [3] or [1, 3] or [m, 3].
    angles       : torch.tensor
                   Rotation angles in degrees. 
    mode         : str
                   Rotation mode determines ordering of the rotations at each axis.
                   There are XYZ,YXZ,ZXY and ZYX modes.
    origin       : torch.tensor
                   Reference point for a rotation.
                   Expected size is [3] or [1, 3].
    offset       : torch.tensor
                   Shift with the given offset.
                   Expected size is [3] or [1, 3] or [m, 3].

    Returns
    ----------
    result       : torch.tensor
                   Result of the rotation [1 x 3] or [m x 3].
    rotx         : torch.tensor
                   Rotation matrix along X axis [3 x 3].
    roty         : torch.tensor
                   Rotation matrix along Y axis [3 x 3].
    rotz         : torch.tensor
                   Rotation matrix along Z axis [3 x 3].
    """
    origin = origin.to(point.device)
    offset = offset.to(point.device)
    if len(point.shape) == 1:
        point = point.unsqueeze(0)
    if len(angles.shape) == 1:
        angles = angles.unsqueeze(0)
    rotx = rotmatx(angles[:, 0])
    roty = rotmaty(angles[:, 1])
    rotz = rotmatz(angles[:, 2])
    new_point = (point - origin).T
    if mode == 'XYZ':
        result = torch.mm(rotz, torch.mm(roty, torch.mm(rotx, new_point))).T
    elif mode == 'XZY':
        result = torch.mm(roty, torch.mm(rotz, torch.mm(rotx, new_point))).T
    elif mode == 'YXZ':
        result = torch.mm(rotz, torch.mm(rotx, torch.mm(roty, new_point))).T
    elif mode == 'ZXY':
        result = torch.mm(roty, torch.mm(rotx, torch.mm(rotz, new_point))).T
    elif mode == 'ZYX':
        result = torch.mm(rotx, torch.mm(roty, torch.mm(rotz, new_point))).T
    result += origin
    result += offset
    return result, rotx, roty, rotz

rotmatx(angle)

Definition to generate a rotation matrix along X axis.

Parameters:

  • angle
           Rotation angles in degrees.
    

Returns:

  • rotx ( tensor ) –

    Rotation matrix along X axis.

Source code in odak/learn/tools/transformation.py
def rotmatx(angle):
    """
    Definition to generate a rotation matrix along X axis.

    Parameters
    ----------
    angle        : torch.tensor
                   Rotation angles in degrees.

    Returns
    ----------
    rotx         : torch.tensor
                   Rotation matrix along X axis.
    """
    angle = torch.deg2rad(angle)
    one = torch.ones(1, device = angle.device)
    zero = torch.zeros(1, device = angle.device)
    rotx = torch.stack([
                        torch.stack([ one,              zero,              zero]),
                        torch.stack([zero,  torch.cos(angle), -torch.sin(angle)]),
                        torch.stack([zero,  torch.sin(angle),  torch.cos(angle)])
                       ]).reshape(3, 3)
    return rotx

rotmaty(angle)

Definition to generate a rotation matrix along Y axis.

Parameters:

  • angle
           Rotation angles in degrees.
    

Returns:

  • roty ( tensor ) –

    Rotation matrix along Y axis.

Source code in odak/learn/tools/transformation.py
def rotmaty(angle):
    """
    Definition to generate a rotation matrix along Y axis.

    Parameters
    ----------
    angle        : torch.tensor
                   Rotation angles in degrees.

    Returns
    ----------
    roty         : torch.tensor
                   Rotation matrix along Y axis.
    """
    angle = torch.deg2rad(angle)
    one = torch.ones(1, device = angle.device)
    zero = torch.zeros(1, device = angle.device)
    roty = torch.stack([
                        torch.stack([ torch.cos(angle), zero, torch.sin(angle)]),
                        torch.stack([             zero,  one,             zero]),
                        torch.stack([-torch.sin(angle), zero, torch.cos(angle)])
                       ]).reshape(3, 3)
    return roty

rotmatz(angle)

Definition to generate a rotation matrix along Z axis.

Parameters:

  • angle
           Rotation angles in degrees.
    

Returns:

  • rotz ( tensor ) –

    Rotation matrix along Z axis.

Source code in odak/learn/tools/transformation.py
def rotmatz(angle):
    """
    Definition to generate a rotation matrix along Z axis.

    Parameters
    ----------
    angle        : torch.tensor
                   Rotation angles in degrees.

    Returns
    ----------
    rotz         : torch.tensor
                   Rotation matrix along Z axis.
    """
    angle = torch.deg2rad(angle)
    one = torch.ones(1, device = angle.device)
    zero = torch.zeros(1, device = angle.device)
    rotz = torch.stack([
                        torch.stack([torch.cos(angle), -torch.sin(angle), zero]),
                        torch.stack([torch.sin(angle),  torch.cos(angle), zero]),
                        torch.stack([            zero,              zero,  one])
                       ]).reshape(3,3)
    return rotz

tilt_towards(location, lookat)

Definition to tilt surface normal of a plane towards a point.

Parameters:

  • location
           Center of the plane to be tilted.
    
  • lookat
           Tilt towards this point.
    

Returns:

  • angles ( list ) –

    Rotation angles in degrees.

Source code in odak/learn/tools/transformation.py
def tilt_towards(location, lookat):
    """
    Definition to tilt surface normal of a plane towards a point.

    Parameters
    ----------
    location     : list
                   Center of the plane to be tilted.
    lookat       : list
                   Tilt towards this point.

    Returns
    ----------
    angles       : list
                   Rotation angles in degrees.
    """
    dx = location[0] - lookat[0]
    dy = location[1] - lookat[1]
    dz = location[2] - lookat[2]
    dist = torch.sqrt(torch.tensor(dx ** 2 + dy ** 2 + dz ** 2))
    phi = torch.atan2(torch.tensor(dy), torch.tensor(dx))
    theta = torch.arccos(dz / dist)
    angles = [0, float(torch.rad2deg(theta)), float(torch.rad2deg(phi))]
    return angles

cross_product(vector1, vector2)

Definition to cross product two vectors and return the resultant vector. Used method described under: http://en.wikipedia.org/wiki/Cross_product

Parameters:

  • vector1
           A vector/ray.
    
  • vector2
           A vector/ray.
    

Returns:

  • ray ( tensor ) –

    Array that contains starting points and cosines of a created ray.

Source code in odak/learn/tools/vector.py
def cross_product(vector1, vector2):
    """
    Definition to cross product two vectors and return the resultant vector. Used method described under: http://en.wikipedia.org/wiki/Cross_product

    Parameters
    ----------
    vector1      : torch.tensor
                   A vector/ray.
    vector2      : torch.tensor
                   A vector/ray.

    Returns
    ----------
    ray          : torch.tensor
                   Array that contains starting points and cosines of a created ray.
    """
    angle = torch.cross(vector1[1].T, vector2[1].T)
    angle = torch.tensor(angle)
    ray = torch.tensor([vector1[0], angle], dtype=torch.float32)
    return ray

distance_between_two_points(point1, point2)

Definition to calculate distance between two given points.

Parameters:

  • point1
          First point in X,Y,Z.
    
  • point2
          Second point in X,Y,Z.
    

Returns:

  • distance ( Tensor ) –

    Distance in between given two points.

Source code in odak/learn/tools/vector.py
def distance_between_two_points(point1, point2):
    """
    Definition to calculate distance between two given points.

    Parameters
    ----------
    point1      : torch.Tensor
                  First point in X,Y,Z.
    point2      : torch.Tensor
                  Second point in X,Y,Z.

    Returns
    ----------
    distance    : torch.Tensor
                  Distance in between given two points.
    """
    point1 = torch.tensor(point1) if not isinstance(point1, torch.Tensor) else point1
    point2 = torch.tensor(point2) if not isinstance(point2, torch.Tensor) else point2

    if len(point1.shape) == 1 and len(point2.shape) == 1:
        distance = torch.sqrt(torch.sum((point1 - point2) ** 2))
    elif len(point1.shape) == 2 or len(point2.shape) == 2:
        distance = torch.sqrt(torch.sum((point1 - point2) ** 2, dim=-1))

    return distance

same_side(p1, p2, a, b)

Definition to figure which side a point is on with respect to a line and a point. See http://www.blackpawn.com/texts/pointinpoly/ for more. If p1 and p2 are on the sameside, this definition returns True.

Parameters:

  • p1
          Point(s) to check.
    
  • p2
          This is the point check against.
    
  • a
          First point that forms the line.
    
  • b
          Second point that forms the line.
    
Source code in odak/learn/tools/vector.py
def same_side(p1, p2, a, b):
    """
    Definition to figure which side a point is on with respect to a line and a point. See http://www.blackpawn.com/texts/pointinpoly/ for more. If p1 and p2 are on the sameside, this definition returns True.

    Parameters
    ----------
    p1          : list
                  Point(s) to check.
    p2          : list
                  This is the point check against.
    a           : list
                  First point that forms the line.
    b           : list
                  Second point that forms the line.
    """
    ba = torch.subtract(b, a)
    p1a = torch.subtract(p1, a)
    p2a = torch.subtract(p2, a)
    cp1 = torch.cross(ba, p1a)
    cp2 = torch.cross(ba, p2a)
    test = torch.dot(cp1, cp2)
    if len(p1.shape) > 1:
        return test >= 0
    if test >= 0:
        return True
    return False