# Is it possible to extract vertices and lines from this image?

I have the following image Is it possible to extract the lines from this image and then convert those lines to a graph representation? I tried using ImagesLines[] with Binarize[] but got very bad results.

• Try option ImageLines[...,Method-> "Segmented"->True]  Dec 30, 2021 at 17:37
• @UlrichNeumann I tried that but the lines didn't line up with the image, there were either too many lines or many lines were missing. Dec 30, 2021 at 17:44
• MorphologicalGraph@Thinning@Invert@i? Dec 30, 2021 at 17:47
• Ah yes,ColorNegate, not Invert Dec 30, 2021 at 18:27
• Do you have the image in its original scale, in a non-lossy (non-JPEG) format? Dec 30, 2021 at 21:59

g = IndexGraph[
MorphologicalGraph[
Thinning[ColorNegate[Binarize[pic]], Method -> "MedialAxis"]]] Then you can merge vertices that are close each other:

pts = GraphEmbedding[g];

Median[EuclideanDistance[pts[[#[]]], pts[[#[]]]] & /@
EdgeList[g]]


13.0384

f = Nearest[Thread[pts -> Range[Length[pts]]]]

merge = Select[f[#, {All, 10}] & /@ pts, Length[#] > 1 &];


You can check the grouping of vertices:

HighlightGraph[g, merge, VertexSize -> 1] and final graph:

final = Fold[VertexContract, g, merge] First, use the method of deleting the branch points developed in this answer:

img = Import["https://i.stack.imgur.com/aLhGVm.png"];

imb = Thinning[ColorNegate@Binarize@img];

edges = DeleteSmallComponents@MorphologicalTransform[imb,
If[#[[2, 2]] == 1 && Total[#, 2] == 3, 1, 0] &];

edgesLabeled = MorphologicalComponents[edges];
edgesLabeled // Colorize Second, extract the branch points (nodes) and separate them from the edges by making their labels sufficiently large, as I did here:

nodes = imb - edges;
threshold = 10^Ceiling[Log10[Max[edgesLabeled] + 1]];
nodesLabeled = MorphologicalComponents[nodes] * threshold;
nodesLabeled // Colorize edgesPlusNodesLabeled = edgesLabeled + nodesLabeled;
edgesPlusNodesLabeled // Colorize Now it is easy to reconstruct the graph:

neighbors =
ComponentMeasurements[edgesPlusNodesLabeled,
"Neighbors", #Label < threshold &];
coords = ComponentMeasurements[edgesPlusNodesLabeled,
"BoundingDiskCenter", #Label >= threshold &];

Graph[UndirectedEdge @@@ neighbors[[All, 2]],
VertexCoordinates -> coords, VertexSize -> .2] Overlay on the original image:

HighlightImage[img, {Thick, Line /@ neighbors[[All, 2]] /. coords,
Green, Translate[Disk[{0, 0}, Offset], coords[[All, 2]]]}] • Your answer and halmir's are both excellent! If I could accept two I would have but I chose the halmir's because it's simpler. Dec 31, 2021 at 11:43
• This is a particularly interesting question, and I asked a similar question for non-planar graphs. See mathematica.stackexchange.com/questions/261413/… Dec 31, 2021 at 13:46