Source code for laserbeamsize.masks

# pylint: disable=invalid-name
# pylint: disable=too-many-locals
# pylint: disable=too-many-arguments

"""
Routines for creating image masks helpful for beam analysis.

Full documentation is available at <https://laserbeamsize.readthedocs.io>
"""

import numpy as np
from PIL import Image, ImageDraw
import laserbeamsize as lbs

__all__ = ('corner_mask',
           'perimeter_mask',
           'rotated_rect_mask',
           'elliptical_mask',
           'iso_background_mask',
           )


[docs] def elliptical_mask(image, xc, yc, dx, dy, phi): """ Create a boolean mask for a rotated elliptical disk. The returned mask is the same size as `image`. Args: image: 2D array xc: horizontal center of beam yc: vertical center of beam dx: ellipse diameter for axis closest to horizontal dy: ellipse diameter for axis closest to vertical phi: angle that elliptical beam is rotated [radians] Returns: masked_image: 2D array with True values inside ellipse """ v, h = image.shape y, x = np.ogrid[:v, :h] sinphi = np.sin(phi) cosphi = np.cos(phi) rx = dx / 2 ry = dy / 2 xx = x - xc yy = y - yc r2 = (xx * cosphi - yy * sinphi)**2 / rx**2 + (xx * sinphi + yy * cosphi)**2 / ry**2 the_mask = r2 <= 1 return the_mask
[docs] def corner_mask(image, corner_fraction=0.035): """ Create boolean mask for image with corners marked as True. Each of the four corners is a fixed percentage of the entire image. ISO 11146-3 recommends values from 2-5% for `corner_fraction` the default is 0.035=3.5% of the iamge. Args: image : the image to work with corner_fraction: the fractional size of corner rectangles Returns: masked_image: 2D array with True values in four corners """ v, h = image.shape n = int(v * corner_fraction) m = int(h * corner_fraction) the_mask = np.full_like(image, False, dtype=bool) the_mask[:n, :m] = True the_mask[:n, -m:] = True the_mask[-n:, :m] = True the_mask[-n:, -m:] = True return the_mask
[docs] def perimeter_mask(image, corner_fraction=0.035): """ Create boolean mask for image with a perimeter marked as True. The perimeter is the same width as the corners created by corner_mask which is a fixed percentage (default 3.5%) of the entire image. Args: image : the image to work with corner_fraction: determines the width of the perimeter Returns: masked_image: 2D array with True values around rect perimeter """ v, h = image.shape n = int(v * corner_fraction) m = int(h * corner_fraction) the_mask = np.full_like(image, False, dtype=bool) the_mask[:, :m] = True the_mask[:, -m:] = True the_mask[:n, :] = True the_mask[-n:, :] = True return the_mask
def rotated_rect_mask_slow(image, xc, yc, dx, dy, phi, mask_diameters=3): """ Create ISO 11146 rectangular mask for specified beam. ISO 11146-2 §7.2 states that integration should be carried out over "a rectangular integration area which is centred to the beam centroid, defined by the spatial first order moments, orientated parallel to the principal axes of the power density distribution, and sized three times the beam widths". This routine creates a mask with `true` values for each pixel in the image that should be part of the integration. The rectangular mask is `mask_diameters' times the pixel diameters of the ellipse. The rectangular mask is rotated about (xc, yc) so that it is aligned with the elliptical spot. Args: image: the image to work with xc: horizontal center of beam yc: vertical center of beam dx: ellipse diameter for axis closest to horizontal dy: ellipse diameter for axis closest to vertical phi: angle that elliptical beam is rotated [radians] Returns: masked_image: 2D array with True values inside rectangle """ raw_mask = np.full_like(image, 0, dtype=float) v, h = image.shape rx = mask_diameters * dx / 2 ry = mask_diameters * dy / 2 vlo = max(0, int(yc - ry)) vhi = min(v, int(yc + ry)) hlo = max(0, int(xc - rx)) hhi = min(h, int(xc + rx)) raw_mask[vlo:vhi, hlo:hhi] = 1 rot_mask = lbs.rotate_image(raw_mask, xc, yc, phi) >= 0.5 return rot_mask
[docs] def rotated_rect_mask(image, xc, yc, dx, dy, phi, mask_diameters=3): """ Create ISO 11146 rectangular mask for specified beam. ISO 11146-2 §7.2 states that integration should be carried out over "a rectangular integration area which is centred to the beam centroid, defined by the spatial first order moments, orientated parallel to the principal axes of the power density distribution, and sized three times the beam widths". This routine creates a mask with `true` values for each pixel in the image that should be part of the integration. The rectangular mask is `mask_diameters` times the pixel diameters of the ellipse. The rectangular mask is rotated about (xc, yc) and then drawn using PIL Args: image: the image to work with xc: horizontal center of beam yc: vertical center of beam dx: ellipse diameter for axis closest to horizontal dy: ellipse diameter for axis closest to vertical phi: angle that elliptical beam is rotated [radians] mask_diameters: number of diameters to include Returns: masked_image: 2D array with True values inside rectangle """ v, h = image.shape rx = mask_diameters * dx / 2 ry = mask_diameters * dy / 2 s = np.sin(-phi) c = np.cos(-phi) xx, xy = rx * c, rx * s yx, yy = - ry * s, ry * c x1, y1 = xc + xx + yx, yc + xy + yy x2, y2 = xc + xx - yx, yc + xy - yy x3, y3 = xc - xx - yx, yc - xy - yy x4, y4 = xc - xx + yx, yc - xy + yy g = Image.new('L', (h, v), 0) ImageDraw.Draw(g).polygon([(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)], outline=1, fill=1) mask = np.array(g) return mask.astype(bool)
[docs] def iso_background_mask(image, corner_fraction=0.035, nT=3): """ Return a mask indicating the background pixels in an image. We estimate the mean and standard deviation using the values in the corners. All pixel values that fall below the mean+nT*stdev are considered unilluminated (background) pixels. Args: image : the image to work with nT: how many standard deviations to subtract corner_fraction: the fractional size of corner rectangles Returns: background_mask: 2D array of True/False values """ # estimate background ave, std = lbs.corner_background(image, corner_fraction=corner_fraction) # defined ISO/TR 11146-3:2004, equation 59 threshold = ave + nT * std background_mask = image < threshold return background_mask