using a sobel operator - edge detection

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

using a sobel operator - edge detection

Post by HugoRune »

Hi
I am trying to implement an edge detection by analysing fred's excellent gradient script, but something seems to be missing:

Here is something that should work like a horizontal sobel:

Code: Select all

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" \  
-convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)"  test.png
Image

But only one one half of the circle shows up.
I think imagemagick might be ignoring the abs(u)?
Or am I misunderstanding how this operator is supposed to work?

By the way, what sort of operator does the -edge switch use? is (-edge 1) plus (-negate -edge1) the same as a sobel or prewit operator?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

HugoRune wrote:Hi
I am trying to implement an edge detection by analysing fred's excellent gradient script, but something seems to be missing:

Here is something that should work like a horizontal sobel:

Code: Select all

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" \  
-convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)"  test.png
Image

But only one one half of the circle shows up.
I think imagemagick might be ignoring the abs(u)?
Or am I misunderstanding how this operator is supposed to work?
It works for me (but I am currently in Q16 HDRI).
But you may have some gremlins (bad invisible chars in your command line). Try

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)" circ_edge.png


Image

Image

what version of IM are you using and on what platform.

convert -version

will tell you your version


The issue is likely that your negative values are getting clipped at zero as you are not in HDRI. So you will need to add a bias to your command line. So use this:

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)" circ_edge2.png

Image
HugoRune wrote: By the way, what sort of operator does the -edge switch use? is (-edge 1) plus (-negate -edge1) the same as a sobel or prewit operator?
It uses a circular gaussian type blur and subtracts from the image.
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

Re: using a sobel operator - edge detection

Post by HugoRune »

Thanks!
I am using ImageMagick 6.5.4-2 2009-06-30 Q16 OpenMP on windows xp, so that is indeed the problem

It seems like getting the HDRI version requires recompiling which I' drather avoid, but I can try if the other option does not work

I tried your bias suggestion, however my results are not quite the same:
convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)" circ_edge2.png

Image

( The other line
convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)" circ_edge.png
produced Image Image as before)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

It does appear to be an issue with not having HDRI. But you can get around it. Note the edge detector is one sided. Thus on the left of the circle you step from black to white, but on the right side you step from white to black. Thus on the left side it will be white and the right side black with the bias (as per my example3). If you leave the bias off and are not in HDRI you will get the black clipped as it is really negative. If you want both sides you can either combine two edge detectors with opposite polarity or just do as I did in the last example below, at least for your simple black and white image. That should work with nonHDRI

Here are my results with HDRI, but you can use the last to get what you want, I believe:

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)" circ_edge.png
Image

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -fx "abs(u)" circ_edge2.png
Image

convert -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" circ_edge3.png
Image

