HoloPy can work with any kind of image data, but we use it for digital holograms, so our tutorials will focus mostly on hologram data.
Loading and viewing a hologram¶
We include a couple of example holograms with HoloPy. Lets start by loading and viewing one of them
import holopy as hp from holopy.core.io import get_example_data_path imagepath = get_example_data_path('image01.jpg') raw_holo = hp.load_image(imagepath, spacing = 0.0851) hp.show(raw_holo)
The first few lines just specify where to look for an image. The most important line actually loads the image so that you can work with it:
raw_holo = hp.load_image(imagepath, spacing = 0.0851)
HoloPy can import any image format that can be handled by Pillow.
The spacing argument tells holopy about the scale of your image. Here, we had
previously measured that each pixel is a square with side length 0.0851 microns.
In general, you should specify
spacing as the distance between adjacent pixel centres.
You can also load an image without specifying a spacing value if you just want
to look at it, but most holopy calculations will give erroneous results on such an image.
The final line simply displays the loaded image on your screen
with the built-in HoloPy
show() function. If you don’t see anything, you may need to set your matplotlib backend.
Refer to Using HoloPy for instructions.
Correcting Noisy Images¶
The raw hologram has some non-uniform illumination and an artifact in the
upper right hand corner from dust somewhere in the optics. These types of
things can be removed if you are able to take a background image with the same optical setup but
without the object of interest. Dividing the raw hologram by the background using
can usually improve the image a lot.
from holopy.core.process import bg_correct bgpath = get_example_data_path('bg01.jpg') bg = hp.load_image(bgpath, spacing = 0.0851) holo = bg_correct(raw_holo, bg) hp.show(holo)
Often, it is beneficial to record multiple background images. In this case,
we want an average image to pass into
bg_correct() as our background.
bgpath = get_example_data_path(['bg01.jpg', 'bg02.jpg', 'bg03.jpg']) bg = hp.core.io.load_average(bgpath, refimg = raw_holo) holo = bg_correct(raw_holo, bg) hp.show(holo)
Here, we have used
load_average() to construct an average of the three background
images specified in
refimg argument allows us to specify a reference
image that is used to provide spacing and other metadata to the new, averaged image.
If you are worried about stray light in your optical train, you should
also capture a dark-field image of your sample, recorded with no laser illumination.
A dark-field image is specified as an optional third argument to
dfpath = get_example_data_path('df01.jpg') df = hp.load_image(dfpath, spacing = 0.0851) holo = bg_correct(raw_holo, bg, df) hp.show(holo)
Some convenient tools for manipulating image data are included within HoloPy. See the HoloPy Tools page for details.
Telling HoloPy about your Experimental Setup¶
Recorded holograms are a product of the specific experimental setup that produced them. The image only makes sense when considered with information about the experimental conditions in mind. When you load an image, you have the option to specify some of this information in the form of metadata that is associated with the image. In fact, we already saw an example of this when we specified image spacing earlier. The sample in our image was immersed in water, which has a refractive index of 1.33. It was illuminated by a red laser with wavelength of 660 nm and polarization in the x-direction. We can tell HoloPy all of this information when loading the image:
raw_holo = hp.load_image(imagepath, spacing=0.0851, medium_index=1.33, illum_wavelen=0.660, illum_polarization=(1,0))
You can then view these metadata values as attributes of
raw_holo, as in
However, you must use a special function
update_metadata() to edit them. If we forgot to
specify metadata when loading the image, we can use
update_metadata() to add it later:
holo = hp.core.update_metadata(holo, medium_index=1.33, illum_wavelen=0.660, illum_polarization=(1,0))
Spacing and wavelength must both be written in the same units - microns in the example above. Holopy has no built-in length scale and requires only that you be consistent. For example, we could have specified both parameters in terms of nanometers or meters instead.
HoloPy images are stored as xarray DataArray objects. xarray is a powerful tool that makes it easy to keep track of metadata and extra image dimensions, distinguishing between a time slice and a volume slice, for example. While you do not need any knowledge of xarray to use HoloPy, some familiarity will make certain tasks easier. This is especially true if you want to directly manipulate data before or after applying HoloPy’s built-in functions.
Saving and Reloading Holograms¶
Once you have background-divided a hologram and associated it with metadata, you might want to save it so that you can skip those steps next time you are working with the same image:
saves your processed image to a compact HDF5 file. In fact, you can use
on any holopy object. To reload your same hologram with metadata you would write:
holo = hp.load('outfilename')
If you would like to save your hologram to an image format for easy visualization, use:
Additional options of
save_image() allow you to control how image intensity is scaled.
Images saved as .tif (the default) will still contain metadata, which will be retrieved if
you reload with
load(), but not
The holograms above make use of several default assumptions. When you load an image like:
raw_holo = hp.load_image(imagepath, spacing = 0.0851)
you are making HoloPy assume a square array of evenly spaced grid points. If your pixels are not square, you can provide pixel spacing values in each direction:
raw_holo = hp.load_image(imagepath, spacing = (0.0851, 0.0426))
Most displays will default to displaying square pixels but if you
use HoloPy’s built-in
show() function to display the image, your hologram will display
with pixels of the correct aspect ratio.