Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Get Brackets (CHDK)
--[[
Capture 'Perfect' focus brackets, with focus overlap defined in terms of defocus (CHDK Circle of Confusion (CoC)) blur
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).
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
None means that requested exposures will only be captured at the current focus point
Additional exposure brackets may be taken at each focus step, using various schemes: 1Ev, 2Ev or 3Ev steps using -/+ or -/-- or +/++; one iso-invariant at
ISO at 800 or 1600; or one (Zero Noise) exposure at +4Ev, +3Ev or +2Ev or auto from a shadow exposure
Use Bookends to help differentiate bracket set in post (reccomended)
Option to switch LCD screen off during shooting
Script will pause and display predicted number of focus brackets and, if requested, the infinity focus distance. Do a Full Shutter press to terminate or Half Shutter to run the script.
If you get an error message, try resetting focus as this is the usual cause
Tested on an S95, G5X, G7X and a G1X
For the EOS M3 version goto: https://chdk.fandom.com/wiki/Landscape_Focus_Bracketing_:_perfect_near_to_far_focus_brackets
Rev 1.9286211
August 2020
Garry George
@chdk_version 1.5
@title Get Brackets
@subtitle Focus Stuff
# 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]
@subtitle Exposure Stuff
# delta = 0 "Exposure delta?" {None 1Ev 2Ev 3Ev 800 1600 ZN4 ZN3 ZN2 Auto}
# logic = 0 "Exposure logic?" {0/-/+ 0/-/-- 0/+/++}
# hilit = 20 "% histo HiLit" [5 30]
@subtitle Other Stuff
# delay = 3 "Script Delay (s)" [0 5]
# bookends = 1 "Bookends?" {No Yes}
# screen_off = 0 "Screen off?" {No Yes}
--]]
capmode = require("capmode")
set_config_value(2151,0) -- switching these two off means we are measuring distance 'from the lens': ...
set_config_value(2152,0) -- ...this is the 'best' we can do without knowing the position of the front principal plane
function restore() -- called at script termination
if done == 0 then
if x_start == -1 then refocus(1000000) else refocus(x_start) end
set_tv96_direct(s)
set_av96_direct(av)
press("shoot_half")
release("shoot_half")
if current_focus_mode ~= 1 then set_mf(0) end
if (current_mode ~= "M") then capmode.set(current_mode) end
set_lcd_display(1)
end
end
function my_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(100)
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)
done = 1
end
function set_up()
current_focus_mode = get_focus_mode()
current_mode = capmode.get_name()
press("shoot_half")
repeat sleep(10) until get_shooting()
s = get_tv96()
av = get_av96()
if (current_mode ~= "M") then capmode.set("M") end
release("shoot_half")
repeat sleep(10) until (not get_shooting())
dof = get_dofinfo()
x = dof.focus
x_start = x
xr = x
base_h = dof.hyp_dist -- that is without diffraction accounted for
fl = dof.focal_length/100 -- focal length in mmx10
if current_focus_mode ~= 1 then
print("MF mode not set")
done = 1
return false
end
if x < 0 then
print("Refocus as at infinity")
done = 1
return false
end
if x > base_h/3 and (focus_strat == 3 or focus_strat == 4 or focus_strat == 6) then
print("Too far away")
done = 1
return false
end
return true
end
function myshoot() -- works inside X_bracket function
local prevcnt=hook_shoot.count()
local rawprevcnt=hook_raw.count()
press'shoot_full_only'
repeat sleep(10) until prevcnt ~= hook_shoot.count()
release'shoot_full_only'
repeat sleep(10) until rawprevcnt ~= hook_raw.count()
end
function bookend()
set_tv96_direct(960)
set_av96_direct(get_max_av96())
local ecnt = get_exp_count()
shoot()
set_tv96_direct(s)
set_av96_direct(av)
repeat sleep(10) until (get_exp_count() ~= ecnt)
end
function refocus(xx)
set_focus(xx)
press("shoot_half")
repeat sleep(10) until get_shooting()
release("shoot_half")
repeat sleep(10) until (not get_shooting())
dof = get_dofinfo() -- update info
return dof.focus
end
function X_bracket()
press("shoot_half")
repeat sleep(10) until (get_shooting())
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()
elseif delta == 9 then
shot_histo_enable(1)
myshoot()
sleep(100)
lower = 1024 - 1024*hilit/100
test=get_histo_range(lower,1024)
step = 0
while test > 0 do
step = step + 1
set_tv96_direct(s + 96 * 2 * step)
myshoot()
sleep(100)
test=get_histo_range(lower,1024)
end
shot_histo_enable(0)
end
set_tv96_direct(s)
release("shoot_half")
repeat sleep(10) until (not get_shooting())
end
-- Main section
done = 0
if not set_up() then
return -- exit script
end
-- Calculate the overlap h
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 umx1000
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
x_stop = h/3
if focus_strat == 1 then
x = 10
xr = refocus(x)
x_stop = x_start
elseif focus_strat == 2 then
x = 10
xr = refocus(x)
elseif focus_strat == 3 then
x_stop = x_start + delx
elseif focus_strat == 4 then
x = x_start - delx
xr = refocus(x)
x_stop = x_start
elseif focus_strat == 5 then
X_bracket()
if bookends == 1 then bookend() end
my_restore()
return
elseif focus_strat == 6 then
x_stop = x_start + delx
x = x_start - delx
xr = refocus(x)
end
-- Keep all DoF calculations in request-space, to limit build up of image to image CHDK-Canon errors
if xr >= base_h then
bracks = 2
else
bracks = (-h*(xr-x_stop)+3*x_stop*xr)/(2*x_stop*xr)
if bracks < 1 then bracks = 1 end
if focus_strat == 0 or focus_strat == 2 then
bracks = bracks + 2
end
end
print("# of Brackets = "..bracks)
if focus_strat == 0 or focus_strat == 2 then
print("Inf focus @: "..(base_h*(quality+2)).."mm")
end
print("Press HS or FS")
repeat
wait_click()
until (is_key("shoot_half") or is_key("shoot_full"))
t1=os.time()
print("Bracketing Started")
if screen_off == 1 then set_lcd_display(0) end
if bookends == 1 then bookend() end
t1=(os.time()-t1)
if delay >= t1 then
t1=delay-t1
sleep(t1*1000)
end
im = 0
while (xr <= x_stop) do -- capture the focus brackets up to the required x_stop
if 2*xr >= h then break end
im=im+1
x = refocus(xr)
print(im.."/"..bracks..": "..x.."mm")
X_bracket()
xr = (xr*(h*10 - 2*fl))/(h*10 - 2*xr*10) -- estimated position of next focus bracket
end
if focus_strat == 0 or focus_strat == 2 then
temp2 = refocus(base_h) -- take shot at the base hyperfocal
im=im+1
print(im.."/"..bracks..": "..temp2.."mm")
X_bracket()
temp2 = base_h*(quality+2)
temp2 = refocus(temp2) -- take shoot at the selected infinity blur
im=im+1
print(im.."/"..bracks..": "..temp2.."mm")
X_bracket()
end
if bookends == 1 then bookend() end
my_restore()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.