Allen Cell Discussion Forum

Playground 9: Segmentation workflows for lamin b1 (interphase)


I have installed aics-segmentation and the machine learning section too, everything works great so far.
I have a question regarding the segmentation for laminb1 workflow :
It is design to work with 3d images (z stacks) but can I adapt it to work 2D (single z) since this is how we take the images for analysis in the lab.

So can I adapt /modify the workflow to work on single plane images ?

Next once I get the segmentation sorted , is it possible to get multiple single ROIs rather than a massive unique one ?

The idea is to use the single ROI (nucleus by nucleus) and apply it back on the original image to get the intensities of each lamin signal per nucleus .
In other words, I am looking to segment, make a mask and measure the intensities in the lamin channel for each single nucleus .

That way I can get all laminb1 intensities per nucleus per image.

Is that feasible, if so can you help me to design such a workflow ?
Thanks a lot!

Hi Antho,

Thanks for your interest. My comments regarding your questins are below:

1- So can I adapt /modify the workflow to work on single plane images ?

This is possible. Most of the wrapper functions were implemented for easy-to-use on 3D images. But, the underlying functions under the hook are actually dimension agnostic. For example, this step aics-segmentation/ at main · AllenCell/aics-segmentation · GitHub actually applies on a single 2D z-slice. For laminb1_interphase workflow, I think it is totally possible to convert it to be applicable on 2D images without much effort. If you find more troubles on this, I would be happy to work up a 2D version of the lamin b1 interphase workflow as an example.

2- is it possible to get multiple single ROIs rather than a massive unique one?

Yes, this is very possible. I used this a lot in my own work. If you look at this step: aics-segmentation/ at main · AllenCell/aics-segmentation · GitHub

it actually returns all nuclei as individual objects. In other words, each nucleus is represented by one unique integer number. We just convert them to binary in the last step to generate the binary segmentation.

I hope the info above is helpful. Let me know if you still have troubles, you may post an example image, and I would be more than happy to provide some code snippets to help you achieve your segmentation and analysis goal.


Hi Jianxu,

Thank you for you response,
I will try on my own but if you could provide an example of the 2d version that would help a lot, I am a newbie in python, so I will be able to make it work surely but that might take a long time of trials and errors … ! with an example I will learn a lot faster (an accelerate my python skills and learning curve) :).

I can certainly update a multi channel file (TIF or else) so you can help to design an easy workflow working on jupyter.
How can I upload a file ? can you send me a link ?

Thank you for your help, this is much appreciated :slight_smile:

Hi Jianxu,

I can run the jutyper book but I am stuck at some point :

viewer_bw = view(segmentation_quick_view(seg))
segmentation is empty

I tried to play with the parameters and cut off but I can’t make it change …

So could I send you an image and if you can run the pipeline, just to check if this is feasible ?

Additionally, does the Allen institute provide some training for this type of analysis , I really lack some skills but I am eager to learn, is there any trainings, summer school or something could be arranged ?
That will be ideal :slight_smile: .

Please let me know, I would like to get the laminb1 2d to work as a starting point .

Hi Jianxu,

I made it work finally up to the end, but still I don’t know how to save as multiple ROI … (dots notebook)…

Is it an argument in the in the output directly ? (I was not able to do it …:frowning: )

Or somethin else ?
Could you give me the missing code, please ?

Thanks a lot !


seg = seg.astype(np.uint8)
seg[seg > 0] = 255


if output_type == "default":
    # the default final output, simply save it to the output path
    save_segmentation(seg, False, Path(output_path), fn)
elif output_type == "customize":
    # the hook for passing in a customized output function
    # use "out_img_list" and "out_name_list" in your hook to
    # customize your output functions
    output_func(out_img_list, out_name_list, Path(output_path), fn)
elif output_type == "array":
    return seg
elif output_type == "array_with_contour":
    return (seg, generate_segmentation_contour(seg))
    raise NotImplementedError("invalid output type: {output_type}")

Glad to see you work up to the end!! To get individual objects, there are multiple ways to do, depending on the segmentation functions you use.

Case 1: in dot notebook

If you just use dot filter, or what we call spot filter, the output in binary, say seg. Then, you can do the following:

from skimage.measure import label
seg_label = label(seg, connectivity=1)

This will give you each individual objects, each labeled with a unique integer value。

Case 2: use shell notebook

there is a watershed step: bw_filled = watershed(struct_img, seed.astype(int), watershed_line=True)>0. You just need to remove the >0 at the end. The results will be for each individual objects.


Hi Jianxu,

Thanks a lot !
I thought it was something to do the connectivity but I was not sure, now I will try :slight_smile: .
What about the function “array with contour” in the output ? how can I play with the arguments ?
such as : output_type == “array_with_contour”: ?

THe last thing would be to get the measurements from the segmentation onto the actual image (or from the nucleus segmentation ) and save all parameters (intensities, sizes, area , perimeter ect…) such as in the “bridging_the_gap_between_binary_image_and_analysis.ipynb” .

I guess it is possible to combine both analysis in one go (nucleus : ROI ) then DOTs (or shell ) (per ROI: nucleus) in a batch mode ?

Thanks a lot;

Hi Jianxu,

Now I encounter another issue :
THe core algorythm for lamin works but then the Part 3: apply watershed to get the shell , is odd.
After the watershed the results is pretty bad, it detects almost nothing from the previous step.

I tried to play with the Hole sizes but it gives me almost the same results : very low detection and very far away from the previous step …

Do you know where the problem could come from ?
Should I post some image examples ?

Thanks a lot,

Hello @antho,

Sorry for the late reply. There are a couple of things you could check:

  1. can you post a screen shot of what your seed image looks like? and what your struct_img looks like?
  2. the seed image supposes to be almost “black” (i.e., almost all zero value) except a few pixels as seeds. Can you try something like np.nonzero(seed>0)? the output value will be the number of objects (i.e., number of seeds).


Hi Jianxu,
No problem,
Here are some print screens along the workflow to give you an idea, I may have made some mistakes so if you could have a look that would be great !
Also, I cannot get the multiple labels at the end only the single ROI with all detections … could you indicate when or how to add the
from skimage.measure import label
seg_label = label(seg, connectivity=1)"

to save as multiple labels ?
Let me know if you need anything else :slight_smile: .

Thanks a lot,

Dear @antho ,

After a closer look at your image, personally, I don’t think tweaking the current 3D lamin b1 workflow will eventually solve this specific 2d image segmentation problem. Personally, I would recommend you to take a look at 2D StarDist, which might be more suitable for this task: GitHub - stardist/stardist: StarDist - Object Detection with Star-convex Shapes


Hi Jianxu,

Thank you for the info, I use stardist too but to segment the nucleus mainly…
I am not sure if I can use stardist to detect the shell for laminb1 since it will be a plain detection but not the outline…
Unless there is a way to tweak it to save the contour rather than the plain detection ?


After segmentinng the solid shapes (nuclei in this case), you can get the contours like this:

Great thanks a lot !

This is not related to laminB1 , but is it possible to use stardist 2D / 3D and the curator from AICS ?
That could be ideal in order to improve the training greatly by correcting the mistakes (if any by stardist) and retrain the model with accurate segmentation.

Is it compatible / possible ?