Here's my attempt, which uses the neural net Carl Lange referred to, plots mesh lines with ListPlot3D
, and finds a 'nice' view point to see the lines.
net = NetModel["Single-Image Depth Perception Net Trained on NYU Depth V2 and Depth in the Wild Data"];
img = Import["https://www.liveenhanced.com/wp-content/uploads/2017/12/Beauty-Of-Bears-Ears-National-Monument.jpg"];
{x, y} = ImageDimensions[img];
height = 1 - Rescale[ArrayResample[net[img], Round[{x, y}/4]]];
meshlines = ListPlot3D[
400 Reverse[height],
Mesh -> 100, MeshFunctions -> {#2 &},
DataRange -> {{0, x}, {0, y}}, PlotStyle -> None
];
mr = DiscretizeGraphics[meshlines,
MeshCellStyle -> {1 -> Black}, PlotTheme -> "Lines"];
M = MomentOfInertia[Point[MeshCoordinates[mr]]];
{v1, v2} = Rest[Eigenvectors[M]];
Show[mr, ViewVertical -> {0, 0, -1},
ViewPoint -> {0, 10, 10} Normalize[Cross[v1, v2]]]
It might be possible to accentuate the detail better by finding a suitable power to raise height
to, e.g. height^2
, etc.
Here's a way to project into 2D, rather than adjusting the ViewPoint
in 3D:
MeshRegion[
-PrincipalComponents[MeshCoordinates[mr]][[All, 1 ;; 2]],
MeshCells[mr, 1],
PlotTheme -> "Lines", MeshCellStyle -> {1 -> Black}
]
Here's a way to add some smooth edge lines. There's room for improvement here -- both in the implementation and output -- and the high degree splines take some time to render.
The idea is to edge detect, break up branch points to get a collection of path curves, approximate each path with a smooth curve, then map into 3D.
boundary = Thinning[EdgeDetect[im, 10]];
brokenboundary = ImageMultiply[boundary, ColorNegate[MorphologicalBranchPoints[boundary]]];
ones = Position[Reverse[Transpose[ImageData[brokenboundary]], {2}], 1];
g = NearestNeighborGraph[ones, {All, 1.5}];
comps = WeaklyConnectedGraphComponents[g];
paths = FindHamiltonianPath /@ comps;
hmap = ListInterpolation[400 Reverse[Transpose[height], {2}], {{0, x}, {0, y}}];
paths3d = Apply[{##, hmap[##]} &, paths, {2}];
Show[
mr,
Graphics3D[{AbsoluteThickness[1], BSplineCurve[#, SplineDegree -> Length[#] - 1] & /@ paths3d}],
ViewVertical -> {0, 0, -1},
ViewPoint -> {0, 10, 10} Normalize[Cross[v1, v2]]
]
ImageRestyle
a shot. If it has enough time I think it could do a really nice job of this. $\endgroup$