# Automated calculation of tree branches radius from thinned image

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:

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:

The code to produce the tree graph for now:

arbre2 = Import["https://i.stack.imgur.com/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];

• 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). Feb 25 '19 at 15:12
• 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 Feb 25 '19 at 15:22
• @Szabolcs thanks, but yes still tricky, because dimensions don't fit neither. Working on it... Feb 26 '19 at 7:29

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

arbre2 = Import["https://i.stack.imgur.com/unIQA.png"];
Thinning[Binarize[ColorReplace[arbre2, White -> Black, .055], 0]],
CornerNeighbors -> True];


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[
Nearest[VertexList[lgraph],
GraphEmbedding[morphograph] - .5][[All, 1]]]];
middle = (path = FindShortestPath[lgraph, vmap[#1], vmap[#2]];
First[Nearest[path, Mean[path]]]) & @@@ EdgeList[morphograph];


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

Point[GraphEmbedding[morphograph]], Hue[0.58, 0.73, 0.8],

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