As we know, on the M series cameras (M3, M10 and M100) CHDK can access the Canon side, so-called, upper and lower focus values. In essence, these two values give us the best estimate of where the focus is, in cms, relative to the sensor plane, ie somewhere between the two values.
There is no way to directly find focus between the upper and lower values, without some interpolation and, critically, knowing the lens stepper motor position at the upper and lower values.
One approach, which I’ve previously discussed, is to create Focus LUTs, and use a 3 point Lagrange approach to estimate the focus. But the FLUTs can take a lot of time to set up, especially if the lens stepper motor has a lot of steps.
Another approach, eg when focus bracketing, is to keep track of the Canon upper and lower values. For example, in my Landscape Bracketing Script I use the following logic to move to a specific focus position towards infinity, say x: Firstly, keep moving one step at a time until the Canon lower distance is less than x AND the upper distance is greater than x; record the count at this position; secondly keep moving until the lower distance is equal to the last upper distance and record the count. Knowing the upper and lower distances that bound x, and the counts at those two distance, carry out a linear interpolation to move back to the required distance.
But, this approach does not work in realtime, ie moving focus (manually or by AF) and wishing to estimate focus, eg for DoF and infinity blur estimates. This is where the Thin Lens Functionalised Focus (TLFF) approach comes in.
If we use a TL model: we assume a symmetrical lens (we ignore pupil magnification); we ignore any hiatus between the front and rear principals (we have a single principal plane); and we ignore the specifics of the lens design (we assume a unit focusing model, achieved by an extension of the principal plane by mf, where m is the magnification and f the focal length.
From the TL model we know that m is given by f/(u-f), where u is the distance from the principal to the object in focus. The extension is thus (f*f)/(u-f), with the extension being zero at infinity.
To estimate the maximum extension, ie at the minimum focus distance (M), we need to know the u value at the MFD, which, in the TL model, is u@MFD = M - f(1+m) = M - f(1+f/(u-f)). In general u = x - f(1+f/(u-f)).
As a pragmatic approximation, we can ignore the mf term, which will be small relative to M or the focus distance (x), thus arriving at the following approximate model to track lens rotation, ie the stepper motor steps,: ((f*f)/(M-2f))*((C-n)/C)=(f*f)/(x-2f), where C is the total counts the stepper motor will make from the MFD to infinity; and n is the value of the stepper motor at the current focus distance. That is, the (C-n/C term models the lens helicoid mechanism.
Solving for x we simply get x = (C*M – 2*f*n)/(C-n). Thus, if we know the stepper motor count at the current focus, ie from call_event_proc('GetEFLensFocusPositionWithLensCom'), we can estimate the focus distance from the sensor. The attached plot shows the above plotted out for an 11mm lens, with a MFD at 150mm and a total step count, in this case, of 529, ie past infinity.
As an aside, it looks like the total step count varies a little between runs, ie after powering off the camera.
From experimentation, the following model functionalises things a little more: x = (C*M – 2*f*n)/(C-n) – A*n/C, where A is a tweaking/scaling variable, eg the MFD or the upper or lower Canon value at the point of focus or some other value that matches your lens.
As a proof of principle, I’ve written a Lua script to demonstrate how the above could be implemented. The script (
https://gist.github.com/pigeonhill/3656fce88badb50d258995a48840d326) is automatic in that it calculates the MFD, the total count and accounts for the count at the MFD not being zero. The script also shows how to account for zoom lenses, ie it detects a focal length change and recalibrates. Calibration is ‘near’ instantaneous. Finally, the test script provides console feedback on the estimated focus and the Canon upper and lower values, ie for comparison.
Note that the TLFF does not map to the Canon side’s lower and upper throughout the focus range. When focus bracketing this not that important, as long as one has an appropriate overlap. I will likely create another script with DoF stuff to demo this.
Is the TLFF approach, correct? No. But then again, any attempt at modelling a complex lens will be wrong: but some models are useful. The TLFF model provides focus estimates that will be ‘accurate enough’ for most situations. Until Canon provides the ‘right’ value and CHDK can access it, it could be the ‘best’ we can do on the M series cameras.
Bottom line: the Thin Lens Functionalised Focus approach allows the user to estimate focus in realtime and, more importantly, when focus bracketing. I’ll keep refining the functional algorithms, ie to see if I can get a ‘better’ match to the Canon side.