Approximating ridge lines

What is a good method to delineate ridge lines that exist within a DEM? My goal is a contour map with heavier lines to represent ridges. [The inverse of this would be to delineate flow lines.]

I’ve been experimenting with grdgradient, with the -D and -S options (azimuth & magnitudes), even applying grdgradient twice, to get some sense of the locations of ridges.

I haven’t quite stumbled upon the means to derive a good representation of ridges. Is there a better algorithm to numerically determine ridge lines (or flow lines)?

After more trial and error, it seems that grdfilter using a box-car mean and a high-pass filter (-Fb25+h), followed by a grdmath command (to mask-out low values) does a fairly decent job of “finding” ridge lines. I’m tweaking parameters to find the sweet spot for what I need.

I’m also interested in this. Care to share some nice plots/results?

Me too :slight_smile:

This experiment is nowhere near being able to directly create a numerical ridge-line data set on the basis of an input DEM. All that I’ve been able to do is identify localized high spots within a DEM.

This is a map of a small portion of the south polar region of the Moon, near the Amundsen Crater. Here’s a sample of the topography (units are meters above the lunar sphere: 1737.4 m):

Using these two commands, I was able to generate an image that indicates the highest points:

gmt grdfilter t.grd -Dp -Fb29+h -Gthp.grd # compute a high-pass DEM
gmt grdmath thp.grd DUP 3 GT MUL 0 NAN = thp1.grd # only retain highest values

Here, in the first command, the box-car regional mean is defined to be 29 cells wide, utilizing a high-pass filter (+h).

Next, a value of 3 was rather arbitrarily used to set a lower threshold limit.

The resulting image appears something like this:

The next step, which I haven’t solved (and likely won’t), is to trap the coordinates of these ridges and crater rims in some meaningful way.

Another thing that pops-out under this kind of processing are LOLA tracking artifacts!

That’s all I have, so far. Thanks for your interest.

1 Like

I’m not sure if this is a potential solution to getting coordinates of the ridges or not.

grdcontour can dump the coordinates of contours using the -D option. If it is somehow possible to contour your last image so that contour lines fall on the black parts, then you might be able to dump the coordinates this way.

I read there’s something called “catchment area” or “flow accumulation” hydrological analysis, like

that produces valley bottom lines so to say.

Some people online suggested it is possible to invert DEM (multiply with -1) and then run hydrological analysis to get ridges.

a SAGA GIS tool behind the QGIS interface appears to be this Tool Flow Accumulation (Top-Down) / SAGA-GIS Tool Library Documentation (v7.0.0)

never tried any of this myself.

@Tim, yes, I thought about that as well, but the lines in the map are rather “fuzzy” and I wasn’t sure that the contour dump would be very meaningful. And the choice of contour may be subjective. Won’t really know until it’s attempted.

@mkono, I spotted some of that material during an on-line search, as well. It seems there are software packages out there that can perform these kinds of tasks. There is a 2019 paper by Tsai & Lin published in the Civil Engineering Research Journal, that provides some very useful ideas. This paper led me to try using grdfilter in a similar fashion.

DOI: 10.19080/CERJ.2019.07.555709

Thank you for the comments and thoughts!

River paths are detected with those flow accumulation alghoritms. Probably simpler (and less accurate) is the Ridge Detection that uses image processing techniques. GMT has neither of them.

The lack of a ridge detection scheme within GMT was why the question was posed!

My approach succeeds at providing a map with the basic info needed. The particular features that are needed can be digitized, in order to make the map/graphic required.

This whole ridge detection thing made me curious, so I had a little play around with the data. Here’s my script:

#!/usr/bin/env zsh
#

gmt grdcut @moon_relief_15s -Gmoon.grd -R74/88/-83/-78
gmt grdgradient moon.grd -D -Gdir.grd -Smag.grd
gmt grdmath -M mag.grd dir.grd SIND MUL DDX \
            mag.grd dir.grd COSD MUL DDY ADD = div.grd
gmt grdfilter div.grd -D4 -Fb3 -Gfiltdiv.grd

gmt begin moon png
   gmt grdimage moon.grd -JS82.5/-90/20 -R75/-82/86/-79+r -Cgray -I
   gmt grdcontour filtdiv.grd -C-0.00002, -Wthick,red
gmt end show
  • First I cut out a small patch of the moon relief and compute the directional and magnitude components of the gradient using grdgradient.
  • Next I compute the divergence of the gradient using grdmath (I hope I’ve got it right!).
  • Then I filter the divergence field using a boxcar filter to just leave the big features (the filter width was somewhat arbitrary).

The plot shows the relief with contours of the filtered divergence overlaid. The -C-0.00002 was found arbitrarily using trial and error.

Maybe the contours could be dumped with the -D option of grdcontour, and then simplified with the simplify module?

1 Like

I’m realising how long it has been since I studied this stuff at university! The divergence of the gradient is the Laplacian. Here is a simplified version of the above script:

#!/usr/bin/env zsh
#

gmt grdcut @moon_relief_15s -Gmoon.grd -R74/88/-83/-78
gmt grdmath -M moon.grd D2DX2 moon.grd D2DY2 ADD = laplacian.grd
gmt grdfilter laplacian.grd -D4 -Fb3 -Gfilt_laplacian.grd

gmt begin moon png
   gmt grdimage moon.grd -JS82.5/-90/20 -R75/-82/86/-79+r -Cgray -I
   gmt grdcontour filt_laplacian.grd -C-0.00002, -Wthick,red
gmt end show
3 Likes

Very cool @timhume.

If I may, since you seem to remember the lectures at university (..);

In the grdmath docs docs there is an operator called CURV, which returns the Curvature of A (Laplacian). Do you know why it is called Laplacian? As you write, isn’t the divergence of the gradient the Laplacian?

Oh dear @Andreas … when I say remember my lectures, it’s a bit like remember a movie one saw thirty years ago. Bits and pieces come back, but not the whole works. This was stuff they taught us in second year physics … and I remember the lecturer setting extremely hard assignments which would wipe out whole weekends.

I’m not sure why CURV is labelled curvature instead of LAP or some such thing. I just checked, and it returns exactly the same result as the script using D2DX2 etc. So there goes a further simplification.

How I ended up at the Laplacian was I was thinking about drawing the gradient on a DEM. The gradient is a field of vectors pointing in the upwards direction of the terrain. A feature of ridge lines is that the gradient vectors on both sides of the ridge line will be converging at the ridge. And converging vectors have a negative divergence. Similarly for valleys, one would look for the gradient vectors diverging (positive divergence). It was only later that I realised that I was actually just computing the Laplacian.

1 Like

The second derivative of a curve gives us the curvature of it. So the Laplacian


also represents the curvature of a surface.

2 Likes

So Laplacian and curvature are synonyms? Or does the word chosen depend on context?

Here’s the best description I could find in a few minutes: https://physics.stackexchange.com/questions/20714/laplace-operators-interpretation

1 Like

Thanks @timhume!

I think that this video can help understand the Laplacian.

2 Likes