Saturday, April 27, 2019

Continuing the Deep Focus story


In this post I'm publishing the latest version of my Magic Lantern Lua script to achieve deep focus.

As we know, lenses are very complex things, for example, here is a cross section through the Canon 24-105 F/4L lens, showing the various individual lens element.



As can be imaged, light rays will follow a complex path, ie as exemplified by the following illustration from an arbitrary lens:


As photographers, or, more correctly, as photographers who wish to play around with a few equations, we usually make use of a few simplifying assumptions. For example, the so-called Thin Lens Model:


The simplicity of the lens equation hides some real power. For example, using various solutions, eg introducing the ideal of reproduction magnification, ie  (Image size)/(Object size) = M, we can show, using similar triangles, that the v and b distances can be stated in terms of the magnitude and the focal length and the object to image distance (x), ie:



Also photographers make use of other useful equations, like the hyperfocal equation (H), which tells us where to focus to achieve a depth of field between H/2 and infinity; and where the focus quality, in terms of (microns) of blur will be never be worse than the so-called circle of confusion (CoC).

But as we know, the Thin Lens model is hardly representative of a real lens. A better model would be to use a Thick Lens model, which may be seen as a Thin Lens model pulled apart.


However, although lens manufacturers tell us some lens specifications, eg maximum magnification, what they don't report is where the lens principal planes sit; and although there are procedures to estimate these positions, they are rather fiddly, and hence, in this script we will continue to assume a thin lens.

Typically, for viewing a 10in print from a full frame camera, at 10in away, the CoC is stated at around 30 microns. Less than this if on a crop camera, ie CoC = (CoC-FF)/Crop. 

Of course, a CoC of 30 microns is often not enough, ie because of closer scrutiny by judges; and can be more, ie web image on Facebook!

As for a minimum blur, pragmatically two sensor pixels is a reasonable limit, ie around 12 microns on my 5D3.

Knowing the CoC, the focal length and the aperture then allows us to estimate the near and far depths of field.

But as we are coding up our solution, we will seek out the ‘correct’ forms for the depths of field.

Thus the near (n) and far (F) depths of field may be written as:




For focus stacking we are seeking solutions when the far depth of field of the current image is the same as the near depth of field of the next image, as shown below:




We thus need to solve for d (note: not the same d in the Thick Lens model above), the amount to move from the current focus position, namely d in this expression:


Some would give up at this point, as it looks difficult to solve for d. However, help is at hand in the form of Wolfram Alpha, which means we can say that d is:


We now seem to have everything we need: we know our focus position (x), thanks to Canon and Magic Lantern; we know the aperture and the focal length; and we know what overlap blur we want.

So there is no confusion, we have not really solved our problem. That is we know the focus position relative to the sensor, and we know the hyperfocal, near depth of field and far depth of field, relative to the lens front principal plane. What we don't know is the position of the front principal plane relative to the sensor.

So the best we can do is assume our thin lens estimate, ie the only principal plane sits at b.

The final step is to code the above up as a ML Lua script: which I have done and which you can down load from the right, in the script list area: ML Get Focus Bracketing Script.

All you need to do is to register your lens in the script, ie name, minimum focus distance and maximum focal length (ie if it is a  zoom).

The script is a so-called Lua simple script, in that it doesn’t have a menu. To run it, simply go to the ML Scripts menu and select run.

The default script assumes a Thin Lens model, however, by commenting in one line you can experiment with using the script in a Thick Lens mode.

I have also written a help script that allows you to press one key to jump you to the ML Scripts menu. I use the RATE key on my 5D3.

The script uses the ML CoC as the required overlap (defocus) blur and to explicitly calculate H. The script does not use the ML depth of field estimates or worry about diffraction.

The script will carry out a calibration step, ie checking what direction the lens moves in, some go left and some go right when command to move towards infinity.

Once the calibration is complete, the script will pause and tell you how many brackets it estimates (+/- 1ish) it will take. At this point you can adjust the focus, aperture and focal length. You can also ETTR, assuming you have selected the ETTR SET option, ie not a long (2+ seconds) half shutter press: the text will change colour to green to indicate you are ready to stack.

The UI shows you the estimated number of brackets, the defocus, diffraction and total blurs at infinity (in microns).

You can ETTR (via SET) when the UI is being shown.

