Last active
January 13, 2020 22:15
-
-
Save pigeonhill/7056282940415f7d99e0cc8688f48a0d to your computer and use it in GitHub Desktop.
CHDK Get Focus Script Rev 2
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
--[[ | |
@title Get Brackets | |
Capture 'Perfect' focus brackets, with focus overlap defined in terms of defocus (CHDK Circle of Confusion (CoC)) blur | |
Plus option of additional exposure brackets at each focus step, using various logic: 1Ev, 2Ev or 3Ev using -/+ or -/-- or +/++; one iso-invariant at | |
ISO at 800 or 1600; or one (Zero Noise) exposure at 4Ev, 3Ev or 2Ev | |
Focus bracketing strategies are: current position to blur-defined infinity (X2Inf); min camera focus to current position (Min2X), min camera focus to blur-defined infinity (Min2Inf); | |
current position to a delta x ahead of the current position (X2DelX); from a delta x in front of the current position to the current position (-DelX2X); | |
from a delta x in front of the current position to a delta x ahead of the current position (-D2+D). | |
None means that requested exposures will only be captured at the current focus point | |
Overlap, ie bracket to bracket focus insurance, is definded in terms of the defocus (CoC) blur, eg CoC/2 means focus brackets 'touch' at a blur of CoC/2. | |
Where as diff means that the defocus blur and the diffraction blur, taken in quadrature, equals the CHDK CoC value | |
Unless, under focus strategy, none is selected or the delX option is selected the script will take three focus brackets, even if initial focus is beyond the defocus hyperfocal (H), | |
ie at H/3, at H and at the blur-based infinity, which means DoF will go from H/4 to infinity. Thus focusing is not critical, just ensure focus is beyond H (+ have CHDK show focus & H) | |
Use Bookends to help differentiate bracket set in post | |
Option to switch LCD screen off during shooting | |
Rev 1.7 | |
Jan 2020 | |
Tested on a G7X and G1X | |
Garry George | |
@chdk_version 1.5 | |
# focus_strat = 0 "Focus logic?" {X2Inf Min2X Min2Inf X2DelX -DelX2X None -D2+D} | |
# overlap = 0 "Overlap at" {CoC 2CoC/3 CoC/2 diff} | |
# quality = 2 "Infinity quality?" {CoC/2 CoC/3 CoC/4} | |
# delx = 10 "Focus delta (mm)" [5 100] | |
# delta = 0 "Exposure delta?" {None 1Ev 2Ev 3Ev 800 1600 ZN4 ZN3 ZN2} | |
# logic = 0 "Exposure logic?" {0/-/+ 0/-/-- 0/+/++} | |
# delay = 3 "Script Delay (s)" [0 5] | |
# bookends = 1 "Bookends?" {No Yes} | |
# screen_off = 1 "Screen off?" {No Yes} | |
# num_braks = 10 "Max num of brackets" [5 20] | |
--]] | |
capmode = require("capmode") | |
function restore() | |
if x_start == -1 then refocus(1000000) else refocus(x_start) end | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
press("shoot_half") | |
repeat sleep(10) until get_shooting() | |
sleep(500) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
if current_focus_mode ~= 1 then set_mf(0) end | |
if (current_mode ~= "M") then capmode.set(current_mode) end | |
set_lcd_display(1) | |
exit_alt() | |
end | |
function set_up() | |
current_focus_mode = get_focus_mode() | |
current_mode = capmode.get_name() | |
if current_focus_mode ~= 1 then set_mf(1) end | |
dof = get_dofinfo() | |
x = dof.focus | |
x_start = x | |
last_x = x | |
base_h = dof.hyp_dist -- that is without diffraction accounted for | |
fl = dof.focal_length/100 | |
s = get_tv96() | |
av = get_av96() | |
if (current_mode ~= "M") then capmode.set("M") end | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
press("shoot_half") | |
repeat sleep(10) until get_shooting() | |
sleep(500) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
return true | |
end | |
function myshoot() -- works inside X_bracket function | |
shoot() | |
end | |
function bookend() | |
set_tv96_direct(960) | |
set_av96_direct(640) | |
local ecnt = get_exp_count() | |
myshoot() | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
press("shoot_half") | |
repeat sleep(10) until get_shooting() | |
sleep(500) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
end | |
function refocus(xx) | |
set_focus(xx) | |
dof = get_dofinfo() -- update info | |
end | |
function X_bracket() | |
set_tv96_direct(s) | |
if delta == 0 then | |
myshoot() | |
elseif delta < 4 and logic == 0 then | |
myshoot() | |
set_tv96_direct(s-96*delta) | |
myshoot() | |
set_tv96_direct(s+96*delta) | |
myshoot() | |
elseif delta < 4 and logic == 1 then | |
myshoot() | |
set_tv96_direct(s+96*delta) | |
myshoot() | |
set_tv96_direct(s+2*96*delta) | |
myshoot() | |
elseif delta < 4 and logic == 2 then | |
myshoot() | |
set_tv96_direct(s-96*delta) | |
myshoot() | |
set_tv96_direct(s-2*96*delta) | |
myshoot() | |
elseif delta == 4 then | |
local iso = get_sv96() | |
myshoot() | |
set_sv96(sv96_market_to_real(iso_to_sv96(800))) | |
myshoot() | |
set_sv96(iso) | |
elseif delta == 5 then | |
local iso = get_sv96() | |
myshoot() | |
set_sv96(sv96_market_to_real(iso_to_sv96(1600))) | |
myshoot() | |
set_sv96(iso) | |
elseif delta == 6 then | |
myshoot() | |
set_tv96_direct(s-96*4) | |
myshoot() | |
elseif delta == 7 then | |
myshoot() | |
set_tv96_direct(s-96*3) | |
myshoot() | |
elseif delta == 8 then | |
myshoot() | |
set_tv96_direct(s-96*2) | |
myshoot() | |
end | |
set_tv96_direct(s) | |
end | |
-- Main section | |
if not set_up() then -- at the moment set_up() always returns true ;-) | |
restore() | |
return -- exit script | |
end | |
if screen_off == 1 then set_lcd_display(0) end | |
h = base_h -- no overlap case: brackets 'touch' at CHDK CoC | |
if overlap == 1 then -- adjust h to achieve the requested overlap, ie 'touching' at 2*CoC/3 or CoC/2 or at the diffraction aware defocus blur | |
h = (h*3)/2 | |
elseif overlap == 2 then | |
h = 2*h | |
elseif overlap == 3 then -- use diffraction aware overlap: Assume CHDK CoC is total blur, formed in quadrature from defocus and diffraction blurs | |
temp1 = 1000*dof.coc -- total blur set up for imath | |
temp2 = (1342*dof.aperture)/1000 -- set up for imath. From diff_blur = 2.44*0.55*N (um) | |
if temp1 > temp2 then -- can use diffraction aware overlap | |
temp = imath.sqrt(imath.mul(temp1,temp1) - imath.mul(temp2,temp2)) -- diffraction aware defocus blur | |
temp2 = imath.div(temp1,temp) | |
if temp2 > 3000 then | |
h = 3*h | |
else | |
h = (h*temp2)/1000 | |
end | |
else -- diff blur > total blur | |
h = 3*h | |
end | |
end | |
if (1 + (h/x))/2 > num_braks then -- too many brackets needed | |
print("Too many brackets needed") | |
restore() | |
return | |
end | |
sleep(delay*1000) | |
if bookends == 1 then bookend() end | |
x_stop = h/3 | |
if x == -1 then | |
-- skip the other checks | |
elseif focus_strat == 1 then | |
x = 0 | |
x_stop = x_start | |
elseif focus_strat == 2 then | |
x = 0 | |
elseif focus_strat == 3 then | |
x_stop = x_start + delx | |
elseif focus_strat == 4 then | |
x = x_start - delx | |
x_stop = x_start | |
elseif focus_strat == 5 then | |
x_stop = x_start | |
elseif focus_strat == 6 then | |
x_stop = x_start + delx | |
x = x_start - delx | |
end | |
while (x < x_stop) and focus_strat ~= 5 and x_start ~= -1 do -- capture the focus brackets up to the required x_stop | |
refocus(x) | |
X_bracket() | |
x = dof.focus -- get actual x moved by cam | |
last_x = x | |
x = (x*(h*10 - 2*fl))/(h*10 - 2*x*10) -- position of next focus bracket | |
if x <= last_x then -- can't continue | |
print("breaking") | |
break | |
end | |
end | |
if x ~= x_stop then refocus(x_stop) end | |
X_bracket() | |
if focus_strat == 0 or focus_strat == 2 then | |
refocus(h) -- take shot at h | |
X_bracket() | |
temp2 = h*(quality+2) | |
refocus(temp2) -- take shoot at infinity blur quality | |
X_bracket() | |
end | |
if bookends == 1 then bookend() end | |
restore() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment