Extract the ISO 11146 beam size from an image file

Overview

laserbeamsize


Simple and fast calculation of beam sizes from a single monochrome image based on the ISO 11146 method of variances. Some effort has been made to make the algorithm less sensitive to background offset and noise.

This module also supports M² calculations based on a series of images collected at various distances from the focused beam.

Extensive documentation can be found at <https://laserbeamsize.readthedocs.io>

Using laserbeamsize

  1. Install with pip:

    pip install --user laserbeamsize
    
  2. or run this code in the cloud using Google Collaboratory by selecting the Jupyter notebook that interests you.

  3. use binder which will create a new environment that allows you to run Jupyter notebooks. This takes a bit longer to start, but it automatically installs laserbeamsize.

  4. clone the laserbeamsize github repository and then add the repository to your PYTHONPATH environment variable

Determining the beam size in an image

Finding the center and dimensions of a good beam image:

import imageio
import numpy as np
import matplotlib.pyplot as plt
import laserbeamsize as lbs

beam = imageio.imread("t-hene.pgm")
x, y, dx, dy, phi = lbs.beam_size(beam)

print("The center of the beam ellipse is at (%.0f, %.0f)" % (x,y))
print("The ellipse diameter (closest to horizontal) is %.0f pixels" % dx)
print("The ellipse diameter (closest to   vertical) is %.0f pixels" % dy)
print("The ellipse is rotated %.0f° ccw from horizontal" % (phi*180/3.1416))

to produce:

The center of the beam ellipse is at (651, 491)
The ellipse diameter (closest to horizontal) is 334 pixels
The ellipse diameter (closest to   vertical) is 327 pixels
The ellipse is rotated 29° ccw from the horizontal

A visual report can be done with one function call:

lbs.beam_size_plot(beam)
plt.show()

produces something like

hene-report.png

or:

lbs.beam_size_plot(beam, r"Original Image $\lambda$=4µm beam", pixel_size = 12, units='µm')
plt.show()

produces something like

astigmatic-report.png

Non-gaussian beams work too:

# 12-bit pixel image stored as high-order bits in 16-bit values
tem02 = imageio.imread("TEM02_100mm.pgm") >> 4
lbs.beam_size_plot(tem02, title = r"TEM$_{02}$ at z=100mm", pixel_size=3.75)
plt.show()

produces

tem02.png

Determining M²

Determining M² for a laser beam is also straightforward. Just collect beam diameters from five beam locations within one Rayleigh distance of the focus and from five locations more than two Rayleigh distances:

lambda1=308e-9 # meters
z1_all=np.array([-200,-180,-160,-140,-120,-100,-80,-60,-40,-20,0,20,40,60,80,99,120,140,160,180,200])*1e-3
d1_all=2*np.array([416,384,366,311,279,245,216,176,151,120,101,93,102,120,147,177,217,256,291,316,348])*1e-6
lbs.M2_radius_plot(z1_all, d1_all, lambda1, strict=True)
plt.show()

produces

m2fit.png

Here is an analysis of a set of images that were insufficient for ISO 11146:

lambda0 = 632.8e-9 # meters
z10 = np.array([247,251,259,266,281,292])*1e-3 # meters
filenames = ["sb_%.0fmm_10.pgm" % (number*1e3) for number in z10]

# the 12-bit pixel images are stored in high-order bits in 16-bit values
tem10 = [imageio.imread(name)>>4 for name in filenames]

# remove top to eliminate artifact
for i in range(len(z10)):
    tem10[i] = tem10[i][200:,:]

# find beam in all the images and create arrays of beam diameters
options = {'pixel_size': 3.75, 'units': "µm", 'crop': [1400,1400], 'z':z10}
dy, dx= lbs.beam_size_montage(tem10, **options)  # dy and dx in microns
plt.show()

produces

sbmontage.png

Here is one way to plot the fit using the above diameters:

lbs.M2_diameter_plot(z10, dx*1e-6, lambda0, dy=dy*1e-6)
plt.show()

In the graph on the below right, the dashed line shows the expected divergence of a pure gaussian beam. Since real beams should diverge faster than this (not slower) there is some problem with the measurements (too few!). On the other hand, the M² value the semi-major axis 2.6±0.7 is consistent with the expected value of 3 for the TEM₁₀ mode.

sbfit.png

License

laserbeamsize is licensed under the terms of the MIT license.

Comments
  • Gaussian fit problem for asymmetric (astigmatic) beams

    Gaussian fit problem for asymmetric (astigmatic) beams

    Dear Scott,

    Thank you for this amazingly useful library. I have just discovered that Gaussian fit seems to be invalid for heavily astigmatic beams, and therefore, the function returns the incorrect beam diameters. Please refer to the image below. Picture1

    Is there any parameter to overcome the problem?

    UPD It seems (from the values) that dx and dy are just mixed up here

    Regards

    opened by Werefkin 7
  • Working with the highly astigmatic beams

    Working with the highly astigmatic beams

    Hello!

    I have a highly astigmatic laser diode. At some point after a lens I getting this with lbs.beam_size_montage():

    image image

    No problems with estimating the center of the beam, but axes are rotated by 45 degrees. Laser modes are aligned along x and y axes, no need to rotate them (almost).

    Is there any type of workaround for this problem?

    Here is the original image from Thorlabs DCC1545M: astigmatic_beam.zip

    P.S. Thanks a lot for this project !!!

    opened by arktrin 6
  • definition of fitting function in m2.py

    definition of fitting function in m2.py

    I like this module, as is makes analysis very easy. However, I wonder about the fitting for M2. Especially I refer to

    def _beam_fit_fn_(z, d0, z0, Theta): """Fitting function for d0, z0, and Theta.""" return d0**2 + (Theta*(z-z0))**2

    I understand the idea of fitting d(z)^2 = ... wwithout the sqrt. But if I change the input from d**2 to d and also the function from d0**2 + (Theta*(z-z0))**2 to np.sqrt(d0**2 + (Theta*(z-z0))**2), I get different results.

    Has anyone an idea, where this change comes from and how to get the proper output? Which of the two versions is right?

    opened by SReich-EMI 3
  • added BPP as output parameter

    added BPP as output parameter

    added the BPP=Theta*d0/4 to the calculations. For us this is always an important value, knowing that it is easily to calculate from M2. I don't know if I have found all poisitions, where to add the BPP, as I could only test one type of analysis with my data.

    opened by SReich-EMI 3
  • Beam diameter estimation

    Beam diameter estimation

    Hello!

    I'm getting wrong beam diameter estimation. Here is the result of lbs.beam_size_plot(beam, pixel_size=5.2, units='µm') :

    image

    Original image: image.zip

    opened by arktrin 1
  • rotated_rect_mask speedup

    rotated_rect_mask speedup

    I want to use this package on data coming at 10Hz but found that the current version was too slow for this. After some profiling, I found that rotated_rect_mask is slow as it rotates the whole image instead of just drawing a rotated rectangle. I wrote an alternative implementation that does that.

    I also added a test to make sure that the result is the same as for the normal implementation and changed depreciated np.float to float.

    opened by HTuennermann 1
  • Bump jinja2 from 2.11.2 to 2.11.3 in /docs

    Bump jinja2 from 2.11.2 to 2.11.3 in /docs

    Bumps jinja2 from 2.11.2 to 2.11.3.

    Release notes

    Sourced from jinja2's releases.

    2.11.3

    This contains a fix for a speed issue with the urlize filter. urlize is likely to be called on untrusted user input. For certain inputs some of the regular expressions used to parse the text could take a very long time due to backtracking. As part of the fix, the email matching became slightly stricter. The various speedups apply to urlize in general, not just the specific input cases.

    Changelog

    Sourced from jinja2's changelog.

    Version 2.11.3

    Released 2021-01-31

    • Improve the speed of the urlize filter by reducing regex backtracking. Email matching requires a word character at the start of the domain part, and only word characters in the TLD. :pr:1343
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • beam centers as float

    beam centers as float

    As my beams are not always perfeclty located at a pixel, I need the position as float and not int. Is there a reason for this restriction?

    for disc of round beam ISO says abs(2*xy)

    opened by SReich-EMI 0
  • New subtract_tilted_background

    New subtract_tilted_background

    I rewrote subtract_tilted_background so it now samples every point around a perimeter with width equal to the width of the corner boxes. I made a new function, perimeter_mask, to enable this. The new function works just as fast despite fitting many more points, and the result is now consistent from one run to the next because the randomness is removed. I updated the notebook to show the perimeter mask function.

    opened by scottbreitenstein 0
  • subtract_image / subtract_threshold implementation iso conform?

    subtract_image / subtract_threshold implementation iso conform?

    A colleague of mine brought up that the clipping to zero done in these functions is not mentioned in the iso standard. Therefore this wouldn't be completely iso conform. Instead, negative numbers should be used for the next steps. Would you be interested in changing this?

    opened by HTuennermann 1
Releases(v1.9.4)
  • v1.9.4(Mar 19, 2022)

    v1.9.4

    • allow beam angle to be specified during fitting
    • new notebook to illustrate constrained fits
    • improve docstrings and therefore api documentation
    • still better ellipse and rect outlines
    • start adding examples

    v1.9.3

    • use faster version of creating rotated rect mask
    • move tests to their own directory
    • avoid deprecated np.float
    • improve drawing of rect and ellipse outlines
    • improve some docstrings
    Source code(tar.gz)
    Source code(zip)
  • v1.9.3(Mar 15, 2022)

    v1.9.3

    • use faster version of creating rotated rect mask
    • move tests to their own directory
    • avoid deprecated np.float
    • improve drawing of rect and ellipse outlines
    • improve some docstrings

    v1.9.2

    • use both black and white dashed lines
    • fit to d and not d**2
    • add more dunders to init.py
    • fix residual calculation broken in v1.9.1
    Source code(tar.gz)
    Source code(zip)
  • v1.9.2(Mar 13, 2022)

    M² is found by fitting to a hyperbola. Heretofore the hyperbola was fit using d², laserbeamsize now uses d. Both methods give nearly identical results, but I believe fitting to d is more correct.

    v1.9.2

    • use both black and white dashed lines
    • fit to d and not d**2
    • add more dunders to init.py
    • fix residual calculation broken in v1.9.1

    v1.9.1

    • centralize version number to a single place

    v1.9.0

    • add beam_ellipticity()
    • add beam_parameter_product()
    • rotate x-tick labels when more than 10 ticks
    • removed deprecated use of np.matrix()
    • M2_report now includes BPP values
    • improve API docs
    • code linting
    Source code(tar.gz)
    Source code(zip)
  • v1.9.1(Mar 10, 2022)

    No features. This just reduces the number of places version numbers are used from 3 (setup.cfg, docs/conf.py, laserbeamsize/__init__.py) down to just the __init__.py file.

    v1.9.1

    • centralize version number to a single place

    v1.9.0

    • add beam_ellipticity()
    • add beam_parameter_product()
    • rotate x-tick labels when more than 10 ticks
    • removed deprecated use of np.matrix()
    • M2_report now includes BPP values
    • improve API docs
    • code linting
    Source code(tar.gz)
    Source code(zip)
  • v1.9.0(Mar 9, 2022)

    v1.9.0

    • add beam_ellipticity()
    • add beam_parameter_product()
    • rotate x-tick labels when more than 10 ticks
    • removed deprecated use of np.matrix()
    • M2_report now includes BPP values
    • improve API docs
    • code linting

    v1.8.0

    • handle rotated masks properly
    • fix readthedoc configuration
    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Dec 15, 2021)

    Internally, laserbeamsize masks the laser spot in the image. This involves rotating a binary mask which sometimes creates pixels that are not exactly 1. Guilhem noticed this and suggested a fix.

    Additionally, building of doc files on readthedocs.io has been made more robust.

    Source code(tar.gz)
    Source code(zip)
  • v1.7.3(Aug 7, 2021)

    v1.7.3

    • create pure python packaging
    • include wheel file
    • package as python3 only

    v1.7.2

    • allow non-integer beam centers
    • add badges to docs
    • use sphinx-book-theme for docs

    v1.7.1

    • explicit warning for non-monochrome images in beam_size()
    • improve help() messages

    v1.7.0

    • fix error in identifying major/minor axes in beam_size_plot()
    Source code(tar.gz)
    Source code(zip)
  • v1.7.2(Mar 22, 2021)

    v1.7.2

    • allow non-integer beam centers
    • add badges to docs
    • use sphinx-book-theme for docs

    v1.7.1

    • explicit warning for non-monochrome images in beam_size()
    • improve help() messages

    v1.7.0

    • fix error in identifying major/minor axes in beam_size_plot()
    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Jan 3, 2021)

  • v1.7.0(Nov 11, 2020)

  • v1.6.1(Sep 30, 2020)

    Minor release.

    • Fix the deprecation warning for register_cmap
    • a sphinx and pydocstyle warnings
    • use all points on background rect for fitting tilted background
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Aug 3, 2020)

    A number of small changes and

    • new function subtract_tilted_background()
    • M²=1 line added M2_radius_plot()
    • autoselect line color on images for visibility (still imperfect)
    • documentation tweaks
    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Jul 28, 2020)

    Support for ISO 11146 measurement of M² now. If you have an array of images, then analysis can be as simple as::

    import imageio
    import matplotlib.pyplot as plt
    import laserbeamsize as lbs
    
    images = [imageio.imread(name) for name in list_of_filenames]
    dy, dx= lbs.beam_size_montage(images, pixel_size=3.75)  # pixel_size in microns
    plt.show()
    lbs.M2_diameter_plot(z10, dx*1e-6, lambda0, dy=dy*1e-6)
    plt.show()
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Jun 7, 2020)

    New feature. visual_report() creates four subplots to show the beam analysis. Other updates include::

    • Add routines to plot values along semi axes
    • Fix error when calculating circular radius
    • Add missing scipy requirement
    • Improve README.rst with figure
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 3, 2020)

    Previously, laserbeamsize used the standard definitions for the first and second order moments of the WIgner distribution to calculate beam parameters.

    This version now also follows ISO 11146 for

    • integration areas
    • background using corners
    • background subtraction

    The overall result is that beam parameters extraction is much more robust.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(May 20, 2020)

