1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
"""
Fabry-Perot Interference Pattern
================================
This example demonstrates image processing techniques for analyzing Fabry-Perot
interference patterns. It shows how to load experimental images, define regions
of interest, detect circular contours, and extract intensity profiles for
quantitative analysis of interference fringes.
Usage:
python fabry_perot_example.py
The script demonstrates optical analysis workflows commonly used in
interferometry, optical metrology, and precision measurements.
"""
# %%
# Importing necessary modules
# --------------------------------
# We start by importing all the required modules for image processing
# and visualization. To run this example, ensure you have all the required
# dependencies installed.
import sigima.enums
import sigima.objects
import sigima.proc.image
from sigima.tests import vistools
from sigima.tests.data import get_test_image
# %%
# Load Fabry-Perot test images
# --------------------------------
# We load two sample image of Fabry-Perot interference patterns.
# These imags is included in the Sigima test data. We will analyze the
# interference fringes present in these images.
# Load the first Fabry-Perot test image
img1 = get_test_image("fabry-perot1.jpg")
print("✓ Successfully loaded fabry-perot1.jpg")
print(f"Image dimensions: {img1.data.shape}")
print(f"Data type: {img1.data.dtype}")
print(f"Intensity range: {img1.data.min()} - {img1.data.max()}")
# Visualize the original interference pattern
vistools.view_images(img1, title="Fabry-Perot Interference Pattern #1")
# %%
# Define circular ROI for fringe analysis
# -------------------------------------------
# We define a circular region of interest (ROI) centered on the image
# to focus our analysis on the central interference fringes.
# Calculate image center
center_x, center_y = 601, 559
roi_radius = 460 # Radius to capture the first few interference rings
print(f"\n✓ Image center: ({center_x}, {center_y})")
print(f"ROI radius: {roi_radius} pixels")
print("This ROI focuses analysis on the central interference pattern")
# Create circular ROI coordinates:
roi_coords = [center_x, center_y, roi_radius]
# Apply circular ROI to the image
img1.roi = sigima.objects.create_image_roi("circle", roi_coords, indices=True)
print("✓ Circular ROI applied to image")
# Visualize image with ROI
vistools.view_images(img1, title="Fabry-Perot with Circular ROI")
# %%
# Configure contour detection for circular fringes
# ---------------------------------------------------
# We can now detect circular contours in the defined ROI. This will help us identify
# the interference rings. To perform this, the first step is to set up the contour
# detection parameter.
# Set up contour shape detection parameter for circles
contour_param = sigima.proc.image.ContourShapeParam()
contour_param.shape = sigima.enums.ContourShape.CIRCLE
contour_param.threshold = 0.5 # Threshold for fringe detection
print("\n✓ Contour detection configured:")
print(f"Shape: {contour_param.shape}")
print(f"Threshold: {contour_param.threshold}")
print("This will detect circular interference fringes")
# %%
# We can now perform the contour detection on the image using the
# configured parameters.
contour_results = sigima.proc.image.contour_shape(img1, contour_param)
print("\n✓ Contour detection completed for first image")
# %%
# We can now print the detected circular contours and their properties
print(f"Number of circular contours detected: {len(contour_results.coords)}")
contour_df = contour_results.to_dataframe()
print("\nDetected contours data frame:")
print(contour_df)
# %%
# Extract horizontal intensity profile
# ----------------------------------------
# We can extract an intensity profile along a horizontal line through the center
# of the image. This profile will show the intensity variations across the
# interference fringes. As before, we need to set up the line profile extraction
# parameter.
# Configure line profile extraction
profile_param = sigima.proc.image.LineProfileParam()
profile_param.direction = "horizontal"
profile_param.row = center_y # Extract profile through image center
print("\n✓ Horizontal profile configured:")
print(f"Direction: {profile_param.direction}")
print(f"Row: {profile_param.row} (image center)")
# Extract intensity profile
profile_signal1 = sigima.proc.image.line_profile(img1, profile_param)
print(f"✓ Profile extracted: {len(profile_signal1.y)} data points")
print(f"Intensity range: {profile_signal1.y.min():.1f} - {profile_signal1.y.max():.1f}")
# Visualize the intensity profile
vistools.view_curves(
[profile_signal1],
title="Horizontal Intensity Profile - Image 1",
xlabel="Position (pixels)",
ylabel="Intensity",
)
# %%
# Load the second Fabry-Perot image
# ----------------------------------------
# We want now to load the Analyze second Fabry-Perot image
try:
# Load second test image
img2 = get_test_image("fabry-perot2.jpg")
print("\n✓ Successfully loaded fabry-perot2.jpg")
print(f"Image dimensions: {img2.data.shape}")
# Copy ROI settings from first image
img2.metadata = img1.metadata # This includes the ROI information
# Visualize second image
vistools.view_images([img2], title="Fabry-Perot Interference Pattern #2")
except Exception as exc:
raise RuntimeError("Failed to load second Fabry-Perot test image.") from exc
# %%
# Contour detection on second image
# ----------------------------------------
# To perform the contour detection on the second image, we can
# reuse the same contour detection parameters defined earlier.
# This technique, applied to multiple images, allow to perform the same analysis on
# each of them and make comparisons easier.
# Apply the same contour detection to the second image
contour_results2 = sigima.proc.image.contour_shape(img2, contour_param)
print("✓ Contour detection completed for second image")
contour_df2 = contour_results2.to_dataframe()
print("\nDetected contours data frame (Image 2):")
print(contour_df2)
# %%
# Extract profile from second image and compare both profiles
# ----------------------------------------------------------------
# We can extract the horizontal intensity profile from the second image
# using the same profile extraction parameters defined earlier.
# Extract horizontal profile from second image
profile_signal2 = sigima.proc.image.line_profile(img2, profile_param)
print(f"\n✓ Profile extracted from second image: {len(profile_signal2.y)} points")
print(f"Intensity range: {profile_signal2.y.min():.1f} - {profile_signal2.y.max():.1f}")
# Compare profiles from both images
vistools.view_curves(
[profile_signal1, profile_signal2],
title="Intensity Profile Comparison",
xlabel="Position (pixels)",
ylabel="Intensity",
)
|