Before you fill out this form:
Did you review the FAQ?
Did you look through previous (open AND closed) issues posted on GH?
Now fill this form out completely
Describe the bug
I was trying to train a model on 3D data. To build the 2D training set I used cellpose/gui/make_train.py. My setup differs from the usual GUI workflow: the data is simulated and the ground truth is stored as TIFF label images rather than GUI-generated _seg.npy files. Working through this surfaced one clear bug and a few input-handling gaps.
Since make_train.py assumes the _seg.npy is a pickled dict as written by the GUI. My TIFF label masks can't be loaded directly, so I converted one image's masks and re-wrapped them as {"masks": array} in a pickled .npy to get them in. It would help if the script accepted a label image as tiff file directly.
With the masks loading, I found mask crops weren't being saved at all, only the image .tif. The cause is that the io.masks_flows_to_seg(...) call is nested inside the except ImportError block for the skimage import, so with skimage installed (the normal case) it never runs. Moving that call onto the success path fixes it, and both the image .tif and mask _seg.npy get written per crop (fix below).
I also wanted crop_size=256 rather than the default 512, because 256 is the input size during training. One of my axes is smaller than 256, and make_train.py doesn't pad in that case, so crops along that axis come out undersized. Padding (or at least a warning) would help here.
Finally, the effective training set came out smaller than I expected. Slice selection is purely random with no filter on how many masks a slice contains, the "drop slices with too few masks" step happens later during training instead. So many saved crops are empty, and after that drop the usable set is well below nimg_per_tif. Filtering on a minimum mask count at save time in make_train.py would be more intuitive.
**Another Question: deskewed lattice light-sheet data
After deskewing, my volume looks like parallelogram rather than a cuboid (screenshot attached), so slices in the YZ and ZX orientations contain large triangular background wedges. Is it a problem to include these wedge-containing slices in the training data?**
Please find attached 2D slices generated for training.
To Reproduce
Steps to reproduce the behavior:
Run log
img_crop = img[ly:ly + crop_size, lx:lx + crop_size].squeeze()
# Moved out of the `if masks0 is not None` block below.
#Otherwise only one of image/mask is saved, never both.
io.imsave(fname, img_crop)
if masks0 is not None:
masks_crop = masks[k][ly:ly + crop_size, lx:lx + crop_size].squeeze()
try:
from skimage.measure import label
masks_crop = label(masks_crop)
except ImportError:
print("skimage not found, cannot relabel masks. Run `pip install scikit-image` to relabel and save masks.")
# Moved out of the `except` block: previously the mask _seg.npy
# was only saved when skimage failed to import, so with skimage
# installed (normal case) mask crops were silently dropped.
flows = [np.zeros(masks_crop.shape, dtype="uint8"),
np.zeros((2, *masks_crop.shape), dtype="uint8"),
np.zeros(masks_crop.shape, dtype="float32")]
io.masks_flows_to_seg(img_crop, masks_crop, flows, fname)
Run logs
your logs here.
Screenshots

Before you fill out this form:
Did you review the FAQ?
Did you look through previous (open AND closed) issues posted on GH?
Now fill this form out completely
Describe the bug
I was trying to train a model on 3D data. To build the 2D training set I used cellpose/gui/make_train.py. My setup differs from the usual GUI workflow: the data is simulated and the ground truth is stored as TIFF label images rather than GUI-generated _seg.npy files. Working through this surfaced one clear bug and a few input-handling gaps.
Since make_train.py assumes the _seg.npy is a pickled dict as written by the GUI. My TIFF label masks can't be loaded directly, so I converted one image's masks and re-wrapped them as {"masks": array} in a pickled .npy to get them in. It would help if the script accepted a label image as tiff file directly.
With the masks loading, I found mask crops weren't being saved at all, only the image .tif. The cause is that the io.masks_flows_to_seg(...) call is nested inside the except ImportError block for the skimage import, so with skimage installed (the normal case) it never runs. Moving that call onto the success path fixes it, and both the image .tif and mask _seg.npy get written per crop (fix below).
I also wanted crop_size=256 rather than the default 512, because 256 is the input size during training. One of my axes is smaller than 256, and make_train.py doesn't pad in that case, so crops along that axis come out undersized. Padding (or at least a warning) would help here.
Finally, the effective training set came out smaller than I expected. Slice selection is purely random with no filter on how many masks a slice contains, the "drop slices with too few masks" step happens later during training instead. So many saved crops are empty, and after that drop the usable set is well below nimg_per_tif. Filtering on a minimum mask count at save time in make_train.py would be more intuitive.
**Another Question: deskewed lattice light-sheet data
After deskewing, my volume looks like parallelogram rather than a cuboid (screenshot attached), so slices in the YZ and ZX orientations contain large triangular background wedges. Is it a problem to include these wedge-containing slices in the training data?**
Please find attached 2D slices generated for training.
To Reproduce
Steps to reproduce the behavior:
Run log
Run logs
your logs here.Screenshots