Note
Go to the end to download the full example code.
Plane Wave Compounding#
This example demonstrates plane wave compounding of data from the PICMUS challenge (Plane-wave Imaging Challenge in Medical Ultrasound). PICMUS provides standardized datasets for evaluating plane wave imaging algorithms.
Example overview:
Load ultrasound data from UFF format files
Beamform data from multiple plane-wave transmits
Coherently compound the results
Visualize the results
Attribution:
Example inspired by vbeam examples (magnusdk/vbeam)
Dataset from PICMUS challenge (https://www.creatis.insa-lyon.fr/Challenge/IEEE_IUS_2016/)
Note
To run this example, we recommend installing mach with all optional dependencies:
pip install mach-beamform[all]
This ensures all dependencies for the examples are available.
Import Required Libraries#
Let’s start by importing the necessary libraries.
import hashlib
import matplotlib.pyplot as plt
import numpy as np
# Import mach modules
from mach import experimental
from mach._vis import db_zero
from mach.io.uff import create_beamforming_setup
from mach.io.utils import cached_download
try:
from pyuff_ustb import Uff
except ImportError as err:
raise ImportError("⚠️ pyuff_ustb is required for UFF data loading. Install with: pip install pyuff-ustb") from err
# Convenience constants
MM_PER_METER = 1000
Download PICMUS Challenge Dataset#
The PICMUS challenge contains multiple datasets with multi-angle plane-wave transmits. This example uses the resolution dataset, which features:
128-element linear array at 5.2 MHz center frequency
75 plane wave transmits at angles from -16° to +16°
Point targets and cysts for resolution and contrast assessment
print("📂 Downloading PICMUS challenge dataset...")
# Download the UFF data file (cached locally after first download)
# Source: https://unioslo.github.io/USTB/datasets.html
url = "https://zenodo.org/records/20261898/files/PICMUS_experiment_resolution_distortion.uff"
uff_path = cached_download(
url,
expected_size=145_518_524,
expected_hash="c93af0781daeebf771e53a42a629d4f311407410166ef2f1d227e9d2a1b8c641",
digest=hashlib.sha256,
filename="PICMUS_experiment_resolution_distortion.uff",
)
print(f"✓ Dataset downloaded to: {uff_path}")
print(f" File size: {uff_path.stat().st_size / 1e6:.1f} MB")
📂 Downloading PICMUS challenge dataset...
Downloading PICMUS_experiment_resolution_distortion.uff: 0%| | 0.00/146M [00:00<?, ?B/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 1%| | 1.05M/146M [00:01<03:44, 644kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 1%|▏ | 2.10M/146M [00:02<03:20, 714kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 2%|▏ | 3.15M/146M [00:04<03:05, 765kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 3%|▎ | 4.19M/146M [00:05<02:50, 827kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 4%|▎ | 5.24M/146M [00:06<02:41, 866kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 4%|▍ | 6.29M/146M [00:07<02:25, 960kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 5%|▌ | 7.34M/146M [00:08<02:24, 954kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 6%|▌ | 8.39M/146M [00:09<02:13, 1.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 6%|▋ | 9.44M/146M [00:10<02:16, 997kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 7%|▋ | 10.5M/146M [00:11<02:22, 946kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 8%|▊ | 11.5M/146M [00:12<02:21, 946kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 9%|▊ | 12.6M/146M [00:13<02:15, 978kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 9%|▉ | 13.6M/146M [00:14<02:16, 967kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 10%|█ | 14.7M/146M [00:16<02:20, 929kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 11%|█ | 15.7M/146M [00:16<02:09, 1.00MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 12%|█▏ | 16.8M/146M [00:17<02:06, 1.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 12%|█▏ | 17.8M/146M [00:18<02:04, 1.03MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 13%|█▎ | 18.9M/146M [00:20<02:10, 967kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 14%|█▎ | 19.9M/146M [00:21<02:06, 990kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 14%|█▍ | 21.0M/146M [00:22<01:58, 1.05MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 15%|█▌ | 22.0M/146M [00:22<01:53, 1.09MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 16%|█▌ | 23.1M/146M [00:24<01:57, 1.04MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 17%|█▋ | 24.1M/146M [00:25<01:56, 1.05MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 17%|█▋ | 25.2M/146M [00:26<02:03, 977kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 18%|█▊ | 26.2M/146M [00:27<02:03, 967kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 19%|█▊ | 27.3M/146M [00:28<01:58, 994kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 19%|█▉ | 28.3M/146M [00:29<01:47, 1.09MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 20%|██ | 29.4M/146M [00:29<01:39, 1.17MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 21%|██ | 30.4M/146M [00:30<01:41, 1.14MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 22%|██▏ | 31.5M/146M [00:31<01:34, 1.21MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 22%|██▏ | 32.5M/146M [00:32<01:37, 1.15MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 23%|██▎ | 33.6M/146M [00:33<01:43, 1.08MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 24%|██▍ | 34.6M/146M [00:34<01:43, 1.07MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 24%|██▍ | 35.7M/146M [00:35<01:38, 1.11MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 25%|██▌ | 36.7M/146M [00:36<01:43, 1.06MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 26%|██▌ | 37.7M/146M [00:37<01:41, 1.06MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 27%|██▋ | 38.8M/146M [00:38<01:36, 1.10MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 27%|██▋ | 39.8M/146M [00:39<01:48, 977kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 28%|██▊ | 40.9M/146M [00:40<01:44, 1.00MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 29%|██▉ | 41.9M/146M [00:41<01:41, 1.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 30%|██▉ | 43.0M/146M [00:42<01:39, 1.03MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 30%|███ | 44.0M/146M [00:43<01:30, 1.12MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 31%|███ | 45.1M/146M [00:44<01:34, 1.06MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 32%|███▏ | 46.1M/146M [00:45<01:37, 1.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 32%|███▏ | 47.2M/146M [00:46<01:31, 1.07MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 33%|███▎ | 48.2M/146M [00:47<01:34, 1.03MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 34%|███▍ | 49.3M/146M [00:48<01:32, 1.04MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 35%|███▍ | 50.3M/146M [00:49<01:31, 1.04MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 35%|███▌ | 51.4M/146M [00:50<01:29, 1.05MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 36%|███▌ | 52.4M/146M [00:51<01:28, 1.05MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 37%|███▋ | 53.5M/146M [00:52<01:23, 1.10MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 37%|███▋ | 54.5M/146M [00:53<01:17, 1.18MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 38%|███▊ | 55.6M/146M [00:54<01:18, 1.14MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 39%|███▉ | 56.6M/146M [00:55<01:16, 1.16MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 40%|███▉ | 57.7M/146M [00:56<01:21, 1.08MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 40%|████ | 58.7M/146M [00:57<01:21, 1.07MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 41%|████ | 59.8M/146M [00:58<01:26, 987kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 42%|████▏ | 60.8M/146M [00:59<01:26, 975kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 43%|████▎ | 61.9M/146M [01:00<01:23, 1.00MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 43%|████▎ | 62.9M/146M [01:01<01:21, 1.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 44%|████▍ | 64.0M/146M [01:02<01:24, 960kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 45%|████▍ | 65.0M/146M [01:03<01:21, 989kB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 45%|████▌ | 66.1M/146M [01:04<01:13, 1.09MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 46%|████▌ | 67.1M/146M [01:05<01:12, 1.08MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 47%|████▋ | 68.2M/146M [01:06<01:11, 1.08MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 48%|████▊ | 69.2M/146M [01:07<01:13, 1.03MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 48%|████▊ | 70.3M/146M [01:08<01:14, 1.00MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 49%|████▉ | 71.3M/146M [01:09<01:10, 1.06MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 50%|████▉ | 72.4M/146M [01:10<01:11, 1.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 50%|█████ | 73.4M/146M [01:11<01:02, 1.16MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 51%|█████ | 74.4M/146M [01:11<00:45, 1.57MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 52%|█████▏ | 75.5M/146M [01:11<00:33, 2.07MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 53%|█████▎ | 76.5M/146M [01:11<00:25, 2.69MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 54%|█████▍ | 78.6M/146M [01:11<00:15, 4.39MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 56%|█████▌ | 81.8M/146M [01:11<00:08, 7.47MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 59%|█████▉ | 86.0M/146M [01:12<00:04, 12.0MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 62%|██████▏ | 90.2M/146M [01:12<00:03, 16.1MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 64%|██████▍ | 93.3M/146M [01:12<00:02, 18.1MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 67%|██████▋ | 97.5M/146M [01:12<00:02, 21.5MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 69%|██████▉ | 101M/146M [01:13<00:03, 11.3MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 71%|███████ | 103M/146M [01:13<00:05, 8.39MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 72%|███████▏ | 105M/146M [01:13<00:05, 7.42MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 73%|███████▎ | 107M/146M [01:14<00:04, 8.51MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 76%|███████▌ | 110M/146M [01:14<00:03, 11.1MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 78%|███████▊ | 113M/146M [01:14<00:02, 13.6MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 81%|████████ | 117M/146M [01:14<00:01, 17.2MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 84%|████████▎ | 122M/146M [01:14<00:01, 20.6MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 86%|████████▋ | 126M/146M [01:14<00:01, 18.8MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 89%|████████▊ | 129M/146M [01:15<00:01, 11.0MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 90%|█████████ | 131M/146M [01:16<00:01, 7.58MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 92%|█████████▏| 133M/146M [01:16<00:01, 7.02MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 93%|█████████▎| 135M/146M [01:16<00:01, 6.63MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 94%|█████████▎| 136M/146M [01:17<00:01, 6.13MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 94%|█████████▍| 137M/146M [01:17<00:01, 5.69MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 95%|█████████▌| 138M/146M [01:17<00:01, 5.33MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 96%|█████████▌| 139M/146M [01:17<00:01, 5.80MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 97%|█████████▋| 141M/146M [01:17<00:00, 5.33MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 97%|█████████▋| 142M/146M [01:18<00:00, 5.00MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 98%|█████████▊| 143M/146M [01:18<00:00, 4.74MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 99%|█████████▊| 144M/146M [01:18<00:00, 4.63MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 99%|█████████▉| 145M/146M [01:18<00:00, 5.25MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 100%|██████████| 146M/146M [01:19<00:00, 4.65MB/s]
Downloading PICMUS_experiment_resolution_distortion.uff: 100%|██████████| 146M/146M [01:19<00:00, 1.84MB/s]
✓ Dataset downloaded to: /home/runner/.cache/mach/PICMUS_experiment_resolution_distortion.uff
File size: 145.5 MB
Load and Inspect PICMUS Data#
UFF files contain structured ultrasound data including channel data (RF signals), probe geometry, and scan parameters. Let’s examine the PICMUS dataset structure.
print("\n📋 Loading PICMUS data structure...")
# Open UFF file and extract components
uff_file = Uff(str(uff_path))
channel_data = uff_file.read("/channel_data")
scan = uff_file.read("/scan")
# Display challenge dataset information
print("\n📊 PICMUS Challenge Dataset:")
print(f" Plane wave transmits: {len(channel_data.sequence)}")
print(f" Array elements: {channel_data.probe.N}")
print(f" Samples per acquisition: {channel_data.data.shape[0]}")
print(f" Frames: {channel_data.data.shape[-1] if channel_data.data.ndim > 3 else 1}")
print(f" Sampling frequency: {channel_data.sampling_frequency / 1e6:.1f} MHz")
print(f" Center frequency: {channel_data.modulation_frequency / 1e6:.1f} MHz")
print(f" Speed of sound: {channel_data.sound_speed} m/s")
# Display plane wave transmit angles
angles_deg = [np.rad2deg(wave.source.azimuth) for wave in channel_data.sequence]
print(f" Plane wave angles: {min(angles_deg):.1f}° to {max(angles_deg):.1f}°")
print(f" Angular step: {np.diff(angles_deg)[0]:.1f}°")
# Display imaging region
print("\n🎯 Imaging Region:")
print(f" Lateral samples: {scan.x_axis.size}")
print(f" Depth samples: {scan.z_axis.size}")
print(f" Lateral extent: {scan.x_axis.min() * MM_PER_METER:.1f} to {scan.x_axis.max() * MM_PER_METER:.1f} mm")
print(f" Depth extent: {scan.z_axis.min() * MM_PER_METER:.1f} to {scan.z_axis.max() * MM_PER_METER:.1f} mm")
📋 Loading PICMUS data structure...
📊 PICMUS Challenge Dataset:
Plane wave transmits: 75
Array elements: 128
Samples per acquisition: 3328
Frames: 1
Sampling frequency: 20.8 MHz
Center frequency: 0.0 MHz
Speed of sound: 1540.0 m/s
Plane wave angles: -16.0° to 16.0°
Angular step: 0.4°
🎯 Imaging Region:
Lateral samples: 387
Depth samples: 609
Lateral extent: -19.1 to 19.0 mm
Depth extent: 5.0 to 49.9 mm
Extract metadata for mach#
print("\n🔄 Preparing data for beamforming...")
# Create beamforming setup for all plane wave angles
beamform_kwargs = create_beamforming_setup(
channel_data=channel_data,
scan=scan,
f_number=1.7,
)
print("📊 Beamforming setup:")
print(f" Sensor data shape: {beamform_kwargs['channel_data'].shape}")
print(" (transmits, elements, samples, frames)")
print(f" Output points: {beamform_kwargs['scan_coords_m'].shape[0]:,}")
print(f" Transmit arrivals shape: {beamform_kwargs['tx_wave_arrivals_s'].shape}")
print(f" F-number: {beamform_kwargs['f_number']}")
# Extract number of plane-wave transmits
n_transmits = beamform_kwargs["channel_data"].shape[0]
print(f" Beamforming {n_transmits} plane-wave transmits")
🔄 Preparing data for beamforming...
📊 Beamforming setup:
Sensor data shape: (75, 128, 3328, 1)
(transmits, elements, samples, frames)
Output points: 235,683
Transmit arrivals shape: (75, 235683)
F-number: 1.7
Beamforming 75 plane-wave transmits
Beamform and compound#
Now we beamform and compound the data:
Individual beamforming: Apply delay-and-sum beamforming to each plane-wave transmit
Coherent compounding: Sum the results to form the final image
Note: The mach.experimental API is subject to change.
print("\n🚀 Beamforming and compounding...")
result = experimental.beamform(**beamform_kwargs)
print("✓ Beamforming and compounding completed!")
print(f" Output shape: {result.shape} (points, frames)")
print(f" Data type: {result.dtype}")
print(f" Coherently compounded {n_transmits} plane-wave transmits")
🚀 Beamforming and compounding...
/home/runner/work/mach/mach/src/mach/kernel.py:251: UserWarning: array is not contiguous, rearranging will add latency
channel_data = try_contiguous(channel_data)
/home/runner/work/mach/mach/src/mach/kernel.py:274: UserWarning: Found 4 input array(s) on CPU. This will add latency due to CPU<->GPU memory transfers. For optimal performance with CUDA beamforming, move arrays to GPU using cupy, jax, or similar.
nb_beamform( # ty: ignore[no-matching-overload]
✓ Beamforming and compounding completed!
Output shape: (235683, 1) (points, frames)
Data type: complex64
Coherently compounded 75 plane-wave transmits
Reshape results#
The beamformed data needs to be reshaped to the 2D imaging grid.
print("\n📊 Processing compounded results...")
# Reshape from flattened points back to 2D imaging grid
grid_shape = (scan.x_axis.size, scan.z_axis.size)
beamformed_image = result.reshape(grid_shape)
# Extract magnitude for B-mode display (envelope detection)
bmode_image = np.abs(beamformed_image)
print("✓ Image processing complete")
print(f" Image shape: {bmode_image.shape} (lateral, depth)")
print(f" Dynamic range: {bmode_image.min():.2e} to {bmode_image.max():.2e}")
📊 Processing compounded results...
✓ Image processing complete
Image shape: (387, 609) (lateral, depth)
Dynamic range: 2.82e-03 to 8.00e+01
Visualize B-Mode#
print("\n📊 Visualizing B-mode...")
# Convert to logarithmic (dB) scale for display
bmode_db = db_zero(beamformed_image)
# Create high-quality visualization
fig, ax = plt.subplots(figsize=(8, 8), dpi=300)
# Set up coordinate system for proper display
extent = [
scan.x_axis.min() * MM_PER_METER,
scan.x_axis.max() * MM_PER_METER,
scan.z_axis.max() * MM_PER_METER,
scan.z_axis.min() * MM_PER_METER,
]
# Display the compounded image
im = ax.imshow(
bmode_db.T,
cmap="gray", # Clinical grayscale colormap
vmin=-40, # 40 dB dynamic range
vmax=0, # Normalized to maximum
extent=extent, # Physical coordinates in mm
aspect="equal", # Preserve spatial relationships
origin="upper", # Depth increases downward (standard)
interpolation="nearest", # Preserve sharp phantom features
)
# Add comprehensive labeling
ax.set_title(
f"PICMUS Challenge: Plane Wave Compounding\n"
f"Coherent Compounding of {n_transmits} Plane Wave Angles "
f"({min(angles_deg):.0f}° to {max(angles_deg):.0f}°)",
fontsize=14,
)
ax.set_xlabel("Lateral Distance [mm]", fontsize=12)
ax.set_ylabel("Depth [mm]", fontsize=12)
# Add colorbar with proper formatting
cbar = plt.colorbar(im, ax=ax, shrink=0.8)
cbar.set_label("Magnitude [dB]", fontsize=12)
cbar.ax.tick_params(labelsize=10)
# Add subtle grid for better readability
ax.grid(True, alpha=0.3, linestyle="--", linewidth=0.5)

📊 Visualizing B-mode...
Expected results#
The plane wave compounded image should clearly resolve:
Point targets: Sharp, well-defined spots for lateral/axial resolution measurement
Hyperechoic lesion: Bright circle to test for geometric distortion
Uniform speckle: Consistent background texture in tissue-mimicking regions
Total running time of the script: (1 minutes 22.063 seconds)