2
$\begingroup$

I am trying to segment a binary image into three parts, head, body, and tail. The binary image is a stack of tiff files of a moving fruit fly larvae. I was able to do this initially by removing points within a certain distance of the centroid:

enter image description here

However, this broke down when the larvae's head moved too close to the centroid, because the head points would then be removed:

enter image description here

I have been looking for creative solutions to this problem. Trying to fit it to a curved ellipsoid and get the vertice points that make up the tail and the head. However, I have not been very successful! I was curious if anyone had any insight into this problem or a suggestion for a creative solution?

Here are the raw binary images:

1)

enter image description here

2)

enter image description here

$\endgroup$
4
  • $\begingroup$ Hm. MorphologicalGraph does a fairly good job to identify the ends of the larvae (try Show[img, MorphologicalGraph[img]]). But it is far from perfect... $\endgroup$ Commented Sep 27, 2020 at 19:00
  • $\begingroup$ Thank you for the suggestion! I will play around with that. I tried a SkeletonTransform into a Binarization but the branching points were interfering. I tried a prune but that was truncating the furthest endpoints. $\endgroup$
    – BioKenLyon
    Commented Sep 27, 2020 at 19:06
  • $\begingroup$ Yes, SkeletonTransform was also one of my first guesses. And indeed, there is too much artificial branching going on... =/ $\endgroup$ Commented Sep 27, 2020 at 19:12
  • $\begingroup$ Using the MorphologicalGraph function I have managed to get the vertex coordinates in each frame. I am running into the issue now that there are more than 2 vertex coordinates. I am thinking to narrow this down to use the EuclideanDistance function to find the points that have the greatest distance between them and take that but does not appear that this solution will work for every case. $\endgroup$
    – BioKenLyon
    Commented Sep 27, 2020 at 22:02

1 Answer 1

2
$\begingroup$

The best answer I could manage is to use the following:

  1. First I got the vertices using MorphologicalGraph function:
     AbsoluteOptions[MorphologicalGraph[myBinMovie[[frame]]], VertexCoordinates]

enter image description here

  1. Sometimes, this would give me more than two vertices so I used an If function to find the furthest two vertices based on the EuclideanDistance function:
      myMaxDisVerts =Table[If[Length@myVertices[[frame, 1, 2]] == 2, 
      myVertices[[frame, 1, 2]],
      myTempMaxDis = 
       Max /@ Table[
         EuclideanDistance[myVertices[[frame, 1, 2, i]], 
          myVertices[[frame, 1, 2, j]]], {i, 1, 
          Length@myVertices[[frame, 1, 2]], 1}, {j, 1, 
          Length@myVertices[[frame, 1, 2]], 1}];
      myVertices[[frame, 1, 2, 
        Flatten@Position[myTempMaxDis, Max[myTempMaxDis]]]]], {frame, 1, 
      Length@myVertices, 1}]
  1. Using these points, I then took the closest 70 pixels that were a value of 1 from the Binary image using the ReplacePixelValue function:
    Table[ReplacePixelValue[
       ConstantImage[0, ImageDimensions@myMaskedMovie[[1]]], 
       Flatten[Table[(NearestTo[myMaxDisVerts[[frame, j]], 
             70(*Determines size of head and tail masks*)][
            test6[[frame]]]), {j, 1, Length@myMaxDisVerts[[frame]], 1}], 
         1] -> 1], {frame, 1, Length@myMaxDisVerts, 1}];

enter image description here

  1. I then took the centroid of these Binary images that made up the "head" and "tail" of the larvae using ComponentMeasurements and found their closest neighbors through each frame:
    myNearestHTPosCentroid = 
      ComponentMeasurements[#, "Centroid"] & /@ myNearestHTPos;
  1. Plotted the centroid and the head and tail points joined points with the original movie:
    myCentroidJoinedLarvaColMovie = 
      Table[Show[myMaskedMovie[[frame]], 
        ListLinePlot[{myCentroidPos[[
           frame]], {myHeadAndTailTracks[[1, frame, 
            2, {2, 3}]]}, {myHeadAndTailTracks[[2, frame, 2, {2, 3}]]}}, 
         PlotMarkers -> {myOrangeCircMark, myCyanCircMark, 
           myRedCircMark}], 
        ListPlot[{Flatten[myCentroidPos[[1 ;; frame]], 1], 
          myHeadAndTailTracks[[1, 1 ;; frame, 2, {2, 3}]], 
          myHeadAndTailTracks[[2, 1 ;; frame, 2, {2, 3}]]}, 
         PlotStyle -> {Lighter[Orange, 0.3], Darker[Cyan, 0.005], Red}, 
         Joined -> True]], {frame, 1, Length@myHeadAndTailTracks[[1]], 
        1}];

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.