Owner
Scott Prahl
Scott Prahl
Transfers a image file(.png) to an Excel file(.xlsx)

Transfers a image file(.png) to an Excel file(.xlsx)

Junu Kwon 7 Feb 11, 2022
Easy to use Python module to extract Exif metadata from digital image files.

Easy to use Python module to extract Exif metadata from digital image files.

ianaré sévi 719 Jan 5, 2023
Extract the temperature data of each wire from the thermal imager raw data.

Wire-Tempurature-Detection Extract the temperature data of each wire from the thermal imager raw data. The motivation of this computer vision project

JohanAckerman 1 Nov 3, 2021
The aim is to extract timeseries water level 2D information for any designed boundaries within the EasyGSH model domain

bct_file_generator_for_EasyGSH The aim is to extract timeseries water level 2D information for any designed boundaries within the EasyGSH model domain

Clayton Soares 1 Jul 8, 2022
Snowfall - helpful image handling utils - abstracts various file and opencv and pil features into result oriented functions

snowfall helpful image handling utils - abstracts various file and opencv and pil features into result oriented functions usage examples: from image_h

Less Wright 2 Jan 9, 2022
Validate arbitrary image uploads from incoming data urls while preserving file integrity but removing EXIF and unwanted artifacts and RCE exploit potential

