Last active
March 2, 2019 08:24
-
-
Save pigeonhill/10a43f5ba543bc758f1ce21d28981a89 to your computer and use it in GitHub Desktop.
CHDK Landscape Bracketing
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 Landscape Bracketing | |
'Perfect' focus brackets from near to blur defined 'infinity': overlap defined at a fraction of camera's CoC | |
Plus option of two additional exposure brackets at each focus step, at 1Ev, 2Ev or 3Ev using -/+ or -/-- or +/++ logic | |
More info at https://chdk.wikia.com/wiki/Landscape_Focus_Bracketing_:_perfect_near_to_far_focus_brackets | |
Camera should be in manual focus mode and M mode | |
Release 1.9985 | |
Tested on a G7X & G1X | |
(c) Garry George | |
@chdk_version 1.5 | |
@param u Focus stack mode? | |
@default u 0 | |
@values u X2Inf Mac2Inf Mac2X X2delX | |
@param g Overlap at? | |
@default g 3 | |
@values g CoC 2CoC/3 CoC/2 diff | |
@param p Exposure bracket delta? | |
@default p 0 | |
@values p None 1Ev 2Ev 3Ev 800 1600 ZN | |
@param j Exposure bracket logic? | |
@default j 0 | |
@values j 0/-/+ 0/-/-- 0/+/++ | |
@param m Delta from X (mm) | |
@default m 25 | |
@range m 1 200 | |
@param n Max number of focus brackets? | |
@default n 0 | |
@values n Inf <10 <20 <30 | |
@param c Script Delay (s) | |
@default c 3 | |
@range c 0 5 | |
@param b Bookends? | |
@default b 1 | |
@values b No Yes | |
@param q Infinity focus quality? | |
@default q 1 | |
@values q CoC/2 CoC/3 CoC/4 | |
@param v Show bracket pos? | |
@default v 1 | |
@values v No Yes | |
@param k Log? | |
@default k 0 | |
@values k No Yes | |
@param e Delete Log File? | |
@default e 0 | |
@values e No Yes | |
--]] | |
capmode = require("capmode") | |
if (capmode.get_name() ~= "M") then | |
print("Switch to M mode") | |
return -- exit script | |
end | |
if get_focus_mode() ~= 1 then | |
print("Switch to MF mode") | |
return -- exit script | |
end | |
if e == 1 then | |
local fp = io.open("A/CHDK/DATA/LBS.CFG") | |
local str = fp:read("*all") | |
fp:close() | |
temp = string.sub(str, 1, 1) | |
temp = "A/CHDK/DATA/LBS."..temp | |
fp = io.open (temp,"r") | |
if fp == nil then | |
print("No ConFig file found") | |
return | |
else | |
str = fp:read("*all") | |
fp:close() | |
if string.find(str,"e=0") == nil then | |
str = string.gsub(str,"#e=1","#e=0") | |
fp = io.open (temp,"w") | |
fp:write(str) | |
fp:close() | |
os.remove("A/CHDK/LOGS/LOG_2306.TXT") | |
print("Log File Deleted") | |
return -- exit script | |
end | |
end | |
end | |
if (get_focus() == -1) then | |
print("@ Infinity") | |
return -- exit script | |
end | |
press("shoot_half") -- get current exposure | |
t = get_tick_count() | |
repeat | |
sleep(50) | |
if get_tick_count() - t > 5000 then | |
print("Unknown Error") | |
release("shoot_half") | |
return | |
end | |
until (get_shooting() == true) | |
release("shoot_half") | |
s = get_tv96() | |
av = get_av96() | |
dof = get_dofinfo() | |
x = dof.focus | |
x_start = x | |
last_x = x | |
base_h = dof.hyp_dist | |
temp = 0 | |
temp1 = 0 | |
temp2 = 0 | |
ok = true | |
fl = dof.focal_length/100 | |
log = {} | |
count = 0 | |
ecnt = get_exp_count() | |
if u == 1 or u == 2 then -- change focus to min focus | |
set_focus((4*fl)/10) | |
press("shoot_half") | |
repeat | |
x = get_focus() | |
sleep(100) -- seems to work on G7X & G1X, may need changing on other cams | |
until x == get_focus() | |
release("shoot_half") | |
end | |
-- A few Functions | |
function myshoot() | |
ecnt = get_exp_count() | |
shoot() | |
end | |
function bookend() | |
if b == 1 then | |
set_tv96(960) | |
set_av96(640) | |
myshoot() | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
repeat sleep(20) until(get_exp_count()~=ecnt) | |
end | |
end | |
function refocus(xx) | |
local dis = 0 | |
set_focus(xx) | |
press("shoot_half") | |
repeat | |
dis = get_focus() | |
sleep(200) -- seems to work on G7X & G1X, may need changing on other cams | |
until dis == get_focus() | |
release("shoot_half") | |
end | |
function X_bracket() | |
set_tv96_direct(s) | |
count = count + 1 | |
if p == 0 then | |
myshoot() | |
elseif p < 4 and j == 0 then | |
myshoot() | |
set_tv96_direct(s-96*p) | |
myshoot() | |
set_tv96_direct(s+96*p) | |
myshoot() | |
elseif p < 4 and j == 1 then | |
myshoot() | |
set_tv96_direct(s+96*p) | |
myshoot() | |
set_tv96_direct(s+2*96*p) | |
myshoot() | |
elseif p < 4 and j == 2 then | |
myshoot() | |
set_tv96_direct(s-96*p) | |
myshoot() | |
set_tv96_direct(s-2*96*p) | |
myshoot() | |
elseif p == 4 then | |
local iso = get_sv96() | |
set_sv96(sv96_market_to_real(iso_to_sv96(100))) | |
myshoot() | |
set_sv96(sv96_market_to_real(iso_to_sv96(800))) | |
myshoot() | |
set_sv96(iso) | |
elseif p == 5 then | |
local iso = get_sv96() | |
set_sv96(sv96_market_to_real(iso_to_sv96(100))) | |
myshoot() | |
set_sv96(sv96_market_to_real(iso_to_sv96(1600))) | |
myshoot() | |
set_sv96(iso) | |
elseif p == 6 then | |
myshoot() | |
set_tv96_direct(s-96*4) | |
myshoot() | |
end | |
set_tv96_direct(s) | |
end | |
h = base_h -- no overlap case: brackets 'touch' at CHDK CoC | |
if g == 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 g == 2 then | |
h = 2*h | |
elseif g == 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 | |
print("Warning: High Diff: using CoC/3") | |
else | |
h = (h*temp2)/1000 | |
end | |
else -- diff blur > total blur | |
h = 3*h | |
print("Warning: Diff>Defocus: using CoC/3") | |
end | |
end | |
if (x > base_h or x == -1) then | |
print("@/beyond H") | |
sleep(c*1000) | |
bookend() | |
X_bracket() | |
temp = get_exp_count().." @ "..x_start.."mm" | |
if v == 1 then print(temp) end | |
bookend() | |
return -- exit script | |
else | |
num = ((10*(h + x))/(2*x) + 5)/10 | |
end | |
if u == 2 or u == 3 then | |
dof = get_dofinfo() | |
x = dof.focus -- register actual x | |
last_x = x | |
sleep(c*1000) | |
bookend() | |
if u == 3 then x_start = x_start+m end | |
repeat -- to capture focus brackets from min focus up to x | |
X_bracket() | |
temp = get_exp_count().." @ "..x.."mm" | |
if v == 1 then print(temp) end | |
x = (x*(h*10 - 2*fl))/(h*10 - 2*x*10) -- position of next focus bracket | |
if (x - last_x) == 0 then x = last_x + 1 end | |
if x < last_x or x <= 0 then | |
print("Unknown Error") | |
refocus(x_start) | |
return | |
end | |
refocus(x) -- request move to x | |
dof = get_dofinfo() | |
x = dof.focus -- register actual x moved by cam | |
last_x = x | |
until (x > x_start) | |
refocus(x_start) | |
dof = get_dofinfo() | |
x = dof.focus -- register actual x moved by cam | |
X_bracket() | |
bookend() | |
temp = get_exp_count().." @ "..x.."mm" | |
if v == 1 then print(temp) end | |
return -- exit script | |
end | |
if (n ~= 0 and num > (n*10)-1) then -- accounting for last bracket at infinity focus | |
print("Warning") | |
temp2 = num + 1 | |
print("Focus Steps = "..temp2) | |
return -- exit script | |
end | |
sleep(c*1000) | |
bookend() | |
-- else look after u == 0 or 1 cases | |
refocus(x) -- explicitly refocus to start | |
dof = get_dofinfo() | |
x = dof.focus | |
last_x = x | |
if k == 1 then log[#log + 1] = "\n"..os.date() end | |
X_bracket() | |
temp = get_exp_count().." @ "..x.."mm" | |
if v == 1 then print(temp) end | |
if k == 1 then log[#log + 1] = temp end | |
repeat -- to capture focus brackets up to just past h/3 | |
x = (x*(h*10 - 2*fl))/(h*10 - 2*x*10) -- position of next focus bracket | |
if x <= last_x or x <= 0 then | |
print("Unknown Error") | |
refocus(x_start) | |
return | |
end | |
refocus(x) -- request move to x | |
dof = get_dofinfo() | |
x = dof.focus -- register actual x moved by cam | |
last_x = x | |
X_bracket() | |
temp = get_exp_count().." @ "..x.."mm" | |
if v == 1 then print(temp) end | |
if k == 1 then log[#log + 1] = temp end | |
until (x > h/3) | |
temp1 = h | |
temp2 = base_h*(q+2) | |
refocus(temp1) -- take shot at h | |
X_bracket() | |
temp = get_exp_count().." @ "..temp1.."mm" | |
if v == 1 then print(temp) end | |
if k == 1 then log[#log + 1] = temp end | |
if temp2 > temp1 then -- take additional infinity focus shot | |
refocus(temp2) | |
X_bracket() | |
temp = get_exp_count().." @ "..temp2.."mm" | |
if v == 1 then print(temp) end | |
if k == 1 then log[#log + 1] = temp end | |
end | |
bookend() | |
temp = count.." focus brackets" | |
print(temp) | |
if k == 1 then log[#log + 1] = temp end | |
temp1 = ((10*dof.coc*base_h)/temp2 + 5)/10 | |
temp = "Infinity blur "..temp1.."um" | |
if k == 1 then log[#log + 1] = temp end | |
if p ~= 0 and k == 1 then log[#log + 1] = "Exposure offset = "..p.."Ev" end | |
refocus(x_start) | |
if k == 1 then | |
print_screen(-2306) | |
for i = 1, #log do | |
print(log[i].."\n") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment