Accounting for diffraction in DOF

Started by garry23, April 20, 2015, 06:04:02 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

garry23

http://www.georgedouvos.com/douvos/Image_Sharpness_vs_Aperture_2.html

https://bitbucket.org/hudson/magic-lantern/pull-request/632/lensc-edited-to-account-for-diffraction-in/diff


Quote from: Original Post@Audionut

I would like to contribute, as I'm sure other photographers would like to have this 'refinement' on DoF. However, I feel my coding is rather too camera centric and I would like to add some user input (but haven't worked out how to do this yet), eg put up a sub menu, say in the focus menu, under DoF.

Bottom line: in time I hope to submit, but I need to do a bit more coding first.

Audionut

When it's out in the open, people can see it and contribute.  ;)

For menu stuff, it's probably best to look at modules.  Since these are recent, they tend to be well scattered with plain english comments.
dmilligan has created a menu.c for LUA.  Bound to be lots of good info in there.

a1ex

If I understand well, you replaced the formula used by ML with a more accurate one, so I don't see the need for a menu.

A patch is also helpful for your blog post, to give the complete picture (what exactly you changed).

Audionut


garry23

@alex

The diffraction addition is fairly simple, but it would benefit from a couple of user inputs, eg the user should be able to select the total blur, current ML uses the FF assumption of 29 microns. Some may want a more exacting number.

Also, there needs to be a test to see if the Airy limit is reached, I set this at 2 pixels, ie just over 12 microns for my 5D3, ie it will vary according to the camera, hence a user input, or a camera look up table, which I haven't worked out how to do.

I will share my simple code tweak this evening, when I return from work. As Audionut says, others can then add value.

Cheers

Licaon_Kter


garry23

@Licaon_Kter

I have created a pull request for the diffraction corrected depth of field in lens.c. Well I think I have? But having never done it before I may not have submitted things correctly ;-)

In case things don't work on the pull request, here is the replacement code, ie remove the current section in lens.c (lines 86-140) and replace with my code.

BTW I have tested it on my 5D3 against an App that also accounts for diffraction, and both compare, ie TrueDoF-Pro

/** Compute the depth of field, accounting for diffraction.
*
* See:
*      http://www.largeformatphotography.info/articles/DoFinDepth.pdf
*
* Assumes a 'generic' FF or Crop sensor, ie pixel density
*
* Makes the reasonable assumption that pupillary ratio can be ignored, ie use symmetric lens equations,
* as this only introduces a very small correction for non-macro imaging (hence what follows does
* not apply for close in macro where dof is around a (few) mm), ie approx 2NC(1+M/p)/M^2,
* where N = aperture, c = blur dia (ie coc), M = magnification and p = pupillary ratio.
*
* Hint: best to use cm in ML, rather than ft, ie more refined feedback
*
*/

