Calculating lens transversal chromatic aberration

Hugin uses a relatively complex model for describing transversal chromatic aberrations (TCA for short). This is a fourth order polynomial:

Rd = a * Ru^4 + b * Ru^3 + c * Ru^2 + v * Ru

Since Lensfun targets more or less realtime image processing, I decided to use a simpler model that is enough for practical applications, with the a coefficient always supposed to be zero:

Rd = b * Ru^3 + c * Ru^2 + v * Ru

Now the good news is that Hugin has a tool that will automatically compute for you all of the parameters for correcting TCA, and will do that based on a single image! This tool is called tca_correct.

So, you just take a sample image at a distance of at least 8 metres (make sure it has a lot of high-contrast objects on it, for example you could make a photo of a white building with dark windows or something like that). Then generate a TIFF with the sensor's original linear RGB colour space. For example, if you use dcraw, call it like this:

dcraw -4 -o 0 -M myimage.RAW

Now just run tca_correct on it like this:

tca_correct -o bcv myimage.tiff

It will print a lot of inside information, and end with something like this:

-r 0.0000000:-0.0004356:0.0011037:0.9994399 -b 0.0000000:-0.0002375:-0.0000052:1.0006518

The format of the above line is "-r a,b,c,v -b a,b,c,v": first set for the red channel, second set for the blue channel (green channel is left in place during TCA corrections).

If you have several shots made at the same focal length (aperture shouldn't matter for TCA), you can run tca_correct several times. You will most probably get different results every time, so choose the result that looks like average. But don't try to mix coefficients from different images or average them randomly!

Also, note that usually it is enough to provide only the b and v parameters (e.g. limit to a third-order polynomial). In this case Lensfun will use a optimized code path and avoid computing two square roots per pixel, so its worth to try first a simpler model:

tca_correct -o bv myimage.tiff
...
-r 0.0000000:0.0000916:0.0000000:0.9999904 -b 0.0000000:-0.0002397:0.0000000:1.0006490

Now let's add that to our lens calibration data:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
        <distortion model="poly3" focal="15" k1="-0.00774" />
        <distortion model="poly3" focal="18" k1="-0.00345" />
        <distortion model="poly3" focal="21" k1="-0.00199" />
        <distortion model="poly3" focal="24" k1="0.00061" />
        <tca model="poly3" focal="12" br="0.0000916" vr="0.9999904" bb="-0.0002397" vb="1.0006490" />
    </calibration>
</lens>

Repeat this step for all calibrated focal lengths. In the end you'll have something like this:

<lens>
    <maker>Pentax</maker>
    <model>SMC PENTAX DA 12-24mm F/4 ED AL IF</model>
    <mount>Pentax KAF2</mount>
    <cropfactor>1.5</cropfactor>
    <calibration>
        <distortion model="poly3" focal="12" k1="-0.01919" />
        <distortion model="poly3" focal="15" k1="-0.00774" />
        <distortion model="poly3" focal="18" k1="-0.00345" />
        <distortion model="poly3" focal="21" k1="-0.00199" />
        <distortion model="poly3" focal="24" k1="0.00061" />
        <tca model="poly3" focal="12" br="0.0000916" vr="0.9999904" bb="-0.0002397" vb="1.0006490" />
        <tca model="poly3" focal="15" br="0.0001253" vr="0.9999184" bb="-0.0002858" vb="1.0008241" />
        <tca model="poly3" focal="18" br="0.0001204" vr="0.9999075" bb="-0.0001990" vb="1.0006258" />
        <tca model="poly3" focal="21" br="0.0001063" vr="0.9999562" bb="-0.0001477" vb="1.0005692" />
        <tca model="poly3" focal="24" br="0.0000982" vr="1.0000005" bb="-0.0001137" vb="1.0004136" />
    </calibration>
</lens>