diff --git a/extensions/chaeo/examples/transfer_labels_to_ilastik_object_classifier.py b/extensions/chaeo/examples/transfer_labels_to_ilastik_object_classifier.py index 3b96805354ac6b1949a443ffc7771dea2ac13391..c69b9b960bfdaf4b95b0afe16549e833ea36492c 100644 --- a/extensions/chaeo/examples/transfer_labels_to_ilastik_object_classifier.py +++ b/extensions/chaeo/examples/transfer_labels_to_ilastik_object_classifier.py @@ -33,6 +33,7 @@ def compare_object_maps(truth: GenericImageDataAccessor, inferred: GenericImageD if len(unique) == 1: # no object in frame dd['inferred_label'] = unique[0] elif len(unique) > 2: # multiple objects in frame, so mask out all but largest + print(f'Found multiple nonzero unique values in label {zi}: {unique}') ob_id = skimage.measure.label(inf_img) pr = skimage.measure.regionprops_table(ob_id, properties=['label', 'area']) mask = inf_img == pr['label'][pr['area'].argmax()] @@ -43,6 +44,7 @@ def compare_object_maps(truth: GenericImageDataAccessor, inferred: GenericImageD labels.append(dd) return pd.DataFrame(labels) + def infer_and_compare(classifier: PatchStackObjectClassifier, prefix, raw, mask, labels): result_acc, _ = classifier.infer(raw, mask) write_accessor_data_to_file(root / f'zstack_train_result.tif', result_acc) @@ -72,24 +74,25 @@ if __name__ == '__main__': MonoPatchStackFromFile(root / 'zstack_train_mask.tif'), MonoPatchStackFromFile(root / 'zstack_train_label.tif'), label_names, + allow_multiple_objects=False ) classifier = PatchStackObjectClassifier({'project_file': classifier_file}) - # verify self-consistency of training set - infer_and_compare( - classifier, - 'train', - MonoPatchStackFromFile(root / 'zstack_train_raw.tif'), - MonoPatchStackFromFile(root / 'zstack_train_mask.tif'), - MonoPatchStackFromFile(root / 'zstack_train_label.tif') - ) - - # run test set - infer_and_compare( - classifier, - 'test', - MonoPatchStackFromFile(root / 'zstack_test_raw.tif'), - MonoPatchStackFromFile(root / 'zstack_test_mask.tif'), - MonoPatchStackFromFile(root / 'zstack_test_label.tif'), - ) + # # verify self-consistency of training set + # infer_and_compare( + # classifier, + # 'train', + # MonoPatchStackFromFile(root / 'zstack_train_raw.tif'), + # MonoPatchStackFromFile(root / 'zstack_train_mask.tif'), + # MonoPatchStackFromFile(root / 'zstack_train_label.tif') + # ) + # + # # run test set + # infer_and_compare( + # classifier, + # 'test', + # MonoPatchStackFromFile(root / 'zstack_test_raw.tif'), + # MonoPatchStackFromFile(root / 'zstack_test_mask.tif'), + # MonoPatchStackFromFile(root / 'zstack_test_label.tif'), + # ) diff --git a/extensions/chaeo/models.py b/extensions/chaeo/models.py index d677d1f4191925e30a11f219957a14e786221afb..d488a699eb70c7ce17220c9dc2c3133ea6c0803a 100644 --- a/extensions/chaeo/models.py +++ b/extensions/chaeo/models.py @@ -3,6 +3,7 @@ import shutil import h5py import numpy as np +import skimage import vigra from extensions.chaeo.accessors import MonoPatchStack, MonoPatchStackFromFile @@ -54,6 +55,7 @@ def generate_ilastik_object_classifier( label_stack: MonoPatchStackFromFile, label_names: list, lane: int = 0, + allow_multiple_objects=True, ) -> Path: """ Starting with a template project file, transfer input data and labels to a new project file. @@ -64,6 +66,7 @@ def generate_ilastik_object_classifier( :param label_stack: stack of patches containing object labels :param label_names: list of label names :param lane: ilastik lane identifier + :param allow_multiple_objects: skip check for multiple objects in each mask image :return: path to generated object classifier """ assert mask_stack.shape == raw_stack.shape @@ -85,6 +88,12 @@ def generate_ilastik_object_classifier( assert unique[-1] < len(label_names) + 1, f'Label ID {unique[-1]} exceeds number of label names: {len(label_names)}' labels.append(unique[-1]) + if not allow_multiple_objects: + ob_id = skimage.measure.label(mask_stack.iat(ii)) + num_obj = len(np.unique(ob_id)) - 1 + if num_obj > 1: + raise MoreThanOneObjectError(f'Found {num_obj} connected objects in mask {ii}') + # write to new project file with h5py.File(new_ilp, 'r+') as h5: @@ -135,3 +144,8 @@ def generate_ilastik_object_classifier( return Path(new_ilp) +class Error(Exception): + pass + +class MoreThanOneObjectError(Error): + pass \ No newline at end of file