Validate arbitrary base64-encoded image uploads as incoming data urls while preserving image integrity but removing EXIF and unwanted artifacts and mitigating RCE-exploit potential.

A3R0 1 Jan 10, 2022
An open source image editor which can manipulate an image in many ways!

Image Editor - An open source image editor which can manipulate an image in many ways! If you need any more modes in repo or I

TroJanzHEX 44 Nov 17, 2022
Image enhancing model for making a blurred image to be somehow clearer than before

This is a very small prject which helps in enhancing the images by taking a Input images. This project has many features like detcting the faces and enhaning the faces itself and also a feature which enhances the whole image

null 3 Dec 3, 2021
Easily turn large sets of image urls to an image dataset. Can download, resize and package 100M urls in 20h on one machine.

img2dataset Easily turn large sets of image urls to an image dataset. Can download, resize and package 100M urls in 20h on one machine. Also supports

Romain Beaumont 1.4k Jan 1, 2023
Nanosensor Image Processor (NanoImgPro), a python-based image analysis tool for dopamine nanosensors

NanoImgPro Nanosensor Image Processor (NanoImgPro), a python-based image analysis tool for dopamine nanosensors NanoImgPro.py contains the main class

null 1 Mar 2, 2022
A pure python implementation of the GIMP XCF image format. Use this to interact with GIMP image formats

Pure Python implementation of the GIMP image formats (.xcf projects as well as brushes, patterns, etc)

FHPyhtonUtils 8 Dec 30, 2022
Image-Viewer is a Windows image viewer based on Python 3.

Image-Viewer Hi! Image-Viewer is a Windows image viewer based on Python 3. Using You must download Image-Viewer.exe from the root of the repository. T

null 2 Apr 18, 2022
Image Reading, Metadata Conversion, and Image Writing for Microscopy Images in Python

AICSImageIO Image Reading, Metadata Conversion, and Image Writing for Microscopy Images in Pure Python Features Supports reading metadata and imaging

Allen Institute for Cell Science - Modeling 137 Dec 14, 2022
Seaborn-image is a Python image visualization library based on matplotlib and provides a high-level API to draw attractive and informative images quickly and effectively.

seaborn-image: image data visualization Description Seaborn-image is a Python image visualization library based on matplotlib and provides a high-leve

null 48 Jan 5, 2023
This app finds duplicate to near duplicate images by generating a hash value for each image stored with a specialized data structure called VP-Tree which makes searching an image on a dataset of 100Ks almost instantanious

Offline Reverse Image Search Overview This app finds duplicate to near duplicate images by generating a hash value for each image stored with a specia

null 53 Nov 15, 2022
Quickly 'anonymize' all people in an image. This script will put a black bar over all eye-pairs in an image

Face-Detacher Quickly 'anonymize' all people in an image. This script will put a black bar over all eye-pairs in an image This is a small python scrip

Don Cato 1 Oct 29, 2021
Fast Image Retrieval is an open source image retrieval framework

Fast Image Retrieval is an open source image retrieval framework release by Center of Image and Signal Processing Lab (CISiP Lab), Universiti Malaya. This framework implements most of the major binary hashing methods, together with both popular backbone networks and public datasets.

CISiP Lab 39 Nov 25, 2022
Fast Image Retrieval (FIRe) is an open source image retrieval project

Fast Image Retrieval (FIRe) is an open source image retrieval project release by Center of Image and Signal Processing Lab (CISiP Lab), Universiti Malaya. This project implements most of the major binary hashing methods to date, together with different popular backbone networks and public datasets.

CISiP Lab 39 Nov 25, 2022
A Python Script to convert Normal PNG Image to Apple iDOT PNG Image.

idot-png-encoder A Python Script to convert Normal PNG Image to Apple iDOT PNG Image (Multi-threaded Decoding PNG). Usage idotpngencoder.py -i <inputf

Lrdcq 2 Feb 17, 2022