Speckle Reduction on Ultrasound Images — Classical vs DnCNN
Background
My PhD research focused on freehand B-mode ultrasound image quality —
speckle noise, spatial correlation modeling, and super-resolution restoration.
That was 8 years ago. This project is me rebuilding that work with modern tools.
Starting point: a clean benchmark on the
BUSI dataset
(780 breast ultrasound images — benign, malignant, normal).
The Problem with Standard Benchmarks
Most speckle reduction papers evaluate on the full image — background included.
But in clinical practice, what matters is image quality within the lesion.
So I added ROI-based evaluation using the segmentation masks provided in BUSI.
For images with multiple lesions, masks were combined via union.
def evaluate_with_roi(original, denoised, mask=None):
global_psnr = psnr(original, denoised, data_range=1.0)
global_ssim = ssim(original, denoised, data_range=1.0)
if mask is not None and mask.max() > 0:
# ROI bounding box
rows = np.any(mask > 0, axis=1)
cols = np.any(mask > 0, axis=0)
rmin, rmax = np.where(rows)[0][[0, -1]]
cmin, cmax = np.where(cols)[0][[0, -1]]
if (rmax - rmin) >= 7 and (cmax - cmin) >= 7:
roi_orig = original[rmin:rmax, cmin:cmax]
roi_den = denoised[rmin:rmax, cmin:cmax]
roi_ssim = ssim(roi_orig, roi_den, data_range=1.0)
Methods
- Noise model: Additive Gaussian (σ=0.05) as speckle proxy (Note: not physically accurate — Nakagami or correlated models are more realistic. PSF-aware correlated noise model is next on the list.)
- Non-Local Means (NLM)
- Median Filter
- Gaussian Filter
- DnCNN — 17-layer residual CNN, trained from scratch on BUSI
DnCNN — A Note on Training
Training was not straightforward.
Initial run with lr=1e-3 plateaued immediately after epoch 2:
Epoch [ 2/30] — Loss: 0.002472
Epoch [10/30] — Loss: 0.002408
Epoch [20/30] — Loss: 0.002383
Epoch [30/30] — Loss: 0.002363 ← barely moved
Dropping to lr=1e-4 with step decay fixed it:
Epoch [ 5/50] — Loss: 0.001487
Epoch [20/50] — Loss: 0.001023
Epoch [50/50] — Loss: 0.000899
This is worth noting: DnCNN is sensitive to initialization and learning rate.
Results varied across runs (PSNR range ~31.2–31.7 dB). Single-run DL benchmarks
should be interpreted with some caution.
Results (780 images)
| Method | PSNR Global | SSIM Global | PSNR ROI | SSIM ROI |
|---|---|---|---|---|
| Noisy | 26.25 | 0.649 | 26.34 | 0.681 |
| Median Filter | 29.71 | 0.810 | 29.32 | 0.811 |
| Gaussian Filter | 29.99 | 0.836 | 29.76 | 0.833 |
| NLM | 31.47 | 0.827 | 31.52 | 0.842 |
| DnCNN | 31.24 | 0.847 | 31.17 | 0.860 |
Key Findings
1. NLM vs DnCNN — it depends on the metric.
NLM wins on PSNR, DnCNN wins on SSIM. SSIM captures structural similarity
better than pixel-level fidelity — arguably more relevant for diagnostic imaging.
2. Global metrics can mislead.
Median filter looks decent globally (29.71 dB) but drops in ROI (29.32 dB) —
edge blurring at lesion boundaries. A paper reporting only global metrics
would miss this.
3. Dataset-scale evaluation matters.
On individual images, NLM sometimes outperforms DnCNN. The pattern only
stabilizes at dataset scale. Single-image comparisons in this field are unreliable.
What's Next
- Super-resolution: Real-ESRGAN / SwinIR fine-tuned on ultrasound
- Realistic noise model: PSF-aware correlated speckle from phantom data (I actually collected this data during my PhD — time to revisit it)
- Thyroid nodule segmentation with SAM
Code on GitHub 👇

Top comments (0)