7. Results & Troubleshooting

The quickest check is to eyeball the overlays and area curves. For a quantitative one, lean on the EchoNet-Dynamic dataset: it ships a ground-truth EF for all 10,030 videos, plus the traced LV boundary on the systole and diastole frames of one cardiac cycle.

7.1. Validating against the EchoNet-Dynamic ground truth

That ground truth lives in two files, both are on the Downloads page.

File

Ground truth it provides

FileList.csv

The true EF (and ESV/EDV) for every video

VolumeTracings.csv

The traced LV boundary on the end-diastole (ED) and end-systole (ES) frames of one cardiac cycle

7.1.1. EF β€” compare against FileList.csv

Run PredictEF.py on the videos (ideally the test split, so the model is scored on clips it never trained on), then join your EFprediction.csv to FileList.csv on FileName and measure the error:

import pandas as pd
pred = pd.read_csv(r"...\EchoNet-dynamic\demo_output\EFprediction.csv")
gt   = pd.read_csv(r"...\EchoNet-dynamic\FileList.csv")
pred["FileName"] = pred["FileName"].str.replace(".avi", "", regex=False)
m = pred.merge(gt[["FileName", "EF"]], on="FileName")
print(f"EF MAE = {(m['Predicted_EF(%)'] - m['EF']).abs().mean():.2f}%")

For reference, the original EchoNet-Dynamic model reaches a mean absolute error of about 4 % on the test split; landing near that means your pipeline is sound.

7.1.2. Segmentation β€” compare against VolumeTracings.csv

VolumeTracings.csv labels exactly two frames per video β€” the ED frame (largest LV) and the ES frame (smallest LV). The first row of each frame is the LV long axis; the rest are chords (X1, Y1)–(X2, Y2) spanning the cavity that together trace the ventricle outline. That gives you two checks:

  • Systole timing β€” the ES frame should coincide with a frame your script flags ComputerSystole = 1 in video_lv_area.csv, while the ED frame should fall on a peak of the Size curve.

  • Boundary overlap β€” turn the tracing into a filled mask and score it against your predicted mask on the same frame with the Dice coefficient:

import numpy as np
from skimage.draw import polygon

def tracing_to_mask(rows, size=112):
    # rows: VolumeTracings rows for ONE (FileName, Frame); skip row 0 (long axis)
    chords = rows.iloc[1:]
    x = np.concatenate([chords.X1.values, chords.X2.values[::-1]])
    y = np.concatenate([chords.Y1.values, chords.Y2.values[::-1]])
    rr, cc = polygon(y, x, (size, size))
    m = np.zeros((size, size), np.uint8); m[rr, cc] = 1
    return m

def dice(a, b):
    return 2 * np.logical_and(a, b).sum() / (a.sum() + b.sum())

On the ED and ES frames, a Dice above ~0.9 means your segmentation closely follows the human tracing.

Coordinates are already at 112 Γ— 112

The released EchoNet-Dynamic videos and the VolumeTracings.csv coordinates are both at 112 Γ— 112 β€” the same scale the scripts use β€” so the masks line up directly. If you switch to full-resolution clips, rescale the X/Y values (or your mask) to a common size first.


7.2. Common errors

Error: state_dict size mismatch when loading weights

You loaded the wrong checkpoint. PredictSegmentation.py needs the DeepLabV3-ResNet50 weights; PredictEF.py needs the R(2+1)D-18 weights. See the table in Installation.

β€œNo .avi or .mp4 videos found”

The input folder path is wrong, empty, or the videos sit in a sub-folder. Both scripts only scan the top level of the folder. Put videos directly inside it.

ModuleNotFoundError: No module named β€˜echonet’

Only PredictSegmentation.py needs echonet (to save annotated videos). Install it from the EchoNet-Dynamic repo (see Installation), or run only PredictEF.py if you do not need segmentation videos.

CUDA out of memory

  • EF: lower block_size in PredictEF.py (e.g. 10 β†’ 4).

  • Segmentation: lower the video batch size (batch_size = 20) in Module B.

  • Or force CPU: set device_name='cpu' / let the script detect no GPU.

Emoji / encoding errors in the Windows console

PredictSegmentation.py already calls sys.stdout.reconfigure(encoding="utf-8"). If you still see UnicodeEncodeError, run from Windows Terminal / PowerShell rather than the legacy cmd.exe, or set set PYTHONUTF8=1 before running.

Predictions look wrong but no error is raised

Most often a domain/normalisation mismatch: the inputs differ from EchoNet-Dynamic data (different scanner, view, contrast). The default MEAN/STD assume EchoNet-like grayscale A4C clips β€” recompute them for your own dataset, see Normalization Statistics.


7.3. Performance tips

  • A CUDA GPU is roughly 10–50Γ— faster than CPU for these models.

  • For EF, larger block_size = fewer kernel launches = faster (until you hit a memory limit).

  • For segmentation, the video module is the slow part; .npy frames are quick.


7.4. Reproducibility checklist

  • Record which checkpoint (r2plus1d_18_32_2_pretrained.pt / deeplabv3_resnet50_random.pt) produced each result.

  • Keep the input folder unchanged, or copy it alongside the output.

  • Note the script version / date (the segmentation header is dated 5/5/2026).

  • Archive the output CSVs together with the annotated media.