Depth of Field Info
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
DOFI | |
Depth of Feild Info script | |
This script dynamically displays (in the ML top bar) the current infinity defocus blur, diffraction blur and the total blur at infinity. | |
The script visually shows the overlap status to aid focus bracketing: green means a positive overlap and red a focus gap between the current focus and the last image taken. | |
Yellow means the current focus is the same as the last image captured. | |
Changing aperature or focal length will reset DOFI. | |
Also exposing the ML menu will reset DOFI. | |
Augmented reality option shows the hyperfocal position as well as the focus. Set tripod height. | |
The ML CoC (total blur) is used as the focus overlap criterion. | |
A thin lens model is assumed, with the lens principal plane positioned at f(1+m) from the sensor, ie magnification is estimated from the TL model: so don't use the script for macro. | |
In AR mode select the correct format and the tripod/camera height above the ground plane. The ground plane is assumed to be parallel to the lens axis. | |
AR mode shows 3*H, H (with a yellow dot), H/3, H/5 and H/7, as well as the focus which will be red if focus is less than H, green if greater than H, or am orange dot if > 3*H | |
Release 0.75 | |
March 2020 | |
Garry George | |
photography.grayheron.net | |
--]] | |
require("config") | |
infinity = 655000 -- trap ML reported infinity | |
f = lens.focal_length | |
x = lens.focus_distance | |
a = camera.aperture.value | |
ML_blur = menu.get("DOF Settings","Circle of Confusion",0) -- this is the overlap blur | |
H = 0 | |
m = 0 | |
r = 0 | |
last_H = H | |
ndof = 0 | |
fdof = 0 | |
infinity_blur = 0 | |
diff_blur = 0 | |
total_blur = 0 | |
blurs = "" | |
num = 0 | |
u = 0 | |
last_f = f | |
last_x = x | |
last_a = a | |
last_ndof = ndof | |
last_fdof = fdof | |
last_lens_0 = 0 | |
lens_0 = 0 | |
card_count = dryos.shooting_card.file_number | |
CON = "ON" | |
COFF = "OFF" | |
image_taken = false -- that is at least one has been taken | |
show = true | |
freq = 0.550 -- 0.550 for visible band photography or 0.850 for IR (or another frequency to suit your sensor conversion) | |
function my_display(text,time,x_pos,y_pos) | |
text = string.rep("\n",y_pos)..string.rep(" ",x_pos)..text | |
display.notify_box(text,time*1000) | |
end | |
if (x==0 or a==0 or f==0) then | |
my_display("Can't use DOFI",2,0,0) | |
return | |
end | |
function myround(nu) return tostring(math.floor(nu+0.5)) end | |
function update() | |
if f ~= last_f or a ~= last_a or menu.visible then -- reset | |
image_taken = false | |
card_count = dryos.shooting_card.file_number | |
last_f = lens.focal_length | |
last_a = camera.aperture.value | |
end | |
if card_count ~= dryos.shooting_card.file_number then | |
last_f = f | |
last_x = x | |
last_lens_0 = lens_0 | |
last_a = a | |
last_H = H | |
last_ndof = ndof | |
last_fdof = fdof | |
card_count = dryos.shooting_card.file_number | |
image_taken = true | |
end | |
f = lens.focal_length | |
ML_blur = menu.get("DOF Settings","Circle of Confusion",0) | |
x = lens.focus_distance -- supplied by Canon from sensor | |
if x < infinity then | |
r = math.sqrt((x*x)/4 - f*x) | |
m = (x - 2*r)/(x + 2*r) | |
else | |
m = 0 | |
end | |
lens_0 = f * (1.0 + m) | |
u = x - lens_0 | |
a = camera.aperture.value | |
H = f + (1000*f*f)/(a*ML_blur) | |
ndof = (H*u-f*f)/(H+u-2*f) | |
if u < H then | |
fdof = (H*u-2*f*u+f*f)/(H-u) | |
else | |
fdof = infinity | |
end | |
num = math.ceil((1 + (H/u))/2) -- estimate of number of focus brackets | |
if u > H then num = 1 end | |
infinity_blur = ML_blur*(H-f)/(x-lens_0-f) | |
diff_blur = 2.44 * a * freq | |
total_blur = math.sqrt(infinity_blur*infinity_blur + diff_blur*diff_blur) | |
blurs = myround(infinity_blur).."/"..myround(diff_blur).."/"..myround(total_blur) | |
if x > infinity then | |
blurs = "INF: "..blurs | |
else | |
blurs = "#"..num..": "..blurs | |
end | |
end | |
function show_ar() | |
local scale = 60 | |
local radmax = 10 | |
local radmin = 2 | |
display.rect(360-scale/2, 240-radmax, scale, 480,COLOR.TRANSPARENT,COLOR.TRANSPARENT) | |
if x < 7*H then | |
local tri_h = 10*DOFI_Menu.submenu["Tripod Height"].value -- in mm | |
local sensor = 24 -- for full frame cam | |
if DOFI_Menu.submenu["Format?"].value == "APS-C" then sensor = sensor/1.6 end | |
local x0 = 2*f*tri_h/sensor | |
display.circle (360,240,4,COLOR.BLACK,COLOR.BLACK) | |
display.line(360-scale/2,240,360+scale/2,240,COLOR.BLACK) | |
display.line(360,480,360,240,COLOR.YELLOW) | |
local hy = 240 + (480*tri_h*(1+f/(3*H))*f)/(sensor*3*H) | |
local hw0= scale/2 | |
local hw = hw0*x0/(3*H) | |
if hy >= 240 and hy >= 0 then | |
display.line(360-1,480,360-1,hy,COLOR.YELLOW) | |
display.line(360+1,480,360+1,hy,COLOR.YELLOW) | |
display.line(360-hw, hy, 360+hw, hy,COLOR.YELLOW) | |
display.line(360-hw, hy-1, 360+hw, hy-1,COLOR.YELLOW) | |
display.line(360-hw, hy+1, 360+hw, hy+1,COLOR.YELLOW) | |
end | |
hy = 240 + (480*tri_h*(1+f/(H))*f)/(sensor*H) | |
hw = hw0*x0/(H) | |
local radh = radmax - ((radmax-radmin)*(H-x0))/(5*H-x0) | |
display.circle (360,hy,radh,COLOR.YELLOW,COLOR.YELLOW) | |
if hy >= 240 and hy >= 0 then | |
display.line(360-2,480,360-2,hy,COLOR.YELLOW) | |
display.line(360+2,480,360+2,hy,COLOR.YELLOW) | |
display.line(360-hw, hy, 360+hw, hy,COLOR.GREEN1) | |
display.line(360-hw, hy-1, 360+hw, hy-1,COLOR.YELLOW) | |
display.line(360-hw, hy+1, 360+hw, hy+1,COLOR.YELLOW) | |
end | |
hy = 240 + (480*tri_h*(1+f/(H/3))*f)/(sensor*H/3) | |
hw = hw0*3*x0/(H) | |
if hy >= 240 and hy >= 0 then | |
display.line(360-3,480,360-3,hy,COLOR.YELLOW) | |
display.line(360+3,480,360+3,hy,COLOR.YELLOW) | |
display.line(360-hw, hy, 360+hw, hy,COLOR.YELLOW) | |
display.line(360-hw, hy-1, 360+hw, hy-1,COLOR.YELLOW) | |
display.line(360-hw, hy+1, 360+hw, hy+1,COLOR.YELLOW) | |
end | |
hy = 240 + (480*tri_h*(1+f/(H/5))*f)/(sensor*H/5) | |
hw = hw0*5*x0/(H) | |
if hy >= 240 and hy >= 0 then | |
display.line(360-4,480,360-4,hy,COLOR.YELLOW) | |
display.line(360+4,480,360+4,hy,COLOR.YELLOW) | |
display.line(360-hw, hy, 360+hw, hy,COLOR.YELLOW) | |
display.line(360-hw, hy-1, 360+hw, hy-1,COLOR.YELLOW) | |
display.line(360-hw, hy+1, 360+hw, hy+1,COLOR.YELLOW) | |
end | |
hy = 240 + (480*tri_h*(1+f/(H/7))*f)/(sensor*H/7) | |
hw = hw0*7*x0/(H) | |
if hy >= 240 and hy >= 0 then | |
display.line(360-5,480,360-5,hy,COLOR.YELLOW) | |
display.line(360+5,480,360+5,hy,COLOR.YELLOW) | |
display.line(360-hw, hy, 360+hw, hy,COLOR.YELLOW) | |
display.line(360-hw, hy-1, 360+hw, hy-1,COLOR.YELLOW) | |
display.line(360-hw, hy+1, 360+hw, hy+1,COLOR.YELLOW) | |
end | |
display.circle (360,240,5,COLOR.BLACK,COLOR.BLACK) | |
radh = radmax - ((radmax-radmin)*(x-x0))/(5*H-x0) | |
local y = 240 + (480*tri_h*(1+f/x)*f)/(sensor*x) | |
if (x > 3*H) then | |
display.circle (360,y,radh,COLOR.ORANGE,COLOR.ORANGE) | |
elseif (x >=H) then | |
display.circle (360,y,radh,COLOR.GREEN1,COLOR.GREEN1) | |
else | |
display.circle (360,y,radh,COLOR.RED,COLOR.RED) | |
end | |
end | |
end | |
function check_stuff() | |
update() | |
if not menu.visible and lv.overlays == 2 and DOFI_Menu.submenu["AR"].value == CON then display.draw(show_ar) end | |
return true | |
end | |
DOFI_Menu = menu.new | |
{ | |
parent = "Focus", | |
name = "DOF Info", | |
help = "Helps with infinity focusing & focus bracketing", | |
depends_on = DEPENDS_ON.LIVEVIEW, | |
submenu = | |
{ | |
{name = "On/Off", | |
choices = {CON,COFF}, | |
update = function(this) | |
if this.value == "ON" then | |
show = true | |
else | |
show = false | |
end | |
end, | |
}, | |
{ | |
name = "AR", | |
help = "Switches the AR display on & off", | |
choices = {CON,COFF}, | |
}, | |
{ | |
name = "Tripod Height", | |
help = "In cm", | |
min = 10, | |
max = 300, | |
value = 65, | |
}, | |
{ | |
name = "Format?", | |
help = "Just select ;-)", | |
choices = {"Full Frame","APS-C"}, | |
}, | |
} | |
} | |
lv.info | |
{ | |
name = "DOFI", | |
value = "", | |
priority = 100, | |
update = function(this) | |
if (not show) then | |
this.value = "" | |
else | |
this.value = blurs | |
this.background = COLOR.WHITE | |
this.foreground = COLOR.BLACK | |
if image_taken then | |
if (x == last_x) then | |
this.background = COLOR.YELLOW | |
this.foreground = COLOR.BLACK | |
elseif (ndof > last_fdof) or (fdof < last_ndof) then | |
this.background = COLOR.RED | |
this.foreground = COLOR.WHITE | |
elseif (ndof < last_ndof) and (fdof > last_ndof) then | |
this.background = COLOR.GREEN1 | |
this.foreground = COLOR.BLACK | |
elseif (ndof > last_ndof) and (ndof <= last_fdof) then | |
this.background = COLOR.GREEN1 | |
this.foreground = COLOR.BLACK | |
end | |
if x > infinity then | |
this.background = COLOR.BLACK | |
this.foreground = COLOR.WHITE | |
end | |
else | |
if x > infinity then | |
this.value = blurs | |
this.background = COLOR.BLACK | |
this.foreground = COLOR.WHITE | |
end | |
end | |
end | |
end | |
} | |
event.shoot_task = check_stuff | |
config.create_from_menu(DOFI_Menu) -- keep a track of the script's menu state at camera close |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment