Last active
January 31, 2026 11:47
-
-
Save alexlib/936272975d55e5baad2f33cdd667c2ee to your computer and use it in GitHub Desktop.
marimo notebook showing PIV image enhancement filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import marimo | |
| __generated_with = "0.19.6" | |
| app = marimo.App(width="medium", auto_download=["ipynb"]) | |
| with app.setup: | |
| import cv2 | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import marimo as mo | |
| @app.function | |
| def enhance_piv_particles(image, kernel_size=5, cap_percentile=95): | |
| # 1. White Top-Hat Transform | |
| # kernel_size should be slightly larger than your typical particle diameter (e.g., 3, 5, or 7) | |
| kernel = cv2.getStructuringElement( | |
| cv2.MORPH_ELLIPSE, (kernel_size, kernel_size) | |
| ) | |
| tophat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, kernel) | |
| # 2. Local Contrast Enhancement (Optional but helpful for low intensity) | |
| # CLAHE spreads the intensity of small objects without global blooming | |
| clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) | |
| enhanced = clahe.apply(tophat) | |
| # 3. Intensity Capping | |
| # Prevents large bright regions from dominating the cross-correlation signal | |
| cap_value = np.percentile(enhanced, cap_percentile) | |
| enhanced_capped = np.clip(enhanced, 0, cap_value).astype(np.uint8) | |
| # Normalize back to 0-255 for visibility/processing | |
| final = cv2.normalize(enhanced_capped, None, 0, 255, cv2.NORM_MINMAX) | |
| return final | |
| @app.cell | |
| def _(): | |
| # Usage: | |
| img = cv2.imread("/home/user/Desktop/C001H001S0001000001.png", 0) | |
| processed_img = enhance_piv_particles(img, kernel_size=5) | |
| return img, processed_img | |
| @app.cell | |
| def _(img, processed_img): | |
| _fig, (_ax_orig, _ax_proc) = plt.subplots(1, 2, figsize=(10, 5)) | |
| _ax_orig.imshow(img, cmap="gray") | |
| _ax_orig.set_title("Original Image") | |
| _ax_orig.axis("off") | |
| _ax_proc.imshow(processed_img, cmap="gray") | |
| _ax_proc.set_title("Processed Image") | |
| _ax_proc.axis("off") | |
| plt.tight_layout() | |
| mo.mpl.interactive(_fig) | |
| return | |
| if __name__ == "__main__": | |
| app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment