Created
March 5, 2018 21:21
-
-
Save pigeonhill/185a1b72e5a909d767f0ce9bdfb259e4 to your computer and use it in GitHub Desktop.
Auto Hand Held Focus Stacking
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
--HHFS Script Release 0.8 | |
--[[ | |
******************************************************************************************** | |
This script creates a two image focus stack via aperture bracketing. | |
The script attempts to maintain the same exposure of the closed down aperture as the base exposure, between two limits: the minimum handheld shutter and the maximum ISO. | |
The script 'remembers' menu settings at camera close, so you will only need to set them once: only change things as required. | |
The base exposure should be taken at a wide aperture. | |
Garry George | |
March 2018 | |
www.photography.grayheron.net | |
******************************************************************************************** | |
--]] | |
require("config") | |
max_iso = 0 -- Set in menu | |
max_iso_apex = 0 | |
base_shutter_apex = 0 | |
base_iso_apex = 0 | |
base_aperture_apex = 0 | |
options0 = {"ON", "OFF"} | |
options1 = {"Auto", "Manual"} | |
options2 = {"0 delay", "2s delay", "5s delay"} | |
options3 = {"FF Sensor", "Crop Sensor"} | |
options4 = {"1600", "3200","6400"} | |
options5 = {"Auto","1/30","1/60"} | |
options6 = {"None", "Audio","Led", "Both"} | |
options8 = {"F/16", "F/22"} | |
min_shutter_value =0 | |
min_shutter_apex = 0 | |
timer_running = false | |
time_pressed = 0 | |
run_HHFS = false | |
beeped = false | |
good_to_go = false | |
function HHFS_bracket(arg) -- note this function is called regularly by the shoot_task event handler and does all the main work | |
if HHFS_menu.submenu["Turn Script on and off"].value == "ON" then good_to_go = true else good_to_go = false end -- track the script's on/off state | |
if good_to_go and timer_running and (not beeped) and (dryos.ms_clock - time_pressed > 3000) then -- give user feedback if requested | |
if HHFS_menu.submenu["User feedback"].value == "Audio" or HHFS_menu.submenu["User feedback"].value == "Both" then beep() end | |
if HHFS_menu.submenu["User feedback"].value == "Led" or HHFS_menu.submenu["User feedback"].value == "Both" then led_blink() end | |
beeped = true -- so don't beep again | |
end | |
if good_to_go and not run_HHFS then -- keep track of min shutter speed in auto mode | |
if lens.focal_length == 0 then menu.set("Hand Held Bracketing", "Min Shutter options", "Manual") end -- handle lenses that don't report FL, but ensure ETTR min shutter set correctly | |
if HHFS_menu.submenu["Min Shutter options"].value == "Auto" then -- set ETTR automatically based on focal length and min hand holding shutter set in script's menu | |
local x = lens.focal_length | |
if HHFS_menu.submenu["Sensor Type"].value == "Crop Sensor" then x = x*1.6 end -- account for crop sensor | |
x = 8*(7+math.ceil(math.log(x)/math.log(2))) | |
if x < 96 and HHFS_menu.submenu["Your min hand holding limit"].value == "1/30" then | |
x = 96 | |
elseif x < 104 and HHFS_menu.submenu["Your min hand holding limit"].value == "1/60" then | |
x = 104 | |
end | |
menu.set("Auto ETTR","Slowest shutter", x) -- set slowest ETTR shutter to FL-informed value, ie 1/FL guidance + your min hand holding limit (1/30 or 1/60) | |
end | |
min_shutter_value = menu.get("Auto ETTR","Slowest shutter",1) | |
min_shutter_value = 1/(2^(min_shutter_value/8 - 7)) -- set min shutter in seconds based on ETTR setting | |
end | |
if good_to_go and run_HHFS then -- capture brackets | |
if HHFS_menu.submenu["Delay?"].value == "2s delay" then | |
msleep(2000) -- inject a 2 sec delay | |
elseif HHFS_menu.submenu["Delay?"].value == "5s delay" then | |
msleep(5000) -- inject a 5 sec delay | |
end -- else no delay | |
base_shutter_apex = camera.shutter.apex | |
base_iso_apex = camera.iso.apex | |
base_aperture_apex = camera.aperture.apex | |
max_iso = tonumber(HHFS_menu.submenu["Max ISO"].value) | |
camera.iso.value = max_iso | |
max_iso_apex = camera.iso.apex | |
camera.iso.apex = base_iso_apex | |
camera.shoot() -- take base image | |
camera.shutter.value = min_shutter_value -- set to slowest shutter | |
min_shutter_apex = camera.shutter.apex | |
local min_aperture_apex = 0 | |
if HHFS_menu.submenu["Min aperture"].value == "F/16" then min_aperture_apex = 8 else min_aperture_apex = 9 end | |
camera.aperture.apex = min_aperture_apex | |
local delta_ev = min_aperture_apex - base_aperture_apex | |
local delta_tv = base_shutter_apex - min_shutter_apex | |
if base_shutter_apex == min_shutter_apex then -- can only use ISO | |
camera.iso.apex = camera.iso.apex + delta_ev | |
if camera.iso.apex > max_iso_apex then camera.iso.apex = max_iso_apex end | |
else -- can use shutter and ISO | |
camera.shutter.apex = min_shutter_apex | |
camera.iso.apex = camera.iso.apex + (delta_ev - delta_tv) | |
if camera.iso.apex > max_iso_apex then camera.iso.apex = max_iso_apex end | |
end | |
camera.shoot() -- take the closed down aperture image | |
camera.shutter.apex = base_shutter_apex -- reset settings to initial state | |
camera.iso.apex = base_iso_apex | |
camera.aperture.apex = base_aperture_apex | |
if timer_running and (not beeped) then -- give user feedback if requested | |
if HHFS_menu.submenu["User feedback"].value == "Audio" or HHFS_menu.submenu["User feedback"].value == "Both" then beep() end | |
if HHFS_menu.submenu["User feedback"].value == "Led" or HHFS_menu.submenu["User feedback"].value == "Both" then led_blink() end | |
end | |
run_HHFS = false | |
end | |
return true -- no reason not to | |
end | |
function test4key(key) | |
if key == KEY.HALFSHUTTER and good_to_go and (not timer_running) and (not run_HHFS) then -- note assumes the shoot_task runs at least once following camera start | |
timer_running = true -- start looking for half shutter long press | |
time_pressed = dryos.ms_clock | |
beeped = false | |
return false -- steal key press | |
elseif key == KEY.UNPRESS_HALFSHUTTER and good_to_go and timer_running and (not run_HHFS) then | |
if dryos.ms_clock - time_pressed > 3000 then -- 3 sec plus half shutter press, so start HH bracketing | |
run_HHFS = true -- OK to run the main script | |
timer_running = false -- stop looking for a long press | |
return false -- steal key press | |
else -- less than 3 seconds so handle as a normal half shutter unpress | |
timer_running = false | |
return true | |
end | |
else -- must be a normal key press | |
return true | |
end | |
end | |
event.keypress = test4key | |
event.shoot_task = HHFS_bracket | |
HHFS_menu = menu.new | |
{ | |
parent = "Shoot", | |
name = "Hand Held Focus Stacking", | |
help = "Start at max aperture", | |
submenu = | |
{ | |
{ | |
name = "Turn Script on and off", | |
help = "Does what it says", | |
choices = options0, | |
}, | |
{ | |
name = "Min Shutter options", | |
help = "Auto means script sets ETTR min, manual means you do", | |
help2 = "For manual, set min in ETTR menu", | |
choices = options1, | |
}, | |
{ | |
name = "Sensor Type", | |
help = "Full Frame or Crop 1.6?", | |
choices = options3, | |
}, | |
{ | |
name = "Delay?", | |
help = "Injects the requested delay before bracketing", | |
help2 = "Switch off Canon delays", | |
choices = options2, | |
}, | |
{ | |
name = "Max ISO", | |
help = "Don't over push it!'", | |
choices = options4, | |
}, | |
{ | |
name = "Min aperture", | |
help = "Smallest aperture", | |
choices = options8, | |
}, | |
{ | |
name = "Your min hand holding limit", | |
help = "Your hand holding shutter speed limit", | |
help2 = "Useful when in Auto mode to override 1/FL for WA lenses", | |
choices = options5, | |
}, | |
{ | |
name = "User feedback", | |
help = "To help with 3s half shutter and indicate bracket end", | |
choices = options6, | |
} | |
} | |
} | |
config.create_from_menu(HHFS_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