supplierdeeply

Bug in DOF calculations at high focal length

  • 10 Replies
  • 2004 Views
*

Offline DBgit

  • *
  • 14
Bug in DOF calculations at high focal length
« on: 13 / April / 2011, 09:33:21 »
Advertisements
Hi

I stumbled on bug in the DOF calculation while writing a DOF-based focus stack script for a S5. I found that the DOF values calculated by CHDK are clearly wrong when the focal length is higher than ~50mm (I observed this both for S5 and SX30 cameras). For example, both the "near limit" and "far limit" are always displayed as "inf" around 50mm. As discussed here (and see the quote below), I think that the problem comes from the overflow of a 16bit integer during the calculation of the hyperfocal distance. Indeed, the problem seems to appear exactly when the hyperfocal distance reaches about 65536 mm, which occurs at roughly a focal length of 50mm for compact cameras. While having the hyperfocal displayed as "inf" above 65.5 m is reasonable, the near and far limits of DOF are calculated from the value of the hyperfocal distance in the source code (/trunk/core/gui_osd.c). Therefore, the overflow of the hyperfocal distance also corrupts the "near limit" and "far limit".

I suspect that this problem affects all cameras, but it is obviously visible only for superzooms (or cameras with focal length higher than 50mm). This bug is a problem because it prevents using CHDK to make universal DOF-based focus stacks...

Did anyone else observe this problem?

Quote
BTW, I took a deeper look at the values of DOF given by CHDK. I think I found what is the problem by playing with a SX30IS of one of my friend. The SX30IS shows exactly the same bug in DOF calculation as the S5IS, so this might be a bug affecting all cameras. I found that the DOF calculations are accurate until the value of the hyperfocal distance reaches about 65536 (2^16). This occurs only at focal length higher than about 50 mm for compact cameras. After that, the value returned by the function get_hyp_dist becomes negative (16 bit int overflow...). This is a problem because, in the source code (/trunk/core/gui_osd.c), the near and far limits of DOF are calculated from the value of the hyperfocal distance. This explains why the CHDK DOF calculation returns the value "inf" for near and far limits at a focal length higher than 50mm. Note that, as the focal length is increased further, the value of hyperfocal distance eventually goes back to positive again (around a focal length of about 65mm). The values of near and far limit of DOF are then not returned as "inf" anymore, but they are clearly not good anyway. For SX30IS, the hyperfocal distance goes back and forth from negative to positive 5 or 6 times when the camera is zoomed in from 4.3 mm to 150.5 mm.

Edit: Oups. I just found that this bug (or a very similar one) has already been submitted to the bug tracker here .
« Last Edit: 15 / April / 2011, 22:06:54 by DBgit »

*

Offline reyalp

  • ******
  • 10055
Re: Bug in DOF calculations at high focal length
« Reply #1 on: 16 / April / 2011, 14:23:50 »
Thanks for the reminder of that.

Patches welcome ;)
Don't forget what the H stands for.

*

Online philmoz

  • *****
  • 2936
    • Photos
Re: Bug in DOF calculations at high focal length
« Reply #2 on: 16 / April / 2011, 18:13:37 »
For SX30IS, the hyperfocal distance goes back and forth from negative to positive 5 or 6 times when the camera is zoomed in from 4.3 mm to 150.5 mm.

On the SX30 set the 'Use EXIF Subj. Dist. (PC65)' option in the DOF calculator.
This will stop the value jumping around and you should only get the 'inf' for near and far limit when the focus is at infinity.

Phil.
CHDK ports:
  sx30is (1.00c, 1.00h, 1.00l, 1.00n & 1.00p)
  g12 (1.00c, 1.00e, 1.00f & 1.00g)
  sx130is (1.01d & 1.01f)
  ixus310hs (1.00a & 1.01a)
  sx40hs (1.00d, 1.00g & 1.00i)
  g1x (1.00e, 1.00f & 1.00g)

*

Offline DBgit

  • *
  • 14
Re: Bug in DOF calculations at high focal length
« Reply #3 on: 16 / April / 2011, 22:14:48 »
Quote
On the SX30 set the 'Use EXIF Subj. Dist. (PC65)' option in the DOF calculator.

