6

I have a 8-bit image and I want to filter it with a matrix for edge detection. My kernel matrix is

0  1  0
1 -4  1
0  1  0

For some indices it gives me a negative value. What am I supposed to with them?

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
Thunfische
  • 1,107
  • 2
  • 15
  • 35

2 Answers2

10

Your kernel is a Laplace filter. Applying it to an image yields a finite difference approximation to the Laplacian operator. The Laplace operator is not an edge detector by itself.

But you can use it as a building block for an edge detector: you need to detect the zero crossings to find edges (this is the Marr-Hildreth edge detector). To find zero crossings, you need to have negative values.

You can also use the Laplace filtered image to sharpen your image. If you subtract it from the original image, the result will be an image with sharper edges and a much crisper feel. For this, negative values are important too.

For both these applications, clamping the result of the operation, as suggested in the other answer, is wrong. That clamping sets all negative values to 0. This means there are no more zero crossings to find, so you can't find edges, and for the sharpening it means that one side of each edge will not be sharpened.

So, the best thing to do with the result of the Laplace filter is preserve the values as they are. Use a signed 16-bit integer type to store your results (I actually prefer using floating-point types, it simplifies a lot of things).

On the other hand, if you want to display the result of the Laplace filter to a screen, you will have to do something sensical with the pixel values. Common in this case is to add 128 to each pixel. This shifts the zero to a mid-grey value, shows negative values as darker, and positive values as lighter. After adding 128, values above 255 and below 0 can be clipped. You can also further stretch the values if you want to avoid clipping, for example laplace / 2 + 128.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • The idea of compressing values to avoid clipping is sound, but in this filter's case, the range is -4*255 to 4*255, so one would like to divide by 8 before adding 128 to fit inside 0..255. The best method is to use a function from a package written in a language with good quality devs (such as Julia). – Dan Getz Jan 29 '23 at 01:41
  • @Dan Few pixels will have such large values, clipping them is the right thing to do, otherwise one can’t see the meaningful information at lower intensities. The last sentence in your comment is weird. Almost like you wrote an image processing package for Julia and are trying to advertise it subtly. :D – Cris Luengo Jan 29 '23 at 01:57
  • True. Actually image arithmetic i.e. pixel arithmetic is complex. Not having careless addition of colors (with all their perceptual complexity) is a feature, not a bug. (this will also be deleted) – Dan Getz Jan 29 '23 at 02:07
  • 1
    @Dan Yes, color reproduction and management is very complicated. I have great respect for people that understand it well. I deal with images to extract information, and so often do all sorts of arithmetic on pixel values that ignore gamut, perceptual uniformity, etc. It’s a totally different goal with totally different tools. – Cris Luengo Jan 29 '23 at 02:15
1

Out of range values are extremely common in JPEG. One handles them by clamping.

If X < 0 then X := 0 ;   
If X > 255 then X := 255 ;
user3344003
  • 20,574
  • 3
  • 26
  • 62
  • 7
    If this Laplacian filter is used for edge detection, what matters are the zero crossings. By clamping, you kill information on where the negatives are. Better to shift by 128 before clamping. –  Oct 30 '18 at 13:31