static void
calc_dof(
    struct lens_info * const info
)
{
    #ifdef CONFIG_FULLFRAME
    const uint64_t        coc = 29; // Total (defocus + diffraction) blur dia in microns (FF)
    #else
    const uint64_t        coc = 19; // Total (defocus + diffraction) blur dia in microns (crop)
    #endif

// Note change 29 or 19 to more exacting standard if required. Alternatively create a user input menu

const uint64_t        fd = info->focus_dist * 10; // into mm
    const uint64_t        fl = info->focal_len; // already in mm

// If we have no aperture value then we can't compute any of this
// Also not all lenses report the focus length or distance
    if( fl == 0 || info->aperture == 0 || fd == 0 )
    {
        info->dof_near      = 0;
        info->dof_far        = 0;
        info->hyperfocal    = 0;
        return;
    }

// Set up some dof info

const uint64_t    freq = 550; // mid vis diffraction freq in nm (use 850 if IR)
const uint64_t        imag = (fd-fl)/fl; // inverse of magnification (to keep as integer)

#ifdef CONFIG_FULLFRAME
    const uint64_t       sen = 13; // sensor Airy limit test in microns
    #else
    const uint64_t       sen = 9; // sensor Airy limit test in microns
    #endif

const uint64_t       diff = (244*freq*info->aperture*(1+imag)/imag)/1000000; // Diffraction blur in microns

// Test if large aperture diffraction limit reached
    if(diff >= coc)
{

// set dof_near at 1mm to show 0 in LV
        info->dof_near       = 1;
        info->dof_far        = 1;
        return;
}

// calculate defocus only blur in microns
const uint64_t sq = (coc*coc - diff*diff);
const uint64_t coc2 = (int) sqrtf(sq); //Defocus only blur

// check if sensor Airy limit reached
if(coc2 < sen)
{

// set dof_near at 1mm to show 0 in LV
info->dof_near       = 1;
        info->dof_far        = 1;
        return;
   

const uint64_t        fl2 = fl * fl;

// Calculate hyperfocal distance H
const uint64_t H = fl + ((10000 * fl2) / (info->aperture  * coc2));
info->hyperfocal = H;
 
// Calculate near and far dofs
    info->dof_near = (fd*fl*10000)/(10000*fl + imag*info->aperture*coc2); // in mm
    if( fd >= H )
        info->dof_far = 1000 * 1000; // infinity
    else
    {
info->dof_far = (fd*fl*10000)/(10000*fl - imag*info->aperture*coc2); // in mm
      }
}



a1ex

@garry23:

I've modified the error handling part of the code, so it still shows something even if either diffraction or airy limit is reached (but with a warning). Hope I didn't break it too much :P

https://bitbucket.org/hudson/magic-lantern/commits/22dceab06cac

There is a small issue: before you reach the diffraction limit, the COC goes smaller and smaller, until it hits 0. After hitting the diffraction limit, if I'd leave COC at 0, the DOF would be reported as infinitely thin (which doesn't quite make sense to me). So, when the limit is reached, I reverted the COC to the default value (29 or 19), so it would still display the result with the old formula (which I guess it's better than nothing, but there is a discontinuity in the DOF values).

Can you suggest a better fix?

garry23

@alex

It is 'correct' that the near and far DOFs collapse, and of course as you move the aperture back and forth you reach a max of condition.

I think a 'better' solution is this:

// Test if large aperture diffraction limit reached
    if(diff >= coc)
    {
        // set dof_near to fd n LV
        info->dof_near = fd;
        info->dof_far = fd;
        return;
    }
    // calculate defocus only blur in microns
    const uint64_t sq = (coc*coc - diff*diff);
    const uint64_t coc2 = (int) sqrtf(sq); //Defocus only blur
    // check if sensor Airy limit reached
    if(coc2 < sen)
    {
        // set dof_near to fd in LV
        info->dof_near = fd;
        info->dof_far = fd;
        return;
    }


In other words, once the diffraction or sensor limit is reached, both near and far have collapsed to the focus distance.

You should not revert to the non-diffraction dof, simply report the two dofs as fd.

Hope this is clear.

garry23

@alex

Forgot to say. The 'best' way forward would be a DoF menu that had three choices:

- DoF = 0, no DoF display
- DoF = 1, DoF with out diffraction
- DoF = 2, DoF with diffraction

For DoF = 1 all you need do is put the diffraction blur in my code to 0.

This will allow the user to decide, ie photographers vs videographers.

I looked at doing this, but my coding skills are not there yet, ie playing around with menus etc.

Cheers

Audionut

Can't reply to bitbucket on my mobile (long story).

@Garry, I don't like the idea of collapsing to the focal length, as this could suggest sufficient sharpness there.  Personally I'd rather collapse everything to zero, since it's more likely the user will question the feedback.

I'll also split this topic later tonight.

garry23

@Auidonut

We may be confusing each other.

As the aperture is reduced you reach a point, past f/16 on a FF camera, where the acceptable depth of field, ie either side of the focus point, reduces to zero, this link visually helps to explain http://www.georgedouvos.com/douvos/Image_Sharpness_vs_Aperture_2.html

The ML near and far reporting is in absolute space, ie relative to the sensor, hence near and far collapse to the focus point.

If near and far were reported in relative space, ie relative to the focus point, they would collapse to zero.

Bottom line: it is correct that the near and far distances collapse to the focus point. As I say above, the best way forward would be to give the user the option of ignoring diffraction, ie near and far simply get wider relative to the focus point as you stop down.

Cheers

Garry

PS This is another great link for those wishing to understand DoF with diffraction: http://www.dl-c.com/DoF/

Audionut

Quote from: garry23 on April 28, 2015, 02:22:38 PM
The ML near and far reporting is in absolute space, ie relative to the sensor, hence near and far collapse to the focus point.

If near and far were reported in relative space, ie relative to the focus point, they would collapse to zero.

But what happens where we use an aperture that doesn't provide the level of sharpness we require.  To me, having the DOF collapse to the FP seems to suggest we may still have the required sharpness there.  I think I would rather some feedback that makes it obvious the current aperture is not providing the required sharpness.

garry23

@Audionut

THE depth of field is the ML reported ((fd-near) + (far-fd)), where near and far are the ML reported numbers.

In other words ML reports the absolute (sic), ie relative to the sensor, acceptable focus distances, either side of the focus point.

Once you have gone beyond the diffraction limit, which is when the diffraction blur is the same at the total blur, you have gone beyond the acceptable depth of field, ie the total CoC, in quadrature, of defocus and diffraction blur, you have broken out of your 'solution space'.

It is absolutely correct that the ML reported near and far distance collapse to the focus distance, the relative (to the focus distance) depth of field is zero.

Maybe one way to help your 'fears/worries' is to code in a colour change ie things go red when the near and far collapse to the fd.

But, bluntly, when I see the near and far collapse to the fd I know I am beyond the diffraction limit.

The key point is, depth of field is relative to the criteria you choose, eg total blur or CoC.

Bottom line: I've tried to incorporate the best focus reporting in ML and, bluntly, with access to compile in the cloud, I'm happy to change whatever you and Alex decide to do :-)

