# Signed distance function from grayscale image

I have a grayscale image and I would like to convert it to a signed distance function.

Right now I'm using DistanceTransform but I do not like the result.

image = Import[FileNameJoin[{NotebookDirectory[], "harbor.png"}]];
levelset =
ImageData[DistanceTransform[ColorNegate[image]] ] -
ImageData[DistanceTransform[image] ];
ListPlot3D[levelset]


harbor.png

output

You can clearly see the outline on the 3d plot which is really noisy, this is probably from the fact that DistanceTransform works on black&white images not on grayscale images.

What I really need is correct gradients near boundary but right now they are complete mess. Is there an easy way how to achieve this?

• Can you explain what you mean by a "signed distance function"? BTW - DistanceTransform does not require a black and white image. – bill s Mar 27 '18 at 13:23

How exact do you need the result to be? You could just binarize an upscaled version of the image:

img = Import["https://i.stack.imgur.com/iMQGZ.png"];
b = Binarize[ImageResize[img, Scaled[8]], .5];
d = DistanceTransform[b] - DistanceTransform[1 - Dilation[b, 1]];


ListContourPlot[ImageData[d][[;; ;; 8, ;; ;; 8]]]

ListPlot3D[ImageData[d][[;; ;; 8, ;; ;; 8]]]

• Just a small improvement. You probably want to divide the result by 8(or by whatever scaling factor you choose). At first I was a bit confused about the values I got. – tom Mar 27 '18 at 15:36