Thanks for the trick. I'll test it as soon as I can get a hand on a SX30. However, I just tried on the S5 and enabling the  'Use EXIF Subj. Dist. (PC65)' option doesn't seem to change anything.  The near and far limits for DOF are still always displayed as "inf" at focal length is between ~50 and ~65mm.


*

Offline DBgit

  • *
  • 14
Patch: Bug in DOF calculations at high focal length
« Reply #4 on: 03 / May / 2011, 00:02:37 »

*

Offline reyalp

  • ******
  • 10055
Re: Bug in DOF calculations at high focal length
« Reply #5 on: 07 / May / 2011, 01:53:15 »
Thanks for the patch, I'll try to get to it this weekend. In the meantime, if any users want to provide feedback, please feel free.

We don't actually have an FPU, but emulation seems to work so it should be OK for this.

If you want to provide a patch that refactors the copy/past code into a function, that's always appreciated too.
Don't forget what the H stands for.

*

Offline DBgit

  • *
  • 14
Re: Bug in DOF calculations at high focal length
« Reply #6 on: 08 / May / 2011, 21:11:35 »
We don't actually have an FPU, but emulation seems to work so it should be OK for this.

I did not know about the lack of FPU. I just tried to change the variable type to float and it seamed to work correctly... If this creates a problem, there are obviously many more elegant way that this overflow bug could be solved. Another similar solution would be to use 64bit int (long long int) rather than float (would that be any faster?).

Also, I'm sure that all the calculations could be made entirely using 32bit int if this provides some advantages. For example, the following line (which creates an overflow at fl>46 340):
Code: [Select]
dof.hyperfocal_distance=(fl*fl)/(10*circle_of_confusion*av);

...could be replaced by this:
Code: [Select]
dof.hyperfocal_distance=((fl/10)*(fl/10))/(10*circle_of_confusion*av)*100;
which should work up to a focal length of about 460 000 (460 mm). This should be OK for any compact camera, but could be a problem if this code is ever used for a SLR with a long telephoto...

Anyway, as this was my first try to patch CHDK code, I tried to keep the changes as small as possible...

« Last Edit: 08 / May / 2011, 21:14:40 by DBgit »

*

Offline reyalp

  • ******
  • 10055
Re: Bug in DOF calculations at high focal length
« Reply #7 on: 14 / May / 2011, 22:17:34 »
I've added this in changeset 1187. There's a lot in that area (pre-existing, not your changes) that could be cleaned up, but I didn't want to get into it right now.

It looks like chdkde also implemented some of this in changeset  632.

Don't forget what the H stands for.


Re: Bug in DOF calculations at high focal length
« Reply #8 on: 16 / May / 2011, 06:25:38 »
In fact, this is really bad solution.
As reyalp mentioned - there is no hardware FPU.
All FPU operations are implemented using library functions from libgcc, and they are very complex (you can look at gcc sources).
It would be much better to use 64-bit int - this will produce much better code.
But I think the best solution is something like this:
/*
   circle of confusion is usually 6, let assume maximum value of 30 (Canon 1Ds Mark III), for future - assume limit of 100
   av - maximum value is 10 (f/32), let assume possible (but impossible :) ) value of 16 (f/256)
   so maximum value of 10*circle_of_confusion*av will be 16000, round to power of 2 = 16384
*/
Code: (c) [Select]
if(fl<16384) dof.hyperfocal_distance=(fl*fl)/(10*circle_of_confusion*av);
else dof.hyperfocal_distance=fl*(fl/(10*circle_of_confusion*av));

*

Offline DBgit

  • *
  • 14
Re: Bug in DOF calculations at high focal length
« Reply #9 on: 16 / May / 2011, 22:09:31 »
I agree that float might not be the best solution to solve the problem and that using 64-bit int is probably better. On the other hand, this part of the code does not appear to be very cpu intensive anyway, so I'm not sure that it makes any visible difference...

   av - maximum value is 10 (f/32), let assume possible (but impossible :) ) value of 16 (f/256)
My understanding is that, in this part of the code, the value taken by the variable av is the actual F# multiplied by 100 (i.e., at F2.7 we have av=270, etc.).

A solution should also be found for the overflow occurring at this line for large subject distances:
Code: [Select]
m=dof.hyperfocal_distance*dof.subject_distance

 

Related Topics