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
Command line utility for converting images to seamless tiles

img2texture Command line utility for converting images to seamless tiles. The resulting tiles can be used as textures in games, compositing and 3D mod

Artёm IG 24 Dec 26, 2022
missing-pixel-filler is a python package that, given images that may contain missing data regions (like satellite imagery with swath gaps), returns these images with the regions filled.

Missing Pixel Filler This is the official code repository for the Missing Pixel Filler by SpaceML. missing-pixel-filler is a python package that, give

SpaceML 11 Jul 19, 2022
Seeks to remove text from an image in a convincing way.

Text-Removal This is a Computer Vision project that seeks to successfully remove text from an image by covering the text areas in a convincing way. He

6 Nov 22, 2022
An python script to convert images to upscaled versions made out of one-colour emojis.

ABOUT This is an python script to convert png, jpg and gif(output isnt animated :( ) images to scaled versions made out of one-colour emojis. Please n

0 Oct 19, 2022
Digital image process Basic algorithm

These are some basic algorithms that I have implemented by my hands in the process of learning digital image processing, such as mean and median filtering, sharpening algorithms, interpolation scalin

JingYu 2 Nov 03, 2022
Make your master artistic punk avatar through machine learning world famous paintings

Master-art-punk Make your master artistic punk avatar through machine learning world famous paintings. 通过机器学习世界名画制作属于你的大师级艺术朋克头像 Nowadays, NFT is beco

蒋虎成 23 Jan 04, 2022
Advance Image Steganography

Chaya Advance Image Steganography Using LSB-LPS + AES-256-GCM + FLIF Right To Privacy! United Nations Declaration of Human Rights (UDHR) 1948, Article

XeroHack 113 Dec 02, 2022
Parking management project which generates barcode parking ticket with user-friendly Tkinter program GUI

Parking-management-system Parking management project which generates barcode parking ticket with user-friendly Tkinter program GUI How to run Download

1 Jul 03, 2022
Bot by image recognition simulating (random) human clicks

bbbot22 bot por reconhecimento de imagem simulando cliques humanos (aleatórios) inb4: sim, esse é basicamente o mesmo bot de 2021 porque a Globo não t

Yuri 2 Apr 05, 2022
vsketch is a Python generative art toolkit for plotters

Generative plotter art environment for Python

Antoine Beyeler 380 Dec 29, 2022
利用近邻法的弱点实现图片缩小后变成另一张图

这是我一个视频的配套代码。 视频是:利用近邻法的弱点实现图片缩小后变成另一张图 https://www.bilibili.com/video/BV1Lf4y1r7dZ 配套代码中,仅generate.py是核心文件,其余的图片神马的,都是赠品。 这个核心文件利用了近邻法缩放的弱点,可以将图a的像素按

偶尔有点小迷糊 182 Dec 19, 2022
A simple Streamlit Component to compare images in Streamlit apps. It integrates Knightlab's JuxtaposeJS

streamlit-image-juxtapose A simple Streamlit Component to compare images in Streamlit apps using Knightlab's JuxtaposeJS. The images are saved to the

Robin 30 Dec 31, 2022
ScreenTeX is a tool that grabs all text when taking a screenshot rather than getting an image.

The ScreenTeX project By: Seanpm2001 / ScreenTeX, Et; Al. Top README.md Read this article in a different language 🌐 List of languages Sorted by: A-Z

Sean P. Myrick V19.1.7.2 3 Oct 25, 2022
Remove Background from Image With Python

Install Library pypi $ pip3 install xremovebg

krypton 4 May 26, 2022
Png2Jpg tool will help you convert from png image format to jpg images format.

PNG 2 JPG All codes assume running from root directory. Please update the sys path at the beginning of the codes before running. Over View Png2Jpg too

Nguyễn Trường Lâu 2 Dec 27, 2021
A little Python tool to convert a TrueType (ttf/otf) font into a PNG for use in demos.

font2png A little Python tool to convert a TrueType (ttf/otf) font into a PNG for use in demos. To use from command line it expects python3 to be at /

Rich Elmes 3 Dec 22, 2021
Program designed to mass edit and watermark all photos in a directory

Photographer-All-In-One This is a program designed for photographers to mass edit or watermark photos (.jpg || .png) You can run this program from any

Brad Martin 2 Nov 23, 2021
This projects aim is to simulate flowers(Gerbera Daisy) phyllotaxis.

phyllotaxis This projects aim is to simulate flowers(Gerbera Daisy) phyllotaxis. Take a look at the arrangement of this flower's seeds, this project's

amirsalar 3 Dec 10, 2021
Convert any image into greyscale ASCII art.

Image-to-ASCII Convert any image into greyscale ASCII art.

Ben Smith 12 Jan 15, 2022
Bringing vtk.js into Dash and Python

Dash VTK Dash VTK lets you integrate the vtk.js visualization pipeline directly into your Dash app. It is powered by react-vtk-js. Docs Demo Explorer

Plotly 88 Nov 29, 2022