Doing a half shutter press will initiate the image capture phase and pressing any other key, will exit the script. But that key will also function as normal. On my 5D3 I exit with the RATE key.

At each focus the script can also capture exposure brackets, using the ML Advanced Bracketing. Note you can also turn on Dual ISO mode. The script will switch both of these off when it takes the bookend images (see below).

[Note: at the moment this will fail if the Advanced Bracketing chooses (sic) to use BULB mode: sorry, this is a problem in ML that I can’t fix. So, if this does occur, ensure the slowest bracket is fast enough not to trigger the BULB mode.]

The script will also take two (dark) bookend images, to help differentiate the bracketing sequence in post.

So there you have it: perfect focus and exposure bracketing, thanks to Magic Lantern Lua and making a few simplifying assumptions.

In future posts I’ll provide further insight into the script’s use and limitations, and show how to process the images in post.

Wednesday, April 17, 2019

Deep Focus Photography: User Guide for ML Get Brackets Script

Warning this is a longer and more detailed post than usual!

The above script (as usual accessible on the RHS of this site) has been written to support ‘deep focus’ photography and specifically capturing focus brackets that seamlessly cover the depth of field from infinity down to a near object of interest.

It is ‘best’ used with wide angle lens, but can be used at any focal length, with care!

Most times deep focus can be handled by focusing at, or ideally, just beyond, the hyperfocal, ie for focus insurance. If focused at the hyperfocal distance (H), the depth of field is, by definition, from H/2 to infinity.

In this case the accepted ‘focus quality’ will go from H/2 to infinity, and is mainly influenced by two dominant ‘blurs’, usually taken together in quadrature. That is, the so-called circle of confusion (CoC) criterion that you have decided to use to cover the lens defocus blur, that varies through the scene and is only zero in the plane of focus; and the diffraction blur, which is essentially the same throughout the scene, only changes with aperture and is never zero.

For Full Frame (FF) cameras the ‘accepted’ defocus CoC, ie without taking account of diffraction, is usually stated as 29 microns, so let’s call this 30 for convenience. This 30 microns CoC is based around an arm’s length viewing of a 10in print, by a person with normal eyesight. Closer scrutiny, ie by judges, and larger prints viewed close-up in gallery, will require CoCs less than 30. A billboard 30m away, less.

As for a sensible minimum defocus blur (CoC) to use; well you can’t squeeze a line pair/dot (one black + one white line) into less than two sensor pixels: so let’s pragmatically accept an absolute lower CoC of two sensor pixels, ie around 12 microns on my 5D3. Both numbers being adjusted by the crop of the camera, ie 1.6 on a Canon APS-C camera, or 12/1.6 to 30/1.6.

Accounting for diffraction complicates the above a little, but, as we will see, we can ignore diffraction if we sensibly select the defocus (Coc) blur in Magic Lantern, ie between 30 and 12 on my 5D3.

To help inform your photography, and focus bracketing, it is useful to remember the ‘Rule of 10’, which says that the hyperfocal (H) in meters (sic) is simply the focal length (FL) in mm divided by 10, IF you are at an aperture of f/10 and you assume your CoC (in microns) is the FL (in mm). As an example, assume a lens with a focal length of 16mm at an aperture of f/10. The ROT says H is simply 16/10 = 1.6m (with a CoC of 16 microns).

In general, for any lens with a focal length of, say, 30mm or less, the ROT will always give a higher quality focus than the usual hyperfocal tables; that assume a fixed 29-30 microns. Thus, shooting with a WA lens, ie less than or equal to 30mm, means that, at f/10, the depth of field will go from FL/20 to infinity, with an infinity blur (defocus CoC) of FL in microns, if you focus at the ROT-based H, ie FL/10 in meters. Also, the wider the lens, the higher the focus quality, ie the lower the infinity blur, will be using the ROT approach: all other things being equal, which there’re not , of course!

Of course, knowing the ROT (at a CoC of the FL in microns) allows one to simply adjust the ROT to account for other apertures. For example, the 16mm ROT H above, at 1.6, will be 0.8m at f/20 or 3.2m at f/5, ie ROT*(10/N), where N is the aperture. Likewise to adjust the ROT to account for different defocus CoCs, all one has to do is do some simple maths: ROT*((FL in mm)/(required CoC in microns)). Thus, our 16mm example, with a ROT H of 1.6m at a CoC of 16 microns, would have a hyperfocal of 3.2m if we used a CoC of 8 microns, ie 1.6*16/8.

