This technical note will show you how to create a binary skeleton of a binary mask. This technique is useful for measuring the length of rod shaped, or long skinny, objects such as bacteria, mitochondria or nanoparticles. It can also be used to measure the number of branches in a networked structure.
Open Bacteria.tif from the Demo Images\Widefield\Bacteria folder
2. Apply a threshold to the image and generate a binary mask. Make sure the thresholds do not bleed into each other so as to select individual bacteria
3. Go to Process 🡪 Binary 🡪 Skeletonize
To measure the length of the lines set the measurements to measure Area and limit the measurements to the threshold. As the lines are a single pixel wide the area will represent the length.
2. Place a threshold on the image
3. To measure this time we will use a slightly different measurement module. This module will allow us to get values for each object in the image, as opposed to a global average we have been getting before. Go to Analyse 🡪 Analyse Particles
4. Configure the resulting dialog box as follow. This will measure the thresholded objects and display two results tables. One that shows the values for each object and one that shows summary information about all the objects.
The same principals above can be applied to connected objects or networks. The resulting distance measurement is not specific to a single object but instead is a value representing the complete network.
2. Use the Default setting to place and apply a threshold to the mitochondria (Image 🡪 Adjust 🡪 Threshold)
3. Convert the binary mask to a skeleton using the Process 🡪 Binary 🡪 Skeletonise command
Go to Analyze 🡪 Set Measurements… and configure the settings to measure Area only
2. Use the Analyze 🡪 Analyze Particles command to get a summary of the lengths of the mitochondria
The average size shows the average length of all the mitochondria in the image. If information on individual cells is required an additional whole cell stain would need to be included.
Having a color overview image of result can help show the result more clearly. In this example one will create a color overview image that shows the short and longer mitochondria in different colors.
1, Select the final skeletonize mask and use the Analyze Particles command again, but this time set a size range of 0-1 and set Show: to Masks, there is no need to have any of the boxes ticked
2. The resulting mask needs to be inverted to give white objects on a black background. This mask represents all the short objects (below the completely arbitrary cut off of 1um)
3. To generate a mask for the longer (>1um) objects follow the steps above but this time set the size cut off to 1.000001-Infinity. The high precision number removes the chance of double counting an object as both small and large (i.e. there is no overlap between the two measurements)
4. Both masks will have the same name (Mask of Mito – Control.tif). To make the next step easier it is a good idea to rename the images to different names (e.g. Short and Long)
5. Merge the two resulting masks
6. Repeat all the previous steps for Mito – Treatment.tip and compare the results.
Once you have a skeleton binary details about the branching and skeleton parameters can be measured.
Select the original skeleton that was generated previously.
2. Go to Analyze🡪Skeleton🡪Analyze Skeleton (2D/3D)
3. In the Analyze Skeleton dialog that comes up you can configure the options for the analysis. For this example tick Show detailed info and Display labelled skeletons and press OK
4. The skeleton binary will be analysed. An image showing the branching points, ends and branches will be generated (called Tagged skeleton) the other image will show the labels of each skeleton as an intensity binary image, each skeleton will have its own discrete intensity. In this example there are many individual skeletons and so many colours are shown in the tagged skeletons image
The tables list the summary information about each skeleton in the Results table. The Branch information table shows the details for each individual branch, the skeleton ID column lists which skeleton the given branches information is from.
The tagged skeleton image is colour coded to show the different parts of the skeleton identified. The branches are shown in orange, the branch points in magenta and the ends shown in blue.
Data is quite often collected in 3 dimensions, for example blood vessel networks. The branching analysis used previously can also be applied to three dimensional data.
The following analysis steps can become quite compute intensive, to save time if needed some premade files are also provided in the demo images folder. Within Demo Images\Confocal\Blood Vessels are pretrained labkit models and generated binaries (both raw and cleaned up) if required.
While data maybe collected in 3D it is possible to get enough information out using 2D analysis methods like those used previously. This will work well on low density, low volume size image sets. It will lead to a large number of false results in more complex data sets as objects that maybe separated in 3D space are joined together.
2. Maximum Intensity Z project the stack by selecting the Stk button and choosing Z Project…
3. To more accurately threshold the signal a filter needs to be applied to even out the intensities a bit. Go to Process 🡪 Filters 🡪 Median… and apply a Median filter with a Radius of 2.0 pixels
4. Set a threshold on the filtered image that selects the signal. Some small chunks may also be selected but these will be filtered out in the following steps.
5. Apply the threshold to produce a binary image of the vessel stain
6. To remove the smaller chunks we will use a Binary Open filter followed by Binary Reconstruction. First make a duplicate of the binary image (right click and choose Duplicate… or go to Edit 🡪 Duplicate).
Select the duplicated image and go to Process 🡪 Binary 🡪 Options
In the Binary Options window set Iterations to 2 and Do: to Open and press ok.
7. You now have two binary images, one original and one with all the small chunks removed (but with other parts removed too). To produce a cleaned up binary image of the vessels we will use binary reconstruction.
Go to Plugins 🡪 Morphology 🡪 Binary Reconstruct
8. In the Binary Reconstruction dialog set mask: as the original binary image and seed:as the open filtered binary and press OK
The resulting reconstructed binary image should have all the small chunks removed but leave the major vessel structures.
Create a skeleton of the binary image by going to Process 🡪 Binary 🡪 Skeletonize
The skeleton binary can now be analysed as previously by going to Analyze 🡪 Skeleton 🡪 Analyze Skeleton (2D/3D)
3. As shown previously the resulting data is presented via different coloured images and data tables.
4. To easily see the details of a single branch network select the labelled skeletons image and set a threshold to the skeleton ID you with to analyse (in this case ID 1).
5. Apply the threshold to get a binary skeleton of just the selected network. Because the labelled image is 32bit you will get a message from the thresholder, just select Convert to Mask.
6. Apply the threshold to get a binary skeleton of just the selected network. Because the labelled image is 32bit you will get a message from the thresholder, just select Convert to Mask.
Ideally if data is collected in 3D it should be analysed in 3D as well. The following steps will show how to generate binary images in 3D through filtering and the use of machine learning (using labkit).
2. To enable easier selection of positive signal a median filter is used as previously. Except this time as the data is 3D a filter capable of filtering all all 3 dimensions needs to be used. While a 2D filter could be applied to each slice of the stack it will not take into account any depth dimension and can result in strange results.
Go to Process 🡪 Filters 🡪 Median 3D…
3. In the resulting 3D Median dialog set the X, Y and Z radius to 1 and press OK
In this example all the filter dimensions are kept the same. It is possible to set different values for each however, though the X and the Y values should usually stay the same size. The Z dimension can be changed if required to accommodate the dimensions of the data, for example if the Z dimension was under or over sampled relative to the XY dimensions.
4. The stack will now be filtered in all three dimensions but if you try to set a threshold on it as before you will notice that some areas are not easily thresholded due to high background or low signal
5. To be able to successfully create a binary image of the vessels a different approach needs to be taken. Machine learning offers a more adaptable and robust way of this. Fiji offers
Reset the threshold and go to Plugins 🡪 Labkit 🡪 Open Current Image with Labkit
The mouse wheel will move though the different slices of the stack. Holding the left button and moving the mouse will change the slice orientation which can get rather confusing. To rest back to default view go to View 🡪 Reset View
For this example we will be separating the image into the vessel signal and the background but it is possible to segment multiple signals if required by adding more labels.
6. Select the Pencil from the icons at the top of the window. You can set the brush size to a large value to make markup a bit easier.
Select background and draw on part of the image background. Repeat for the foreground label. You can draw labels on multiple areas and layers of the image if needed.
7. Once you have marked out some areas (it doesn’t have to be a lot – you can always add more later) press the Labkit Pixel Classification button under the Segmentation section.
8. The default classification will be loaded and is fine for most applications.
Pressing the Gear icon will pen up the classifier settings and let you change filters and enable GPU acceleration if needed
NOTE: GPU acceleration requires the CLIJ2 plugin to be installed and will only work with nVidia GPUs currently.
9. Once some markup for each label has been done press the Play/Triangle button next to the classifier. Labkit will now segment the image based on the pixel values you have selected for each label. This can take some time depending on the size of the data set and the speed of your computer system.
GPU acceleration can help speed this up but may not always work stably (or at all) on some systems.
You can scroll through the layers using the mouse button so see if the segmentation is adequate. If it isn’t you can mark up more for each label or remove erroneous markup using the eraser tool.
10. Once you are happy with the segmentation you can save the classifier for later use by going to Segmentation 🡪 Save Classifier…in the Labkit window.
NOTE: An example classifier file is available in Demo Images\Confocal\Blood Vessels\Labkit Classifier if required and can be applied buy going to Segmentation 🡪 Open Classifier
11. To create a binary image of the segmentation go to Segmentation 🡪 Show Segmentation Result in ImageJ in the Labkit window
12. The binary image created by labkit has a few issues that need to be corrected before being able to progress with the analysis. Firstly, the image is created as virtual image (note the (V) after the image name). This means the image is only holding in RAM the current slice and not all the slices, this will affect future steps in the analysis.
To fix this create a duplicate of the whole image stack
13. The second thing to fix is to reapply the original pixel calibration as it was lost when going through labkit as well. The values used here were copied out of the original file, you will need to do the same thing with your own data.
Select the duplicated stack and go to Image 🡪 Properties… and adjust the calibration values as shown
14. Lastly the stack needs to be converted back to binary so it can be filtered and analysed. Select the stack and apply a threshold of 1 to 255 to convert the stack back to binary
NOTE: Make sure Calculate threshold for each image is unticked for this to work properly
15. To check if any filtering needs to be applied to remove any small chunks that will give false data the easiest thing to do it to visualise the binary in 3D
Go to Plugins 🡪 3D Viewer
Leave the settings at default (if you have the compute power you can change the Resampling factor to 1 to preserve detail)
16. Looking at the data in 3D shows that there are small chunks that may need to be filtered out
Alternatively, you could create a maximum projection of the binary stack. This will show the discrete blobs that don’t overlap in the z space but those that are on a different plane to a major vessel
17. To remove the small chunks we need to apply a size filter, because this is a 3D data set the filer needs to be a volume filter rather than the usual area filter. To do this we will use the 3D Objects Counter which is essentially the 3D version of the analyse particles command
Select the binary stack and go to Analyze 🡪 3D Objects Counter
18. In the 3D Objects Counter dialog set a minimum size filer of 3000 to remove the smaller chunks (this was determined through trial and error for this specific dataset). Make sure under Maps to Show that Objects is ticked, this will create a new image with only the remaining objects in it (like show masks in analyse particles)
NOTE: Processing for this step can take some time. Progress will be shown in the log window. If needed there are versions of the pre and post filtered stacks in Demo Images\Confocal\Blood Vessels\Binaries
19. A new window will be created with the filtered results in it. Each object will be given a unique intensity/colour. By default, the scale of the image maybe a bit off making it hard ot see some of the objects.
20. To more easily visualise the result adjust the Brightness and Contrast (just pressing the Auto button will be fine).
21. To check in 3D first make a duplicate of the stack and then convert the duplicate to RGB
22. You can then view the RGB stack in the 3D Viewer as before. Note that all the small bits of debris are now gone.
23. As the object counter output image is various intensities we need to convert it to binary for the final analysis. Select the objects output (the non-RGB one) and apply a threshold of 1 to 255 we did before.
24. Make a duplicate of the final binary to be used in a later analysis
Now that we have a final, clean 3D binary stack we can analyse the branching etc as we did previously with 2D data.
To generate a skeleton of the binary data go to Plugins 🡪 Skeleton 🡪 Skeletonize (2D/3D)
2. The result will be a binary skeleton like before. It may look a bit odd per slice but a maximum projection should show a network.
3. To analyse the skeleton go to Analyse 🡪 Skeleton 🡪 Analyse Skeleton (2d/3D) as before. The same module works for both 2D and 3D data. The result outputs are the same as the 2D data but are now measured in true 3D
4. Creating maximum intensity projections of the outputs gives a good overview of the results
NOTE: The labelled skeleton image may go strange. Just reapply the Fire LUT and adjust brightness and contrast.
5. As the outputs of the analysis are 3D stacks they can be visualised in the 3D Viewer. Due to them being drawn from only 1 pixel wide lines they do not visualise that well however.
6. This can be fixed by dilating the lines out using a dilation filter. As the data is 3D this needs to be a 3D binary filter.
Go to Plugins 🡪 MorphoLibJ 🡪 Filtering 🡪 Morphological Filters (3D)
7. In the Morphological Filters (3D) dialog window set the Operation to Dilation, the Element Shape to Ball and the XYZ radii to 2
8. The resulting stacks will have thicker lines that will be easier to visualise in 3D
Earlier in the 2D analysis it was shown how to extract an induvial branch network and measure its specific details. The same is possible for 3D data.
Select the binary stack you duplicated earlier to use later on and run the 3D Objects Counter on it to generate the objects map
2. Select the network of interest by setting the threshold that corresponds to its ID, in this example number 2, and applying the theshold
3. You should now have a binary stack representing just the selected branch(es) of interest.
4. This selected branch can then be analysed as before to get the branching info from skeletonization. It can also be used to measure intensity values.
Go to Analyze 🡪 3D OC Options
5. Within the 3D-OC Set Measurements window you can set a range of measurements that can be set.
To measure the intensity of the original vessels image make sure Redirect to: is net to Vessels.tif
6. To measure select the binary image and then go to Analyze 🡪 3D Objects Counter. Make sure nothing is ticked under Maps to show and that Statistics and Summary are ticked under Results tables to show
7. The data will be outputted into a summary and a detailed results table, this will include the intensity information about the channel the analysis was redirected to.