I am working on a 3D volume of CT lung images, In order to detect nodules I need to fit an ellipsoid model for each suspected nodule, How can I make a code for that ??? Nodule is the suspected object to be a tumor, my algorithm needs to check every object, and approximate it to an ellipsoid, and from the ellipsoid parameters we calculate 8 features to build a classifier which detects whether it a nodule or not through training and testing data, so I need to fit such ellipsoid
here one slice of the volume CT lung image
here another slice of the same volume but it contains a nodule (the yellow circle there is a nodule) so I need my code to check every shape to determine whether it is a nodule or not
you may be interested in a recent plugin that we developed for the open-source software Icy http://icy.bioimageanalysis.org/
The plugin name is FitEllipsoid, it allows rapidly fitting an ellipsoid to the image contents by first clicking on a few points on the orthogonal view. A tutorial is available here: https://www.youtube.com/watch?v=MjotgTZi6RQ
Also note that we provide Matlab and Java source codes on GitHub (but I cannot provide them since it is my first appearance on the website).
As we do not have 3D dataset at disposal I start with 2D.
So first we need to select the lungs so we do not count any other objects then those inside. As this is gray scale we first need to binarize it somehow. I use my own
class picture
for DIP and this will heavily use mygrowthfill
so I strongly recommend to first read this:Where you will find all explanations you need for this. Now for your task I would:
turn RGBA to grayscale
<0,765>
I just compute intensity
i=R+G+B
as for 24 bit image the channels are 8 bit the result is up to3*255 = 765
. As the input image was compressed by JPEG there are distortions in color and also noise in the image so do not forget about that.crop out the white border
Just cast rays (scan lines) from middle of each outer line of the border towards middle and stop if non white-ish pixel hit. I treshold with
700
instead of765
to compensate the noise in image. Now you got the bounding box of usable image so crop out the rest.compute histogram
To compensate distortions in image smooth the histogram enough to remove all unwanted noise and gaps. Then find the local maximum from left and from right (red). This will be used for binarisation treshold (middle between them green) This is my final result:
binarise image
Just treshold image against the **green* intensity from histogram. So if
i0,i1
are the local maximum intensities from left and right in the histogram then treshold against(i0+i1)/2
. This is the result:remove everything except lungs
That is easy just fill the black from outside to some predefined background color. Then the same way all the white stuff neighboring background color. That will remove human surface, skeleton, organs and the CT machine leaving just the lungs. Now recolor the remaining black with some predefined Lungs color.
There should be no black color left and the remaining white are the possible nodules.
process all remaining white pixels
So just loop through the image and on first white pixel hit flood fill it with predefined nodule color or distinct object index for latter use. I also distinct the surface (aqua) and the inside (magenta). This is the result:
Now you can compute your features per nodule. If you code your custom
floodfill
for this then you can obtain from it directly things like:[pixels]
[pixels]
Which all can be used as your feature variables and also to help with fitting.
fit the found surface points
There are many methods for this but I would ease up it as much as I could to improve performance and accuracy. For example you can use centroid as your ellipsoid center. Then find the
min
andmax
distant points from it and use them as semi-axises (+/- some orthogonality corrections). And then just search around these initial values. For more info see:You will find examples of use in linked Q/As there.
[Notes]
All of the bullets are applicable in 3D. While constructing custom
floodfill
be careful with the recursion tail. Too much info will really fast overflow your stack and also slow things down considerably. Here small example of how I deal with it with few custom return parameters +growthfill
I used:And here C++ code I did the example images with: