Re: using a sobel operator - edge detection
Posted: 2009-08-16T21:35:11-07:00
Normalization for kernels that add to zero as in this case should be equal to 1/2 of the sum of the absolute values of the kernels (at least when no bias)
Take this image, simply a step from white to black (in normalized image values 1 to 0):
convert -size 100x100 gradient: -threshold 50% grad_thresh50.png
Now consider the filter:
1 2 1
0 0 0
-1 -2 -1
As the filter passes over the image vertically moving downward, first it has:
1 2 1 at the white (4x1)
0 0 0 at the white (0x1)
-1 -2 -1 at the white (-4x1)
Thus while it is over white it gets a sum of zero, so the result is black.
Then as the filter reaches the transition from white to black, it has
1 2 1 at the white (4x1)
0 0 0 at the white (0x1)
-1 -2 -1 at the black (-4x0)
this sums to 4 which gets clipped at 1 for nonHDRI.
Then as the filter moves one row down it has
1 2 1 at the white (4x1)
0 0 0 at the black (0x0)
-1 -2 -1 at the black (4x0)
This sums to 4 which gets clipped at 1.
Thus we get a black image with a double line of white.
Set the image normalization divisor to 1 equivalent to what IM produces as a nominal normalization per Anthony's comment about the normalizatin code:
divisor=1
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=1
Now change the divisor to a perfect normalization (divide the image by 4 which is equivalent to dividing the kernel elements by 4):
divisor=4
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=1
but once the divisor is larger than the optimal normalization value of 4. The max value starts to come down from 1:
divisor=4.1
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=0.975616
divisor=8
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=0.500008
So nominally IM will make too large a result from any edge filter. The result will be amplified by 1/2 the sum of the absolute value of the kernel elements. Small edge values will be brighter by this factor and large edge values will be clipped at 1.
So to avoid clipping at 1 in non-hdri, you need to normalize by 4 = 1/2 sum (abs value of kernel elements)=
( 1+2+1+0+0+0+1+2+1)=8/2=4
That would be the optimum automatic normalization for edge filters whose kernel elements sum to 0.
Otherwise, one has to provide kernel elements that are properly normalized by dividing the integers by 4, i.e.
0.25 0.5 0.25
0 0 0
-0.25 -0.5 -0.25
or divide the input image by 4. This provides a result that is not clipped at the white end for nonHDRI.
Take this image, simply a step from white to black (in normalized image values 1 to 0):
convert -size 100x100 gradient: -threshold 50% grad_thresh50.png
Now consider the filter:
1 2 1
0 0 0
-1 -2 -1
As the filter passes over the image vertically moving downward, first it has:
1 2 1 at the white (4x1)
0 0 0 at the white (0x1)
-1 -2 -1 at the white (-4x1)
Thus while it is over white it gets a sum of zero, so the result is black.
Then as the filter reaches the transition from white to black, it has
1 2 1 at the white (4x1)
0 0 0 at the white (0x1)
-1 -2 -1 at the black (-4x0)
this sums to 4 which gets clipped at 1 for nonHDRI.
Then as the filter moves one row down it has
1 2 1 at the white (4x1)
0 0 0 at the black (0x0)
-1 -2 -1 at the black (4x0)
This sums to 4 which gets clipped at 1.
Thus we get a black image with a double line of white.
Set the image normalization divisor to 1 equivalent to what IM produces as a nominal normalization per Anthony's comment about the normalizatin code:
divisor=1
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=1
Now change the divisor to a perfect normalization (divide the image by 4 which is equivalent to dividing the kernel elements by 4):
divisor=4
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=1
but once the divisor is larger than the optimal normalization value of 4. The max value starts to come down from 1:
divisor=4.1
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=0.975616
divisor=8
convert grad_thresh50.png -evaluate divide $divisor \
-convolve "1,2,1,0,0,0,-1,-2,-1" grad_thresh50_$divisor.png
convert grad_thresh50_$divisor.png -format "min=%[fx:minima]; max=%[fx:maxima]" info:
min=0; max=0.500008
So nominally IM will make too large a result from any edge filter. The result will be amplified by 1/2 the sum of the absolute value of the kernel elements. Small edge values will be brighter by this factor and large edge values will be clipped at 1.
So to avoid clipping at 1 in non-hdri, you need to normalize by 4 = 1/2 sum (abs value of kernel elements)=
( 1+2+1+0+0+0+1+2+1)=8/2=4
That would be the optimum automatic normalization for edge filters whose kernel elements sum to 0.
Otherwise, one has to provide kernel elements that are properly normalized by dividing the integers by 4, i.e.
0.25 0.5 0.25
0 0 0
-0.25 -0.5 -0.25
or divide the input image by 4. This provides a result that is not clipped at the white end for nonHDRI.