xGoat
More tea please.

Finding lens distortion parameters

I’ve recently found myself needing to remove some barrel distortion (a form of radial distortion) from some images. “fulla” is a tool that comes with hugin that will correct both radial distortion and chromatic aberration (which is where different wavelengths/colours are distorted by different amounts). fulla seems to be quite good, but in order to use it, you will need to know the coefficients to feed it for your particular set-up.

There’s a tool called PTOptimizer for working out the coefficients to use. I found its documentation somewhat cryptic, and so I thought I’d attempt to save some other people some time by describing what I did to calculate the coefficients to pass to fulla.

  1. Take a calibration photo. I drew a grid of straight lines on a piece of A3 paper and photographed it with my camera. It doesn’t matter what orientation the lines are in, just that they’re straight in the real world. You’ll want your lines to cover your image reasonably well.

  2. Trace the lines in the gimp. Various other websites will talk about using hugin, or some other tool to do the tracing. In the end I found it easiest to draw a path in gimp over each line, then export all the paths from gimp (right click on a path and click “Export path…”).

  3. Convert your trace into a “PTO” file. PTOptimizer needs to be fed these paths along with some other parameters in a file of the format described here. I wrote a short python script to convert the SVG gimp exported into a PTO file. An important piece of information that took me forever to work out was how to encode this into some “c lines” properly. Each c-line only takes two control points (the points from the lines you drew earlier). So, there should be multiple c-lines per line from your image. These c-lines are grouped together by their type. The type is encoded in the “tN” field of the c-line, where N is an integer of 3 or above.

    For example, here are two sets of c-lines describing two calibration lines:

    # First calibration line:
    c n0 N0 x937.55 y2301.82 X936.36 Y2268.73 t4
    c n0 N0 x936.36 y2245.09 X935.55 Y2200.09 t4
    #...
    c n0 N0 x938.45 y278.27 X939.36 Y230.73 t4
    c n0 N0 x940.55 y184.55 X941.91 Y105.82 t4
    
    # Second calibration line:
    c n0 N0 x2020.45 y121.91 X2022.55 Y170.55 t5
    c n0 N0 x2026.18 y239.73 X2029.45 Y309.27 t5
    #...
    c n0 N0 x2100.56 y2091.75 X2102.31 Y2141.00 t5
    c n0 N0 x2104.44 y2202.69 X2105.62 Y2251.25 t5
    

  4. Fill out the PTO header. There are some other pieces of information that PTOptimizer needs. The docs for this are mostly sufficient. Make sure you set a, b, and c to be non-zero, otherwise you’ll find (as I did) that the optimiser doesn’t get anywhere. Here’s an example header:

    # The width, height, and field-of-view of our image
    p f0 w3000 h4759 v94.04
    
    # Input image information -- importantly a, b, c are non-zero
    i w3456 h2304 f0 v94.04 a0.001 b0.001 c0.001
    
    #We want the a, b, and c parameters to be optimised:
    v a0 b0 c0
    
  5. Run PTOptimizer against the PTO file. It’ll do a load of things, and then write its results onto the end of the PTO file you gave it. Dig around in there to find a line that looks like this:
    # Polynomial Coefficients: a   -0.000923 (*); b   -0.013905 (*); c   -0.004376 (*)
    
  6. Calculate the d coefficient. According to the panotools lens correction model, this should be 1-(a+b+c).
  7. Construct a fulla command line. Take the a, b, c, and d values you’ve got and stick them into fulla:
    fulla -g -0.000923:-0.013905:-0.004376:1.019204 myfile.jpg -o somewhere.jpg
    

    I’d run your calibration image through it to see how straight the lines get.

For chromatic aberration correction, see this page.

Job done.

Posted at 12:32 am on Wednesday 5th December 2012

Site by Robert Spanton. © 2008 - 2011