I am progressing in the branching problem described here. After having extracted my tree structure and done a lot of manipulations on it (very interesting, but not described here), I would like to associate a radius (and/or weight) to each edge of the tree, based on the initial radius R of the branches as seen on this image:

enter image description here

Having that value (approximated), I would be able to calculate some interesting properties of my tree, to which I don't have access for now.

I have thought about an algorithm that would progress along each edge and stop at the middle, then taking the normal and following it up to the border, which would give me the answer... but this method is not really elegant in my opinion.

The base image:

enter image description here

The code to produce the tree graph for now:

arbre2 = Import["https://i.sstatic.net/unIQA.png"];
mask = FillingTransform[Thinning[Binarize[ColorReplace[arbre2, White -> Black, .055], 0]], CornerNeighbors -> True];
skel2 = Thinning[mask]; HighlightImage[skel2, MorphologicalBranchPoints[skel2], 1];
morphograph2 = MorphologicalGraph[skel2, VertexSize -> 2, VertexLabels -> Automatic];
newtreegraph2 = TreeGraph[DeleteCases[EdgeList[morphograph2], x_ \[UndirectedEdge] x_], VertexCoordinates -> GraphEmbedding[morphograph2], VertexSize -> 5, VertexLabels -> Automatic];
  • $\begingroup$ You could create something similar to a SkeletonTransform by taking the DistanceTransform and multiplying it by the skeleton obtained by different means (Thinning). You could remove the branch points to break the skeleton into components corresponding to the graph edges, then try to process those. Matching them up with the actual Graph edges is probably still not easy (so this is just an idea-comment—it's far from a full answer). $\endgroup$
    – Szabolcs
    Feb 25, 2019 at 15:12
  • 1
    $\begingroup$ Something like this: compsIm = skel2 - Dilation[MorphologicalBranchPoints[skel2], 1]; thicknesses = ComponentMeasurements[{compsIm DistanceTransform[mask], comps = MorphologicalComponents[compsIm]}, "Mean"]; We have some sort of thickness measurement for each graph edge now. But we do not have the exact mapping from these to the edges in the Graph expression $\endgroup$
    – Szabolcs
    Feb 25, 2019 at 15:22
  • $\begingroup$ @Szabolcs thanks, but yes still tricky, because dimensions don't fit neither. Working on it... $\endgroup$
    – Valacar
    Feb 26, 2019 at 7:29

1 Answer 1


This is more like op's non-elegant method idea, but might be a starting point:

arbre2 = Import["https://i.sstatic.net/unIQA.png"];    
mask = FillingTransform[
   Thinning[Binarize[ColorReplace[arbre2, White -> Black, .055], 0]], 
   CornerNeighbors -> True];
skel2 = Thinning[mask];

Convert it to the image mesh and then graph to get middle point of edges:

imesh = ImageMesh[skel2, Method -> "Exact"];    
lgraph = Graph[
   UndirectedEdge @@@ 
    Rationalize[MeshPrimitives[imesh, 1]][[All, 1]]];

Compute middle points of edges:

morphograph = MorphologicalGraph[skel2];    
vmap = Association[
   Thread[VertexList[morphograph] -> 
       GraphEmbedding[morphograph] - .5][[All, 1]]]];    
middle = (path = FindShortestPath[lgraph, vmap[#1], vmap[#2]]; 
     First[Nearest[path, Mean[path]]]) & @@@ EdgeList[morphograph];

Compute radii:

rad = RegionDistance[ImageMesh[ColorNegate[mask]], middle];

Show[{ImageMultiply[mask, ColorNegate[skel2]], 
  Graphics[{Green, PointSize[.004], Point[middle], Red, 
    Point[GraphEmbedding[morphograph]], Hue[0.58, 0.73`, 0.8], 
    Table[Text[rad[[i]], middle[[i]], {-1.2, 0}], {i, 

enter image description here

With graphs:

Graph[morphograph, EdgeLabels -> Thread[EdgeList[morphograph] -> rad]]

enter image description here

  • $\begingroup$ That's it I reckon! Thanks for that $\endgroup$
    – Valacar
    Feb 28, 2019 at 9:09

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.