I'll start from the code given by flinty in the comment in order not to do this work again. Let us name his end result as firstStage:
img = Import["https://i.stack.imgur.com/ujHq1.png"];
vtxmask = Closing[Binarize@img, 2];
edgemask = Binarize@ImageMultiply[ColorNegate@img, vtxmask];
firstStage =
Pruning@Thinning@
ImageAdd[edgemask, ImageMultiply[ColorNegate@vtxmask, Red]]

The rest is mine.
I'll proceed in the same manner as in my previous answer. Most of the code is self-describing, so I'll comment on it only a little.
nodesRemoved = Binarize[firstStage];
nodes = firstStage - nodesRemoved;
nodesLabeled = MorphologicalComponents[nodes]*1000000;
nodesLabeled // Colorize

After removing the nodes we have full edges with crossovers. We broke full edges at crossovers, and then separate broken edges and crossovers by labeling:
brokenEdges =
DeleteSmallComponents[
MorphologicalTransform[nodesRemoved,
If[#[[2, 2]] == 1 && Total[#, 2] <= 3, 1, 0] &], 5];
brokenEdgesLabeled = MorphologicalComponents[brokenEdges]*100;
brokenEdgesLabeled // Colorize
crossovers = nodesRemoved - brokenEdges;
crossoversLabeled = MorphologicalComponents[crossovers];
crossoversLabeled // Colorize


Bringing back together nodes, crossovers, and broken edges (but now all they have distinct labels!):
everythingLabeled =
brokenEdgesLabeled + crossoversLabeled + nodesLabeled;
everythingLabeled // Colorize

Each crossover occurs at the intersection of two full edges and connects 4 line segments ("broken edges"):
crossoversWithBrokenEdges =
ComponentMeasurements[everythingLabeled,
"Neighbors", #Label < 100 &];
For determining pairs of line segments ("broken edges") that correspond to one full edge, we determine centroids of broken edges and crossovers:
crossoversCentroids =
ComponentMeasurements[everythingLabeled, "Centroid", #Label < 100 &];
brokenEdgesCentroids =
ComponentMeasurements[everythingLabeled, "Centroid",
100 <= #Label < 1000000 &];
Every broken edge connects a crossover and a node, every full edge connects two nodes:
brokenEdgesWithNodes =
ComponentMeasurements[everythingLabeled, "Neighbors",
100 <= #Label < 1000000 &];
Let us define a function that determines which pair of broken edges correspond to the full edge. The key idea is that planar angle composed by the centroids of two broken edges with centroid of the crossover inbetween should be near 180 degrees:
Clear[joinBrokenEdges]
joinBrokenEdges[cross_ -> labels : {p1_, p2_, p3_, p4_}] :=
Module[{pts = labels /. brokenEdgesCentroids,
cr = cross /. crossoversCentroids, n, pair1, pair2},
n = MaximalBy[# -> PlanarAngle[cr -> pts[[{1, #}]], "Interior"] & /@ {2, 3, 4},
Last][[1, 1]];
pair1 = labels[[{1, n}]];
pair2 = labels[[Complement[{2, 3, 4}, {n}]]];
Rule[Alternatives @@ #, #] & /@ {pair1, pair2}
];
With this function, we transform crossoversWithBrokenEdges into a set of rules for joining broken edges:
joiningRules = Flatten[joinBrokenEdges /@ crossoversWithBrokenEdges];
These rules apply only to really broken edges, so we can easily get full edges from brokenEdgesWithNodes:
fullEdgesWithNodes =
Cases[brokenEdgesWithNodes /. joiningRules,
HoldPattern[_Integer -> _]];
Joining broken edges is a bit trickier:
joinedEdgesWithNodes =
Normal[Select[Flatten[#], # >= 1000000 &] & /@
GroupBy[Cases[brokenEdgesWithNodes /. joiningRules,
HoldPattern[_List -> _]], First -> Last]];
Now we have all edges recovered:
allEdges =
Join[fullEdgesWithNodes[[All, 2]], joinedEdgesWithNodes[[All, 2]]];
We also need node centroids in order to reproduce the original layout of the graph:
nodesCentroids =
ComponentMeasurements[everythingLabeled,
"Centroid", #Label >= 1000000 &];
Now everything is ready:
Graph[Style[UndirectedEdge @@ #, RandomColor[]] & /@ allEdges,
VertexCoordinates -> nodesCentroids,
VertexLabels -> Placed["Name", Tooltip],
EdgeLabels -> Placed["Name", Tooltip], VertexSize -> .2]

img = Import["https://i.stack.imgur.com/ujHq1.png"]; vtxmask = Closing[ Binarize@img , 2]; edgemask = Binarize@ImageMultiply[ColorNegate@img, vtxmask]; Pruning@Thinning@ImageAdd[ edgemask, ImageMultiply[ColorNegate@vtxmask, Red] ]Having preprocessed it, it might be easier to work from this https://imgur.com/a/WaIxkhk but not sure where to start. – flinty Jan 01 '22 at 14:52