mask[img_]:=FillingTransform@Closing[#,2]&@EdgeDetect[#,2]&@ImageAdjust@BilateralFilter[#,3,.01,MaxIterations->10]&@img;(*mask function*)
incircle[poly_List?MatrixQ]:=With[{nodes=VoronoiMesh[poly]["Coordinates"],sd=SignedRegionDistance[Polygon[poly]]},With[{ord=First@Ordering[sd[nodes],1]},{nodes[[ord]],Abs@sd[nodes[[ord]]]}]];(*function to find an incircle of a grain*)

files=FileNames["*.tif",NotebookDirectory[]];(*image flie of a pollen grain*)
img=Import[files[[1]]]//ImageTrim[#,{{0,64},{1280,960}}]&(*import an image and remove the description*)

mas=mask[img];(*convert to binary*)
selected=SelectComponents[mas,#AdjacentBorderCount==0&&#Area>30000&];(*select pollen grains*)
trim=ComponentMeasurements[selected,"BoundingBox",All][[All,2]]//Sort;(*get triming ranges of of grains*)
trimimg=ImageTrim[img,trim[[1]]];(*trim a focal grain on the original image*)
b=ComponentMeasurements[SelectComponents[selected,"BoundingBox",{1}],"Image"][[1,2]];(*get an image of a focal grain*)
nonb=ImageSubtract[b,TopHatTransform[b,DiskMatrix[50]]];(*get an image of a focal pollen body, or a focal grain whose spines were removed*)
sub=ImageSubtract[b,nonb];(*get an image of spines*)
dt=DistanceTransform@sub;
marker=MaxDetect[dt,.7];(*make markers*)
segments=ImageData[sub,"Bit"]WatershedComponents[ColorNegate@dt,marker];(*separate overlapping spines*)
segsub1=Image[segments,"Binary"];(*get an image of spines after separation*)
segsub2=DeleteSmallComponents[#,50]&@ImageSubtract[b,#]&@DeleteSmallComponents[#,5000]&@ImageSubtract[b,segsub1];
(*repair invalid separation*)
dilnonb=Dilation[nonb,1];(*get an image of a dilated pollen body to find spine basal lines*)
mcsegsub=MorphologicalComponents@segsub2;
cm=Range@Max@mcsegsub;(*list of component ID*)
seg=Image/@((1-Unitize[#-mcsegsub])&/@cm);(*list of images of individual segments*)
r1=ImageMesh[#,Method->"Exact"]&/@seg;(*list of meshes of individual segments*)
r2=ImageMesh[#*dilnonb,Method->"Exact"]&/@seg;(*list of meshs of basal lines of individual segments*)
farthest=MapThread[Maximize[RegionDistance[#2,{x,y}],{x,y}∈#1]&,{r1,r2}];(*find tips*)
len=farthest[[All,1]];(*list of spine length*)
tip=farthest[[All,2,All,2]];(*list of coordinates of tips*)
base=MapThread[RegionNearest[#2,#1]&,{tip,r2}];(*list of coordinates of basal points*)
{cent,radius}=incircle@MeshCoordinates@ImageMesh@b;(*get the center and the radius of the incircle*)
spi=Transpose@{len,tip,base};(*a list of spines*)
orderedspi=Reverse@SortBy[spi,First];(*a list of spines, greater first*)

hlimg=HighlightImage[trimimg,{Opacity[1],AbsoluteThickness[1],White,RegionBoundary@ImageMesh@b,RegionBoundary@ImageMesh@nonb,Line/@Rest/@Drop[orderedspi,5],AbsoluteThickness[2],Red,Circle[cent,radius],Line/@Rest/@Take[orderedspi,5]}](*a highlighted image*)

{{"diameter","spine length 1","spine length 2","spine length 3","spine length 4","spine length 5"},Prepend[orderedspi[[;;5]][[;;,1]],radius*2]*50/504}//Grid(*diameter of the inscribed circle and 5 longest spine lengths (um)*)