3

how does ImageFilter in PIL normalize the pixel values(not the kernel) between 0 and 255 after filtering with Kernel or mask?(Specially zero-summing kernel like:( -1,-1,-1,0,0,0,1,1,1 ))

my code was like:
import Image
import ImageFilter
Horiz = ImageFilter.Kernel((3, 3), (-1,-2,-1,0,0,0,1,2,1), scale=None, offset=0) #sobel mask
im_fltd = myimage.filter(Horiz)
Alok Nayak
  • 2,381
  • 22
  • 28

2 Answers2

1

The answer is in the documentation for Kernel:

If the scale argument is given, the result of applying the kernel to each pixel is divided by the scale value. The default is the sum of the kernel weights.

Edit: I did a little experimenting and discovered what happens when the scale is zero, since dividing by zero isn't going to work well. Any resulting value <= 0 becomes 0 and anything > 0 becomes 255.

In your case I'd recommend using a scale of 1 and an offset of 128 instead.

P.S. you can verify the calculation of the scale parameter by looking at the source:

    if scale is None:
        # default scale is sum of kernel
        scale = reduce(lambda a,b: a+b, kernel)
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • the thing about zero-summing kernel is that they have negative values, so they can produce negative value for a pixel,dividing them with scale still produce negative value. Here in my code, even with scale 1 or None and offset=0, PIL is producing image normalized between 0 and 255.So which normalization technique does it use? – Alok Nayak Apr 09 '13 at 18:22
  • @user1756427, I had to do some experimenting - check my edit. – Mark Ransom Apr 09 '13 at 19:13
  • yes you are right ,offset 128 helps. I did some experimenting too and and based on observation, I think two things are happening: 1) applying kernel or mask on a pixel and then scale and offset. If the result is negative(< 0), then it is assigned 0, else if it is greater than 255, then it is assigned 255. 2)kernel is applied in reverse i.e (-1,-1,-1,0,0,0,1,1,1) is applied like if it is (1,1,1,0,0,0,-1,-1,-1) – Alok Nayak Apr 10 '13 at 07:44
  • you wrote above that "Any resulting value <= 0 becomes 0 and anything > 0 becomes 255.". This should be "Any resulting value <= 0 becomes 0 and anything > 255 becomes 255.". I edited that but dont know what happened. – Alok Nayak Apr 10 '13 at 19:14
  • @user1756427, my statement is correct - any positive non-zero value (before the division by 0) becomes 255. I think what happens is that it really does do a division and -x/0 become -infinity, 0/0 becomes 0, and x/0 becomes +infinity. Then -infinity gets converted to 0 and +infinity gets converted to 255. – Mark Ransom Apr 10 '13 at 20:21
  • ,I am **_assuming_** that what happens according to this [source](http://www.imagemagick.org/Usage/convolve/#normalize) :"If the result of the addition is Zero ('0.0'), then the kernel is assumed to be a special Zero-Summing Kernel. In that case the kernel is scaled to make all positive values equal to '1.0', and by the same token, all negative values will then add up to '-1.0'." For knowing what actually happening, we have to understand the [C source code of PIL](http://svn.effbot.org/public/tags/pil-1.1.4/_imaging.c). – Alok Nayak Apr 11 '13 at 05:18
  • @user1756427 I checked the sources myself before the last update and couldn't find any evidence that a sum of `0` was treated specially. Thus my theory of -infinity and +infinity. – Mark Ransom Apr 11 '13 at 13:42
1

The above answer of Mark states his theory regarding what happens when a Zero-summing kernel is used with scale argument 0 or None or not passed/mentioned. Now talking about how PIL handles calculated pixel values after applying kernel,scale and offset, which are not in [0,255] range. My theory about how it normalizes calculated pixel value is that it simply do: Any resulting value <= 0 becomes 0 and anything > 255 becomes 255.

Alok Nayak
  • 2,381
  • 22
  • 28
  • That's a perfectly reasonable assumption, it's how most image processing operations handle out-of-range outputs. See http://codereview.stackexchange.com/questions/6502/fastest-way-to-clamp-an-integer-to-the-range-0-255 for my own example. There's another approach too, see http://stackoverflow.com/a/141943/5987 – Mark Ransom Apr 11 '13 at 19:59
  • Is clamping so obvious in Image processing that it isnt mentioned anywhere (or rarely) in PIL. Do People assume it by default? – Alok Nayak Apr 12 '13 at 14:12
  • Yes, I think that's true. It's also known as [saturating arithmetic](http://en.wikipedia.org/wiki/Saturating_arithmetic). If you've ever seen the visual results of simply truncating out of range values, you'd know why this is standard practice. – Mark Ransom Apr 12 '13 at 14:34