Cheers

Garry

PS Play around with this DoF simulator: http://www.dl-c.com/DoF/

Audionut

I understand what you are saying.  The change to red is a good one IMO, it just provides another hint of a possible problem.

Quote from: garry23 on April 29, 2015, 03:32:16 AM
But, bluntly, when I see the near and far collapse to the fd I know I am beyond the diffraction limit.

That's fine.  But you could dumb down your level of knowledge on the subject, and consider how those with less knowledge of the subject may interpret the displayed feedback. 
Either way, it's your code and ML is for power users, so.............

A wonderful contribution to the project.  Thanks.

garry23

@Audionut

Once we have it up and running in a consistent way, I would like to add some appropriate words to the user manual.

As I said to Alex, I believe the best way forward is to separate out the two methodologies, ie the original non diffraction corrected that will simply keep giving you an ever wider value fir the near and far feedback, and the correct diffraction corrected version that collapses near and far to the focus point at small apertures.

I would like to see the current commit, as tweaked by Alex, changed and will comment to him along those lines. That is give the user the option of seeing the near and far with or without diffraction.

Cheers

Garry

Audionut

The issue would be "yamlmo".

Since ML is for power users, the best way to fix yamlmo is to fine tune your diffraction code and then remove the redundant DOF feedback.  IMO.

garry23

@Auidinut

Thanks for splitting  out the DoF thread from the compile in the cloud.

I think the current nightly iteration is good start at giving ML an outstanding feature, ie diffraction corrected depth of field reporting.

I'm confident a second version will follow soon, that hopefully will give the user some control over the settings.

BTW here are some words that help explain the current version. http://www.magiclantern.fm/forum/index.php?topic=11269.msg146455#msg146455