Finally, we can use H, from the ROT or a table or a calculation, to estimate the number of focus brackets required to cover from our point of focus (x) to H, where x = H/m, and m is an integer between 3 and infinity. The number of brackets is simply (m + 1)/2. For example, if we need to cover a depth of field that covers from H/9 to H, ie to infinity, then m = 9 and the number of ‘perfect’ brackets would be 5 = (9 + 1)/2. If we then decided to increase the near field from H/9 to H/19, the number of brackets just double to (19 + 1)/2 = 10.

The key thing to take away from the above is: know your H and know how to use the ROT.

Let’s now assume you are focusing at less than H/2 and you still require to cover focus to infinity, ie you can’t use a single image. In this case you have various options.

You could naively follow the advice some photographers give and focus 2/3 into the scene. But then you will likely be disappointed with your result. The ‘2/3 rule’, ie depth of field is split 1/3 in front of the point of focus and 2/3 behind, is only true at H/3. So, please don’t use this ‘rule’.

You could use the depth of field scale on your lens. But many new lenses don’t have such scales and if they do, they’re not usable (an example of a useable scale on a modern, high quality lens, is the one that Irix use: BTW my 11mm Irix appears to be calibrated around a defocus CoC of the FL in microns, ie it’s a ROT scale!). Some old, manual lenses do have good depth of field scales, but you will need to calibrate/confirm they are still OK or, simply manually focus, ignoring the focus scale reporting on the lens, and then use the depth of field scale to focus bracket from your point of focus.

If you have an AF lens, and are running Magic Lantern, you could use my DoF Bar script to give you the required manual feedback for focus bracketing.

Finally, if you have an AF lens, and are running Magic Lantern, you now have the ultimate focus bracketing tool: my Get Focus Brackets script.

Once loaded in the normal way, ie turn on auto start, this script may be switched on and off under its ML Focus menu. There are three options:

  • Script ON+Bookends plus place dark image bookmarks at the start and end of the bracketing sequence, to help delineate the bracket set in post. This is the default and recommended setting;
  • Script ON will simply create the focus brackets, ie no bookmarks;
  • Script OFF means just that and that the button that runs the script is usable in its normal mode.
The script will only run if the lens is an AF one and you are in LV. If running the only feedback from the script is displayed in the top right ML bar. Here you will see one of two ‘B number’ presentations:
B=n, where n >= 3: showing the estimated number of brackets the script will take (for n>3, B = +/- 1);
B=0 means the script will not run: for whatever reason ;-) 

B=666 means diffraction is dominating, so open up the aperture

The script watches for camera changes, ie in AF setting, focal length, aperture etc.

Once you see B=n, where n >= 3, you should be confident the script will run.

The speed the script runs at is camera dependent. On my 5D3 it’s ‘zippy’ but not super fast. But IMHO, if you are on a tripod and doing land/city-scape, deep focus, photography, you should be relaxing and enjoying life. OK, if the capture is really slow, then you may have to deal with a little bracket to bracket movement – but such is life, ie it’s not perfect :-)

If you are focused beyond H/3, ie B=3, don’t worry about fine tuning focus, as the script will always take three brackets at/around H/3, H and 3*H. The 3*H shot being the infinity focus shot, generating an infinity blur of the ML CoC/3. Hence if you have an ML CoC set at 30 microns (ie full frame and less by the crop on an APS-C camera), the infinity blur will be around 10 microns = 30/3.

The script is sensitive to the ML depth of field diffraction setting as it uses the ML set hyperfocal. So, if you wish to increase the focus quality through the scene, switch on diffraction aware, however, be warned: the number of brackets needed to cover the depth of field will increase. Set diffraction aware on and play around with aperture to see the impact on B.

An alternative approach is to switch off the ML diffraction aware, ie use the Simple option, and explicitly adjust the CoC under your direct control. If you wish the brackets to overlap at 2/3 of the CoC, ie at 20 micons as opposed to the normal 30, then dial this in to the ML depth of field menu: but remember to select Simple. The following illustrates what overlap means, ie it is a fraction of the 'normal' CoC = the CoC you dial into ML:


