Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

non-max suppression not working #2

Open
steveliles opened this issue Mar 16, 2018 · 1 comment
Open

non-max suppression not working #2

steveliles opened this issue Mar 16, 2018 · 1 comment

Comments

@steveliles
Copy link

steveliles commented Mar 16, 2018

Hi, great lib (and also image-js) - thanks :)

I noticed that non-max suppression doesn't seem to be working - I end up with some very thick edges. For example, here's lena:

lena-canny-mod5

I inserted some debugging and noticed that we're getting 5 values for dir, vs. the intended 4 (per the description of edge thinning in wikipedia).

Changing line 71 to % 4 instead of % 5 appears to work (thins the edges to 1 pixel), but the results don't look right, so I'm dubious that my change here is correct. For example, look at the hat brim, and the vertical post to the left side, compared to the 3rd output image below.

lena-canny-mod4

I didn't understand the math enough to know how to fix line 71, so I replaced with my own - possibly less efficient - alternative, based on the wikipedia description:

var angle_radians = Math.atan2(gradientY.getValueXY(i, j, 0), gradientX.getValueXY(i, j, 0))
var angle_degrees = Math.abs((180/Math.PI)*angle_radians)-22.5
var dir = Math.round(angle_degrees / 45)

... which produces an output more in line with what I'd expect:

lena-canny-steve

I'm still not convinced this is correct/ideal, as there are some stronger edges in the %4 version than in this version which would be nice to preserve too - e.g. compare the top-right of the hat, lena's cheek, and the top of lena's shoulder between the 2nd and 3rd outputs. I assume this is related to the differences in rounding between the two implementations.

btw., I timed several runs using each implementation and don't see an appreciable difference (actually mine was about 0.5% faster in this very unscientific test).

Tests above used the following options:

{ gaussianBlur:2, lowThreshold: 10, highThreshold:20 }
@steveliles
Copy link
Author

For my own understanding while debugging I ended up re-writing the non-max suppression loop as follows:

for (var i = 1; i < width - 1; i++) {
        for (var j = 1; j < height - 1; j++) {

        var angle_radians = Math.atan2(gradientY.getValueXY(i, j, 0), gradientX.getValueXY(i, j, 0))
        var angle_degrees = (180/Math.PI)*angle_radians
        if (angle_degrees < 0) {
          angle_degrees = angle_degrees + 157.5
        } else {
          angle_degrees = angle_degrees - 22.5
        }
        var dir = Math.round(angle_degrees / 45) * 45
        var current = G.getValueXY(i, j, 0)

            switch (dir) {
              case 0:
                if ((current >= G.getValueXY(i, j - 1, 0)) && (current >= G.getValueXY(i, j + 1, 0))) {
                  nms.setValueXY(i, j, 0, current)
                }
                break
              case 45:
                if ((current >= G.getValueXY(i - 1, j - 1, 0)) && (current >= G.getValueXY(i + 1, j + 1, 0))) {
                  nms.setValueXY(i, j, 0, current)
                }
                break
              case 90:
                if ((current >= G.getValueXY(i - 1, j, 0)) && (current >= G.getValueXY(i + 1, j, 0))) {
                  nms.setValueXY(i, j, 0, current)
                }
                break
              case 135:
                if ((current >= G.getValueXY(i - 1, j + 1, 0)) && (current >= G.getValueXY(i + 1, j - 1, 0))) {
                  nms.setValueXY(i, j, 0, current)
                }
                break
            }
        }
    }

With this I'm getting results more in line with what I'd expect, for example with the same options as the above 3 images I'm now getting:

lena png-canny

Now that (I think) it is working properly, there's too much noise with the thresholds set so low. Here's { gaussianBlur:2, lowThreshold: 20, highThreshold:40 }

lena png-canny

Nice clean lines and you can easily pick out the features of the eyes, so I think this is about right, however it does seem to be ~ 15-20% slower.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant