# Flat fielding an image with two 1-D arrays

This is more of a math questions, but I thought I had a better chance of finding a camera enthusiast with a math background here.

I've always flat fielded images using a two dimensional array with a gain for each pixel. Therefore I end up with a flat field table of A x B for a camera of A x B pixels. I recently started working with a camera that claimed that they had built in flat fielding, but the gain table they produced contains only two 1D arrays, A + B.

I was a little surprised, but I've surmised that the gain table they produce is made up of an average gain in the horizontal direction and an average gain in the vertical direction, divided by some constant. When the camera wants to flat field, it simply takes the vertical and horizontal gains based on the pixel location and multiples the raw pixel value by both gains. I tested this and it looks reasonable and the image is indeed flat fielded.

What I am looking for is the math to back up what they are doing in order to prove it to myself. If I place my origin at the center of the image and I know the image fall off is constant due to vignetting, I'd like to be able to calculate my own two 1-D arrays and just get a better understanding of the math behind the system.

Thanks!

• I don't think there's any real maths here. Just using an average for each row and an average for each column won't be as accurate as using a specific value for every pixel - but it may be good enough; how good may depend on a lot of the physics of the sensor. Commented Oct 28, 2013 at 17:21
• I understand this won't correct individual pixel response on the sensor. This method would only be used to correct the optical vignetting caused by the lens which is purely geometrical. I imagine it this way: If I took the average gain across each row and graphed it with respect to row position, the gains on the top and bottom would be highest, in the center the lowest. The same is true for columns: left and right would have the highest, center the lowest. Therefore, a corner pixel would have the highest gain, a center top would be slightly lower, etc. I just want to understand the math. :) Commented Oct 28, 2013 at 17:56
• Ultimately the result would be the same as having a 2d flat field since in order to work on the 2d array of the pixel structure you're still combining the 1d arrays into a single 2d array (even if it's at the point you apply it to the 2d image array.) The only difference is you're just not exposing it. Given that lens elements rotate you probably don't even need multiple 1d arrays, just need a single one. Commented Oct 28, 2013 at 18:04
• True, but then I'd be moving into polar coordinates which would play havoc on my x,y pixel axis. In reality, I'd like to be able to prove to myself that the gain in the x direction is independent of the gain in the y direction. As I type this, I am starting to see that I could use the Pythagorean theorem to separate out the x and y gains, but now I need to relate it to the circular fall off of the vignetting for each point across the image. I have an idea but it's going to have to sit in my mind for awhile before it's complete. Any help is still appreciated. Commented Oct 28, 2013 at 21:16
• no requirement for polar coordinates, just a mapping which brings the short side into the appropriate range from the long one. That kind of shift is trivial to implement as an algorithm. Say you have a 300x600px image and a 600px 1d correction array, when applying to the short side you start at term 150 and done. Commented Nov 1, 2013 at 16:13

You can, as user1118321 states correct vignetting using a pair of 1-D arrays provided the vignetting profile is a negative exponential  (it doesn't have to be strictly Gaussian i.e. the integral doesn't have to sum to 1). The gain to be applied at coordinates [x,y] must be of the form:

e^k(x^2 + y^2)


where k < 0, e > 1 (for a Gaussian e is the exponential constant)

If this is the case then the gain at [x,y] can be found by multiplying

e^k(x^2)


by

e^k(y^2)


as finding the product of two exponentials is simply a case of adding the exponents. So if you store the value of e^k(z^2) in an array you can look-up the value twice for x and y, multiply them and you have the value for [x,y] (you don't even need 2 arrays if the vignette is circular). If it is elliptical then the two arrays will be of the same form but will have different scaling.

However a constant linear fall-off in a circular pattern cannot be corrected using this method (unless you resort to polar coordinates, then only 1 array is needed) as it relies on the properties of exponentials.

It strikes me that the use of two 1D arrays suggests this flat fielding correction is designed to account only for amplifier variations across the pixel matrix (to reduce banding / plaid patterned noise) not to correct for vignetting.

If you're just looking to correct the vignetting, you can make a separable filter, just like you'd do with a Gaussian blur:

In addition to being circularly symmetric, the Gaussian blur can be applied to a two-dimensional image as two independent one-dimensional calculations, and so is termed separable. That is, the effect of applying the two-dimensional matrix can also be achieved by applying a series of single-dimensional Gaussian matrices in the horizontal direction, then repeating the process in the vertical direction. In computational terms, this is a useful property, since the calculation can be performed in O(w_kernel * w_image * h_image) + O(h_kernel * w_image * h_image) time (where h is height and w is width; see Big O notation), as opposed to O(w_kernel * h_kernel * w_image * h_image) for a non-separable kernel.

When you work with a blur on non-square pixels, for example, you can make the horizontal kernel wider or shorter (depending on the pixel aspect ratio). With a vignette, since it's an oval, you can do a similar thing - do a horizontal pass, then a vertical pass. In the case of a brightness or other color adjustment, it probably won't be a processing time win, since you're not sampling from multiple input pixels at each output pixel. But it might be a memory win since you have 2 small tables instead of one large one.