To use the script, put the camera in M mode and Live View, and simply focus on the nearest point of interest in your scene that you wish to see in focus, ie the front of that object, using any focusing method you wish: doing this means you will have a little insurance in front of the focus.

As an aside if you are focused at a fraction of the hyperfocal, ie x = H/m, where m >= 1, the near depth of field in front of x can be estimated from H/(m.(m+1)) and behind the point of focus as H/(m.(m-1)). Thus, say, with an H of 1000mm and focused at, say, 200mm, ie m = 5, the depth of field behind the focus (ie towards the camera) is about 1000/(5*6) = 33mm; whereas in front of the point of focus, ie towards infinity, it is 1000/(5*4) = 50mm. That is, as we know, depth of field collapses as you move towards the camera and below H, and at high m the two depth of field, either side of the point of focus, converge to about H/(m^2).

Next review the B number and confirm it is acceptable, ie not too large.

Assuming composition and exposure are OK, now press the script’s trigger key. The default is the RATE key, but you can easily change this in the script. On the 5D3 the RATE key works well for me. Once running and useable, ie not switched off, this trigger key is hijacked, ie it won’t be usable in normal mode. To access it in standard mode, simply switch off the script in its menu.

The first time the script runs after every camera start up, it carries out a short calibration test to check the lens motor’s chirality, ie what direction does the lens move in when Lua lens.focus() is called. This is all transparent to the user.

Assuming all is OK, the script will then either take the first image and then refocusing and take the next etc, or first move to H/3 and then take the first image and refocus etc. At the end of the bracketing the lens will be repositioned to about where it was at the start, ie there may be small differences according to where you start the lens.

Once captured, ingest the images into your post processing environment, I’ll assume Lightroom in this post, and you will clearly see your bracketing sequences, ie delineated by bookends.

For those that like seeing data, you can then get a feel (sic) for where each image was focused, by exploring the makers data in the image’s EXIF. This can be accomplished several ways, eg using the EXIF plug in from http://regex.info/blog/lightroom-goodies/metadata-viewer or with EXIFToolsGui at http://u88.n24.queensu.ca/exiftool/forum/index.php/board,7.0.html.

Interpretation of the focus position from the EXIF is not straightforward, as Canon decided to write out two numbers: FocusDistanceUpper and FocusDistanceLower, rather than Focus. Also, there appears to be some debate as to what these Canon EXIF data mean. Until someone says something else to correct me, I suggest you assume (sic) that the focus position is in the middle of the upper and lower numbers.

Once ingested in LR you then need to merge the focus brackets. Unfortunately, you can’t do this only within LR at the moment, ie without a little help. Personally, I use one of three round trips routes:

  • LR to PhotoShop and back to LR
  • LR to Helicon Focus and back to LR
  • LR to Zerene Stacker and back to LR
For example, in Helicon Focus, which I use most of the time, I find Method B works well with the script’s seamlessly created focus brackets; and it’s pleasing to see Method B unfold in front of you, ie first the depth map, followed by the detail being added in.

You may, however, find you need to adjust some of the images, ie to remove bracket-2-bracket movement artifacts. Each of the above allows you to do this, eg via adjusting masks or clone from one image to the composite.

This post has a lot of words: so let’s finish with a test image I just took in my garden, with my 5D3 and 12-24mm Sigma lens at 19mm, with a aperture of f/11..


The camera was in M mode and I had Dual-ISO switched on. I ML ETTRed to get 1/13s. The script indicated 4 brackets would be taken, ie B=4, but remember the +/- 1 for the B number. 


I used ExifToolGui to establish the four focus distances, ie lower and upper in meters: (0.28/0.28), (0.39/0.41), (0.93/1.16) and (1.51/2.19). I had diffraction aware on in ML and the CoC was set at 30 microns.  ML stated the resultant hyperfocal was 1.27m.

Finally, the latest version of the script will always be here: https://gist.github.com/pigeonhill/d02e5d5a88516c67e929397d74af0142

Monday, April 8, 2019

Landscape Bracketing Script: Update

Because I was not content with its stability, I've withdrawn and rewritten my original CHDK Landscape Focus Bracketing script.

I've written some background on the new script here.

In addition, the link on the right of this page now points to the new script.

Here are a couple of test images I took at the weekend with the new script, using my G7X: