0

I want to find sharp edges in a heightmap image, while ignoring shallow edges.

OpenCV offers multiple approaches to finding edges in a 2d Image: Canny, Sobel, etc.

However, all these approaches work by comparing the intensity values on both sides of the edge. If the 2D Image represents a height map of a 3D object, then this results in some weird behaviour.

In a height map, the height of a 3D object at a given X/Y coordinate is represented as the intensity of the 2D Pixel at that X/Y coordinate:

enter image description here

In the above picture, at the edge B the intensity changes only slightly between the left and right side, even though it is a sharp corner.

At the edge A, there is a bigchange in the intensity between pixels on the left side of the edge and the right, even though it is only a shallow angle.

So there is no threshold for Canny or Sobel that will preserve the sharp edge but filter the shallow edge.

(In the above example, the edge B has one side with an ascending slope, and one side with a descending slope. I could filter for this feature; but that would remove the edges C and D as well)

How can I get a binary edge image, containing only edges above a certain angle? (e.g. edge B, C, and D, but not A)

Or alternatively, how can I get a gradient derivative image, where the intensity of each pixel is proportional to the angle of the edge at that pixel?

HugoRune
  • 11,755
  • 6
  • 57
  • 129

3 Answers3

0

Probably you'll want to use second derivative instead of first for this task.

Here's my intuition: taking derivative of height (intensity in your case) at each position on an evenly spaced grid would be proportional to arctan of the surface slope between sampling points (or at sampling points if you use a 2-sided derivative approximation). But since you want to detect sharp edges - you are looking for a derivative of slope at the sampling points. This means that you can set a threshold on a derivative of arctan of derivative of intensity to achieve your goal (luckily there's no "need to go deeper" :) )

You will have to be extra careful with taking a derivative of "slope angles" that you'll get - depending on the coordinate system you may come across ambiguity of angle difference (there are 2 ways to get from one angle to another, which are different in general case; you're looking for the "shorter" one). You can look for possible solution here

Community
  • 1
  • 1
alexisrozhkov
  • 1,595
  • 9
  • 18
0

I have a rather simple approach that I came across wile reading a blog post.

It involves computing the median value of the gray scale image. Using this value we can now set two threshold values:

  • lower: max(0, (1.0 - 0.33) * v)
  • upper: min(255, (1.0 + 0.33) * v)

Now pass these two values as parameters into the cv2.Canny() function.

You will now be able to perform an optimized edge detection given any image. The crux of this answer depends on the median value of the image which varies for different images.

Jeru Luke
  • 13,413
  • 9
  • 57
  • 71
-1

If i understand your question correctly, "what you need is basically a corner with high intensity values". If that is so then look for Harris corner detector which would help you to find points with high gradient change in both direction. http://docs.opencv.org/2.4/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.html

Once you detect the corners you can filter the corners which have high intensity by using a suitable threshold.

Aparajuli
  • 254
  • 1
  • 2
  • 12