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] ];


enter image description here


enter image description here

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?

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

1 Answer 1


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]];

This yields relatively clean-looking gradients:

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

enter image description here

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

enter image description here

  • $\begingroup$ Good idea to upscale and then downscale! This should suffice for my purpose. $\endgroup$
    – tom
    Mar 27, 2018 at 15:12
  • $\begingroup$ 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. $\endgroup$
    – tom
    Mar 27, 2018 at 15:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.