<p>Gradient magnitude and angle can be found using a <a href="https://en.wikipedia.org/wiki/Sobel_operator" rel="nofollow noreferrer">Sobel operator</a>. It's more sophisticated than the [1, 0, -1]. This is commonly used either directly for <a href="https://en.wikipedia.org/wiki/Edge_detection" rel="nofollow noreferrer">edge detection</a>, or as part of a <a href="https://en.wikipedia.org/wiki/Canny_edge_detector" rel="nofollow noreferrer">more complex algorithm</a>.</p>

<p>Or, if I've misunderstood, and you want only the curvature of the 2D isoline, <a href="https://math.stackexchange.com/questions/1122819/numerical-approximation-for-2d-curvature">this answer on Math Overflow</a> might be of use.</p>

CC BY-SA 3.0
2017-11-20T12:29:04.790Z
Thanks, I'm aware of the Sobel operator, but it slows my algorithm down too much. The MO answer assumes I have the isoline as a set of points. I don't, I have a 2D array of grayscale values.
Stefan Monov
CC BY-SA 3.0
2017-11-20T15:50:55.973Z
In that case, you might consider posting your code to the [CodeReview StackExchange](https://codereview.stackexchange.com/) and ask for performance help.
user1118321
CC BY-SA 3.0
2017-11-20T18:58:40.073Z
I could, but the folks over there are less likely to have the specialized expertise for doing this *graphics* thing efficiently. Thanks again.
Stefan Monov
CC BY-SA 3.0
2017-11-20T03:16:23.037Z
2017-11-20T03:16:23.037Z
user1118321
<p>I've got a discrete grayscale image (a.k.a. 2D rectangular array of floats). Its continuous representation (whether received via reconstruction with sinc, with a cubic kernel, with a triangle kernel...) is a continous 2D function, so it has isolines. I'm interested in calculating the magnitude of the derivative of the isoline at a given point.</p>

<p>Pic:</p>

<p><a href="https://i.sstatic.net/QErl7.png" rel="noreferrer"><img src="https://i.sstatic.net/QErl7.png" alt="diagram"></a></p>

<p>Red line is part of an isoline, and green arrows are example derivatives of that isoline at 2 points.</p>

<p>Here's my approximate solution:</p>

<pre><code>float getCurvature(vec2 p) {
    vec2 grad = getBilinear(gradients, p);
    if(grad = vec2(0, 0)) return 0;
    else grad = normalize(grad);

    vec2 gradP = perpendicularLeft(grad);

    float val = getBilinear(img, p);
    float valLeft = getBilinear(img, p+gradP);
    float valRight = getBilinear(img, p-gradP);
    return (val - (valLeft + valRight) * .5f);
}
</code></pre>

<p>It basically computes the second directional derivative in a direction perpendicular to the gradient. It works fine for my purposes, except that it's somewhat slow in the CPU implementation (and I have reasons not to port it to GPU).</p>

<p>Any faster (and/or more accurate) method?</p>

<p><strong>Edit:</strong> I found a twice-faster method, still calculating the second derivative, but in a simpler way. It's equation (5) <a href="http://mathonline.wikidot.com/higher-order-directional-derivatives" rel="noreferrer">on this page</a>. It works, but the result is more crude. I think I should switch to a higher-quality differentiation kernel than [+1, 0, -1].</p>

<algorithm>
How to calculate curvature of isoline of image
Stefan Monov
# How to calculate curvature of isoline of image

(Asked by: username_0 on 2017-11-18)

I've got a discrete grayscale image (a.k.a. 2D rectangular array of floats). Its continuous representation (whether received via reconstruction with sinc, with a cubic kernel, with a triangle kernel...) is a continous 2D function, so it has isolines. I'm interested in calculating the magnitude of the derivative of the isoline at a given point.

Pic:

[![diagram](https://i.sstatic.net/QErl7.png)](https://i.sstatic.net/QErl7.png)

Red line is part of an isoline, and green arrows are example derivatives of that isoline at 2 points.

Here's my approximate solution:

```
float getCurvature(vec2 p) {
    vec2 grad = getBilinear(gradients, p);
    if(grad = vec2(0, 0)) return 0;
    else grad = normalize(grad);

    vec2 gradP = perpendicularLeft(grad);

    float val = getBilinear(img, p);
    float valLeft = getBilinear(img, p+gradP);
    float valRight = getBilinear(img, p-gradP);
    return (val - (valLeft + valRight) * .5f);
}

```

It basically computes the second directional derivative in a direction perpendicular to the gradient. It works fine for my purposes, except that it's somewhat slow in the CPU implementation (and I have reasons not to port it to GPU).

Any faster (and/or more accurate) method?

**Edit:** I found a twice-faster method, still calculating the second derivative, but in a simpler way. It's equation (5) [on this page](http://mathonline.wikidot.com/higher-order-directional-derivatives). It works, but the result is more crude. I think I should switch to a higher-quality differentiation kernel than [+1, 0, -1].

**Tags:** algorithm


---

## 1 answers

### Answer by username_1 on 2017-11-20. Score: 2

Gradient magnitude and angle can be found using a [Sobel operator](https://en.wikipedia.org/wiki/Sobel_operator). It's more sophisticated than the [1, 0, -1]. This is commonly used either directly for [edge detection](https://en.wikipedia.org/wiki/Edge_detection), or as part of a [more complex algorithm](https://en.wikipedia.org/wiki/Canny_edge_detector).

Or, if I've misunderstood, and you want only the curvature of the 2D isoline, [this answer on Math Overflow](https://math.stackexchange.com/questions/1122819/numerical-approximation-for-2d-curvature) might be of use.

> **Comments:**
> **username_0**: Thanks, I'm aware of the Sobel operator, but it slows my algorithm down too much. The MO answer assumes I have the isoline as a set of points. I don't, I have a 2D array of grayscale values.  
> **username_1**: In that case, you might consider posting your code to the [CodeReview StackExchange](https://codereview.stackexchange.com/) and ask for performance help.  
> **username_0**: I could, but the folks over there are less likely to have the specialized expertise for doing this *graphics* thing efficiently. Thanks again.  

---