convert \( -size 50x50 xc:black -fill white -draw "circle 25,25 20,10" -write circ.png \
-bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" \) \
\( -clone 0 -negate \) -compose difference -composite circ_edge4.png
Image
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

Re: using a sobel operator - edge detection

Post by HugoRune »

Thanks, this works:

Code: Select all

convert  zelda3.JPG ^
    ( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" ( +clone -negate ) -compose difference -composite ) ^
    ( -clone 0 -bias 50% -convolve "-1,-2,-1,0,0,0,1,2,1" ( +clone -negate ) -compose difference -composite ) ^
    -delete 0 ^
    -compose plus -composite test6.png
The result looks sobel-like
Image --> Image

I also tried this variant

Code: Select all

convert  zelda3.JPG ^
    ( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -negate -level 50%,100% ) ^
    ( -clone 0 -bias 50% -convolve "-1,-2,-1,0,0,0,1,2,1" -solarize 50% -negate -level 50%,100% ) ^
    -delete 0 ^
    -compose plus -composite test5.png
same result, might be a bit faster

Image


But I think there is still some clipping involved: The results I get with gimp look much smoother and preserve more details:

Image

Is this due to lack of HDRI, or is there something else I am missing?

I am not doing the sqrt(sobelX^2+sobelY^2) step, instead simply adding them, but I do not think that is the sole cause.


UPDATE
I got some improvements by halfing the brightness of the two sobel images before adding them.
Still not quite there however.

Code: Select all

convert  zelda3.JPG ^
    ( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -negate -level 50%,100% +level 0%,50% ) ^
    ( -clone 0 -bias 50% -convolve "-1,-2,-1,0,0,0,1,2,1" -solarize 50% -negate -level 50%,100% +level 0%,50% ) ^
    -delete 0 ^
    -compose plus -composite test7.png
imagemagick: Image gimp: Image

UPDATE 2
almost there!
There is apparently some clipping happening
But I simply divided the whole kernel by 10, now the results are very close to perfect.
10 is probably not quite the right number, I just got that by trial and error.
If I am normalizing the image afterwards, it probably does not matter.

Code: Select all

convert  zelda3.JPG ^
    ( -clone 0 -bias 50% -convolve "-0.1,0,0.1,-0.2,0,0.2,-0.1,0,0.1" -solarize 50% -negate -level 50%,100% ) ^
    ( -clone 0 -bias 50% -convolve "-0.1,-0.2,-0.1,0,0,0,0.1,0.2,0.1" -solarize 50% -negate -level 50%,100% ) ^
    -delete 0 ^
    -compose plus -composite test8.png
imagemagick: Image

The remaining differences might be due to simply adding the two sobel images instead of building the root of the sum of their squares.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

adding two images that have full dynamic range without hdri will overshoot white. you are using -compose plus which will oveshoot white when you add two full dynamic range images. You could try -blend 50%.

But properly you need to do the square and square root or abs as in my script.

The other issue is the way IM handles kernel coeffs. It does an automatic normalization. If the coeffs were all positive, then it would divide by the sum of the coeffs so that the result had a gain of 1 and would not change the overall brightness. With your filters, edge detectors, they sum to zero. So IM apparently uses the max value for the gain. Thus the filters are twice as bright as they should be, because the max value is 2 and -2. So you may want to compensate.

Try this, where I have used a gain variable that you can adjust to suit to compensate for the internal gain by 2, but you can make it smaller. This is multipled by the result of the convolution, but is equivalent to dividing each coefficient by 2. Then I compute the squared x and y components, add them together and take the square root (-evaluate pow 0.5 or -gamma 2, they are equivalent).

dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=0.5
convert \( $infile -convolve "$dx" -evaluate multiply $gain \) \( $infile -convolve "$dy" -evaluate multiply $gain \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad.png

Image

GIMP probably has some other normalization scheme for edge filters whose sum is zero. Perhaps they normalize by the sum of the absolute values of the kernel coeffs, which would be dividing by 8.

dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/8]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain \) \( $infile -convolve "$dy" -evaluate multiply $gain \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad2.png
Image

or perhaps half that or divide by 4

dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/4]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain \) \( $infile -convolve "$dy" -evaluate multiply $gain \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad3.png
Image

For all I know they may be doing something to sharpen the result via added post processing like thresholding the edges so only to get those above some value or even unsharp masking. But who knows for sure.
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

Re: using a sobel operator - edge detection

Post by HugoRune »

I was curious, so I checked the source of gimps sobel-.c
They divide the end result by 5,66, which probably means
5,66 = sqrt(32) = sqrt(4^2 + 4^2)
so essentially dividing each side by 4.

I guess the maximum value the sobel mask can produce is 4*white:

Code: Select all

-1 0 1      B B W
-2 0 2 over B B W
-1 0 1      B B W

= 1*w + 2*w + 1*W = 4
(B = black,W = white)
So by dividing by 4 there should be no clipping in the end.

However I had trouble getting the "-evaluate multiply 0.25" to work properly when using bias. I think until I switch to HDRI, my last attempt with

Code: Select all

convert  zelda3.JPG ^
    ( -clone 0 -bias 50% -convolve "-0.1,0,0.1,-0.2,0,0.2,-0.1,0,0.1" -solarize 50% -negate -level 50%,100% ) ^
    ( -clone 0 -bias 50% -convolve "-0.1,-0.2,-0.1,0,0,0,0.1,0.2,0.1" -solarize 50% -negate -level 50%,100% ) ^
    -delete 0 ^
    -compose plus -composite test8.png
works well enough for my purposes
Image
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

Did you try my code directly? and don't add the bias. it should work fine under Q16 no HDRI. I wrote my scripts under Q16 no HDRI and they worked. See first set of examples at http://www.fmwconcepts.com/imagemagick/ ... /index.php However, there I did not include the -evaluate multiply .25 (-evaluate divide 4). So the code I just gave you was a direct copy and simplification of what was in my Q16 script except for the scaling by 1/4.

My script implements the exact definition of gradient as sqrt (DX^2 + DY^2) using either the Prewit or Sobel edge detectors.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

Here is the difference without and with the bias. You can move the bias after the -evaluate.


dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/4]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain \) \
\( $infile -convolve "$dy" -evaluate multiply $gain \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad3.png
Image

dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/4]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain -bias 50% \) \
\( $infile -convolve "$dy" -evaluate multiply $gain -bias 50% \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad4.png
Image


using twice as large gain (0.5), we get

dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/2]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain \) \
\( $infile -convolve "$dy" -evaluate multiply $gain \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad5.png
Image

dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/2]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain -bias 50% \) \
\( $infile -convolve "$dy" -evaluate multiply $gain -bias 50% \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad6.png
Image
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

Re: using a sobel operator - edge detection

Post by HugoRune »

Did you try my code directly? and don't add the bias. it should work fine under Q16 no HDRI. I wrote my scripts under Q16 no HDRI and they worked.
Now i am confused. I tried your code, but I do not get the same results as you:

your zelda3_grad3.png Image --- my zelda3_grad3.png Image

It looks like my version (6.5.4-2 2009-06-30 Q16) is clipping some of the values and yours is not
(For testing, I just updated to "6.5.4-10 2009-08-08 Q16" but the results remain the same)

I had to change your code a bit to make it conform to windows, but that itself should not change the result:

Code: Select all

***your code for above pic***
dx="-1,0,1,-2,0,2,-1,0,1"
dy="1,2,1,0,0,0,-1,-2,-1"
infile="zelda3.png"
gain=`convert xc: -format "%[fx:1/4]" info:`
convert \( $infile -convolve "$dx" -evaluate multiply $gain \) \
\( $infile -convolve "$dy" -evaluate multiply $gain \) \
\( -clone 0 -clone 0 -compose multiply -composite \) \
\( -clone 1 -clone 1 -compose multiply -composite \) \
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad3.png

Code: Select all

***my command line, addapted for windows***
convert ( zelda3.JPG -convolve "-1,0,1,-2,0,2,-1,0,1" -evaluate multiply 0.25 ) ^
( zelda3.JPG -convolve "1,2,1,0,0,0,-1,-2,-1" -evaluate multiply 0.25 ) ^
( -clone 0 -clone 0 -compose multiply -composite ) ^
( -clone 1 -clone 1 -compose multiply -composite ) ^
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad3.png

The others are also different
here is zelda_grad_4
your zelda3_grad4.png Image---my zelda3_grad4.png Image

(update: in the last line, i had written "your zelda3_grad3.png -- my zelda3_grad3.png". Correct is "your zelda3_grad4.png -- my zelda3_grad4.png")
Last edited by HugoRune on 2009-08-15T14:50:13-07:00, edited 1 time in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

I suspect without HDRI and no bias, your derivatives are getting clipped at zero for the negative values. So you may need to do like I did with the bias:

convert ( zelda3.JPG -convolve "-1,0,1,-2,0,2,-1,0,1" -evaluate multiply 0.25 -bias 50% ) ^
( zelda3.JPG -convolve "1,2,1,0,0,0,-1,-2,-1" -evaluate multiply 0.25 -bias 50% ) ^
( -clone 0 -clone 0 -compose multiply -composite ) ^
( -clone 1 -clone 1 -compose multiply -composite ) ^
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad3_bias.png

Does that change things? Also try 0.5 rather than 0.25 and see how that affects it.

Sorry I am currently in HDRI for debugging other scripts and cannot change back right now. One has to be more creative when not in HDRI to overcome the clipping issues of the limitations from the IM compile not allowing negatives or fractional values.

As for Windows vs Unix, for reference see http://www.imagemagick.org/Usage/windows/, but looks like you have that under control.
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

Re: using a sobel operator - edge detection

Post by HugoRune »

fmw42 wrote:I suspect without HDRI and no bias, your derivatives are getting clipped at zero for the negative values. So you may need to do like I did with the bias:

convert ( zelda3.JPG -convolve "-1,0,1,-2,0,2,-1,0,1" -evaluate multiply 0.25 -bias 50% ) ^
( zelda3.JPG -convolve "1,2,1,0,0,0,-1,-2,-1" -evaluate multiply 0.25 -bias 50% ) ^
( -clone 0 -clone 0 -compose multiply -composite ) ^
( -clone 1 -clone 1 -compose multiply -composite ) ^
-delete 0,1 -compose plus -composite -gamma 2 zelda3_grad3_bias.png

Does that change things? Also try 0.5 rather than 0.25 and see how that affects it.
zelda3_grad3_bias.png: Image
(i think that is the same as the zelda3_grad4.png)

The other attempts with 0.5 instead of 0.25 failed similarly. As far as i can tell, convert clips immediately after the convolve, everything below 0 and above max_white. Any "-bias" or "-evaluate multiply" afterwards cannot affect the outcome.

However, if I put them before the -convolve, I can make it work:

Code: Select all

convert zelda3.JPG -evaluate multiply 0.125 -bias 50% ^
( -clone 0 -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -negate -level 50%,100% ) ^
( -clone 0 -convolve "1,2,1,0,0,0,-1,-2,-1" -solarize 50% -negate -level 50%,100% ) ^
-delete 0 ^
( -clone 0 -clone 0 -compose multiply -composite ) ^
( -clone 1 -clone 1 -compose multiply -composite ) ^
-delete 0,1 -compose plus -composite -gamma 2 ^
zelda_4_4.png
multiplying the source with 1/8 and using the old trick to remove the bias, I can get a result that looks exactly the same as with gimp.

left: imagemagick ---- right:gimp
Image Image

That seems to be the best solution for non-HDRI imagemagick.
Thanks for your help!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

I believe you are right about the -bias needing to be before the -convolve in nonhdri. But I believe the proper way is (but may or may not make a difference)

convert zelda3.JPG -evaluate multiply 0.125 ^
( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -negate -level 50%,100% ) ^
( -clone 0 -bias 50% -convolve "1,2,1,0,0,0,-1,-2,-1" -solarize 50% -negate -level 50%,100% ) ^
-delete 0 ^
( -clone 0 -clone 0 -compose multiply -composite ) ^
( -clone 1 -clone 1 -compose multiply -composite ) ^
-delete 0,1 -compose plus -composite -gamma 2 ^
zelda_4_4.png

But why do you need the solarize etc after the -convolve. Why negate. Seems like you can just use -solarize 50% -level 0x50%, if you really need it at all. Does that work equally? I think it should.

As I cannot get back to Q16 without HDRI at this time, I cannot verify. But -solarize etc is just going to do effectively the absolute value, which is more properly done by sqrt(X^2 + Y^2) rather than abs(X) + asb(Y). Note sure though about the 50% bias and how that might mess up the sqrt(X^2 + Y^2)

So you are doing sqrt( abs(X)^2 + abs(Y)^2 ) rather than properly sqrt(X^2 + Y^2) or its approx abs(X) + asb(Y) and the latter would probably need to be divided by two or blended to compensate for adding so that there is no clipping at white. But you are dividing by 8 at the beginning, so that should keep from clipping at white.

Anyway, it just seems that you have overkill here. But I cannot verify at this time.

Seems like you should get pretty much the same by

convert zelda3.JPG -evaluate multiply 0.125 ^
( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -negate -level 50%,100% ) ^
( -clone 0 -bias 50% -convolve "1,2,1,0,0,0,-1,-2,-1" -solarize 50% -negate -level 50%,100% ) ^
-delete 0 -compose plus -composite zelda_4_4.png

or

convert zelda3.JPG -evaluate multiply 0.125 ^
( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -level 0,50% ) ^
( -clone 0 -bias 50% -convolve "1,2,1,0,0,0,-1,-2,-1" -solarize 50% -level 0,50% ) ^
-delete 0 -compose plus -composite zelda_4_4.png

Either of these should be about like doing ( abs(X) + abs(Y) )/8

Sorry I cannot test now while in HDRI.
HugoRune
Posts: 90
Joined: 2009-03-11T02:45:12-07:00
Authentication code: 8675309

Re: using a sobel operator - edge detection

Post by HugoRune »

But why do you need the solarize etc after the -convolve. Why negate. Seems like you can just use -solarize 50% -level 0x50%, if you really need it at all. Does that work equally? I think it should.
No, that does not work (see images below). The -solarize is a negation of the brighter colors, you need a -negate to cancel it out.
If there was a "+solarize" operator that negates the darker colors, one could use that instead of "-solarize -negate"
(after -bias 50% darker colors mean "negative values", brighter colors "positive values")
So you are doing sqrt( abs(X)^2 + abs(Y)^2 ) rather than properly sqrt(X^2 + Y^2)
well, abs(x)^2 = x^2 so
sqrt( abs(X)^2 + abs(Y)^2 ) = sqrt(X^2 + Y^2)
so the abs(x) has no effect on the end result (if HDRI)

The reason why I have to do abs(X)^2, is because non-HDRI imagemagick absolutely cannot deal with negative values.

So I have to add a bias of 1/2, perform a sobel, then negate everything below 1/2, then remove the bias. This way imagemagick never sees any negative values, and since i square each pixel in the next step, mathematically there is no difference.

Code: Select all

Here is the reasoning:
- let's say 0 is black, 1 is white
- sobel can return brightness values between -400% and +400%
- anything below 0 or above 1 gets clipped immediately

So I start with
- a normal image   (all pixels have values from 0 to 1)
- multiply 1/8     (all pixels 0 to 1/8)
- bias 50%         (all pixels 1/2 to 1/2+1/8)
- convolve sobelX  (all pixels 0 ti 1)    [1/2 +/- (1/8 * 400%)]
- solarize         (all pixels 0 to 1/2)     values above 1/2 are flipped below
- negate           (all pixels 1/2 to 1)   now all values are >1/2 and unflipped
- level 50%,100%   (all pixels 0 to 1)  bias is removed
- clone & multiply (all pixels 0 to 1)    0^2=0 1^2=1
So no I have an abs(sobelX)^2 image, which is *identical* to a sobelX^2 image done on HDRI
at no point where any values below 0 or above 1, so there can be no clipping


- I do the same for sobelY
- then -compose plus sobelX^2+sobelY^2 (all pixels 0 and ?)
This could lead to clipping, but I think due to mathematical properties of the sobel operators it does not, since they cannot be both maximal in the same pixel

- gamma 2 (squareroot, no clipping here) 
Seems like you should get pretty much the same by

convert zelda3.JPG -evaluate multiply 0.125 ^
( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -negate -level 50%,100% ) ^
( -clone 0 -bias 50% -convolve "1,2,1,0,0,0,-1,-2,-1" -solarize 50% -negate -level 50%,100% ) ^
-delete 0 -compose plus -composite zelda_4_4.png
Image
or

convert zelda3.JPG -evaluate multiply 0.125 ^
( -clone 0 -bias 50% -convolve "-1,0,1,-2,0,2,-1,0,1" -solarize 50% -level 0,50% ) ^
( -clone 0 -bias 50% -convolve "1,2,1,0,0,0,-1,-2,-1" -solarize 50% -level 0,50% ) ^
-delete 0 -compose plus -composite zelda_4_4.png
This logically cannot work:
Image
The output image in the second case is almost pure white. That is because it is a combination of
sobelX= Image and sobelY= Image
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: using a sobel operator - edge detection

Post by fmw42 »

right about the bias and the solarize -negate. But my other point was that your abs and sqrt of square are redundant. That was why I suggested you either do the abs or the compose mutliply -evaluate pow 0.5. You don't need both.

Sorry I could not check things before replying, which I usually do, but I am stuck in HDRI mode for a while.
Post Reply