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 |
|---|---|
|
The true EF (and |
|
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 = 1invideo_lv_area.csv, while the ED frame should fall on a peak of theSizecurve.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_sizeinPredictEF.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;
.npyframes 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.