Add gphoto error handling, fix crash on fast triggering
This commit is contained in:
parent
0351c19eba
commit
9d5a49da21
|
@ -1,6 +1,7 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
# Camera type - can be : showmewebcam, picam, webcam, dslr
|
# Camera type - can be : showmewebcam, picam, webcam, dslr
|
||||||
cam_type = 'webcam'
|
cam_type = 'webcam'
|
||||||
|
apply_settings_on_startup = true
|
||||||
use_date_for_folder = false
|
use_date_for_folder = false
|
||||||
file_extension = 'jpg'
|
file_extension = 'jpg'
|
||||||
jpg_quality = 88
|
jpg_quality = 88
|
||||||
|
|
117
frame_opencv.py
117
frame_opencv.py
|
@ -37,6 +37,7 @@ _ = gettext.translation('template', localedir='locales', languages=[LOCALE]).get
|
||||||
# defaults
|
# defaults
|
||||||
project_settings_defaults = {
|
project_settings_defaults = {
|
||||||
'cam_type': "webcam",
|
'cam_type': "webcam",
|
||||||
|
'apply_settings_on_startup' : True,
|
||||||
'use_date_for_folder': False,
|
'use_date_for_folder': False,
|
||||||
'file_extension':'png',
|
'file_extension':'png',
|
||||||
'jpg_quality':90,
|
'jpg_quality':90,
|
||||||
|
@ -421,8 +422,8 @@ class dslr():
|
||||||
'whitebalance' : dict(min=0, max=7, step=1, default=2, value=1), # 0 Automatic 1 Daylight 2 Fluorescent 3 Tungsten 4 Flash 5 Cloudy 6 Shade 7 Preset
|
'whitebalance' : dict(min=0, max=7, step=1, default=2, value=1), # 0 Automatic 1 Daylight 2 Fluorescent 3 Tungsten 4 Flash 5 Cloudy 6 Shade 7 Preset
|
||||||
'capturetarget' : dict(min=0, max=1, step=1, default=0, value=0), # Internal memory
|
'capturetarget' : dict(min=0, max=1, step=1, default=0, value=0), # Internal memory
|
||||||
'iso' : dict(min=0, max=5, default=0, step=1, value=0), # 0:100, 5:3200
|
'iso' : dict(min=0, max=5, default=0, step=1, value=0), # 0:100, 5:3200
|
||||||
'shutterspeed' : dict(min=0, max=51, step=1, default=0, value=20), # 0 : 1/4000, 51: 30s
|
'shutterspeed' : dict(min=0, max=51, step=1, default=0, value=30), # 0 : 1/4000, 51: 30s
|
||||||
'manualfocusdrive' : dict(min=0, max=1, step=1, default=0, value=0), # Trigger autofocus # manualfocusdrive
|
# ~ 'manualfocusdrive' : dict(min=0, max=1, step=1, default=0, value=0), # Trigger autofocus # manualfocusdrive
|
||||||
}
|
}
|
||||||
# Map generic config name to specific picamera setting name
|
# Map generic config name to specific picamera setting name
|
||||||
self.cam_settings_map = {
|
self.cam_settings_map = {
|
||||||
|
@ -446,17 +447,22 @@ class dslr():
|
||||||
self.onionskin_was_on = self.onionskin
|
self.onionskin_was_on = self.onionskin
|
||||||
self.liveview_only = False
|
self.liveview_only = False
|
||||||
self.lenspos = None
|
self.lenspos = None
|
||||||
|
self.flip_img = False
|
||||||
self.cam_busy = False
|
self.cam_busy = False
|
||||||
self.cam = self.gp.check_result(self.gp.gp_camera_new())
|
self.camera_current_config = None
|
||||||
|
self.cam = self.init_camera()
|
||||||
|
|
||||||
|
def init_camera(self):
|
||||||
|
cam = self.gp.check_result(self.gp.gp_camera_new())
|
||||||
try:
|
try:
|
||||||
self.gp.check_result(self.gp.gp_camera_init(self.cam))
|
self.gp.check_result(self.gp.gp_camera_init(cam))
|
||||||
# get configuration tree
|
# get configuration tree
|
||||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(cam))
|
||||||
except:
|
except:
|
||||||
print(_("No camera found."))
|
print(_("No camera found."))
|
||||||
self.cam.exit()
|
cam = None
|
||||||
self.camera = None
|
|
||||||
self.current_camera_config = None
|
self.current_camera_config = None
|
||||||
|
return cam
|
||||||
|
|
||||||
def test_device(self, source):
|
def test_device(self, source):
|
||||||
pass
|
pass
|
||||||
|
@ -489,6 +495,8 @@ class dslr():
|
||||||
return cur_check_value
|
return cur_check_value
|
||||||
|
|
||||||
def capture_frame(self, img_path):
|
def capture_frame(self, img_path):
|
||||||
|
if self.cam is None:
|
||||||
|
self.cam = self.init_camera()
|
||||||
if not self.cam_busy:
|
if not self.cam_busy:
|
||||||
# CHECK: Should we init and close dslr for each frame ?
|
# CHECK: Should we init and close dslr for each frame ?
|
||||||
# Check battery level
|
# Check battery level
|
||||||
|
@ -503,32 +511,33 @@ class dslr():
|
||||||
# We don't want to download a jpg or raw from the dslr and save it as a false *.png.
|
# We don't want to download a jpg or raw from the dslr and save it as a false *.png.
|
||||||
img_path = self.find_file_ext(file_path.name, img_path)
|
img_path = self.find_file_ext(file_path.name, img_path)
|
||||||
print('Copying image to', img_path)
|
print('Copying image to', img_path)
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
try:
|
|
||||||
camera_file = self.cam.file_get(
|
camera_file = self.cam.file_get(
|
||||||
file_path.folder,
|
file_path.folder,
|
||||||
file_path.name,
|
file_path.name,
|
||||||
self.gp.GP_FILE_TYPE_NORMAL
|
self.gp.GP_FILE_TYPE_NORMAL
|
||||||
)
|
)
|
||||||
except:
|
|
||||||
print("Camera error. Check Battery and try restarting the camera.")
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
capture_ok = camera_file.save(img_path)
|
capture_ok = camera_file.save(img_path)
|
||||||
except:
|
except self.gp.GPhoto2Error as ex:
|
||||||
print('File access error.')
|
print(ex.code)
|
||||||
return False
|
# This is the way to find which error code is returned by gphoto
|
||||||
# ~ camera.exit()
|
# See http://gphoto.org/doc/api/gphoto2-result_8h.html for error codes
|
||||||
self.cam_busy = False
|
# Cam was turned off/on
|
||||||
|
if ex.code == self.gp.GP_ERROR_IO_USB_FIND or ex.code == self.gp.GP_ERROR_IO_USB_CLAIM:
|
||||||
|
self.cam.exit()
|
||||||
|
self.cam = self.init_camera()
|
||||||
|
# ~ if ex.code == self.gp.GP_ERROR_CAMERA_BUSY:
|
||||||
|
# ~ print("Camera Busy.")
|
||||||
|
self.cam_busy = False
|
||||||
|
return False
|
||||||
|
# Flip image if needed
|
||||||
|
if self.flip_img:
|
||||||
|
frm = cv2.imread(img_path)
|
||||||
|
frm = cv2.flip(frm, -1)
|
||||||
|
cv2.imwrite(img_path, frm)
|
||||||
# Update frame
|
# Update frame
|
||||||
cam.frame = cv2.imread(img_path)
|
self.frame = cv2.imread(img_path)
|
||||||
# ~ frame = cv2.resize(frame, (project_settings['screen_w'], project_settings['screen_h']))
|
self.cam_busy = False
|
||||||
# ~ if capture_ok is None:
|
|
||||||
# ~ return True
|
|
||||||
return True
|
return True
|
||||||
else:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def apply_gphoto_setting(self, setting:str):
|
def apply_gphoto_setting(self, setting:str):
|
||||||
# Get corresponding setting name if possible
|
# Get corresponding setting name if possible
|
||||||
|
@ -546,14 +555,6 @@ class dslr():
|
||||||
choices = list(self.gp.check_result(self.gp.gp_widget_get_choices(cur_setting)))
|
choices = list(self.gp.check_result(self.gp.gp_widget_get_choices(cur_setting)))
|
||||||
# Build dict with name/value equivalence
|
# Build dict with name/value equivalence
|
||||||
choices_dict = {choices.index(i):i for i in list(choices)}
|
choices_dict = {choices.index(i):i for i in list(choices)}
|
||||||
# Increment mode : current value is increased or looped
|
|
||||||
# ~ if inc:
|
|
||||||
# Get current setting value
|
|
||||||
# ~ new_value = gp.check_result(gp.gp_widget_get_value(cur_setting))
|
|
||||||
# Check current value + 1 is in range
|
|
||||||
# ~ if choices.index(new_value) in range(0, self.camera_current_settings[setting]['max']+1):
|
|
||||||
# Apply or loop value accordingly
|
|
||||||
# ~ pass
|
|
||||||
# If new_value exists in list, apply
|
# If new_value exists in list, apply
|
||||||
if select_setting['value'] in choices_dict:
|
if select_setting['value'] in choices_dict:
|
||||||
cur_setting_choice = self.gp.check_result(self.gp.gp_widget_get_choice(cur_setting, select_setting['value']))
|
cur_setting_choice = self.gp.check_result(self.gp.gp_widget_get_choice(cur_setting, select_setting['value']))
|
||||||
|
@ -570,6 +571,8 @@ class dslr():
|
||||||
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['min']
|
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['min']
|
||||||
|
|
||||||
def apply_setting(self, to_set:list=None, inc:int=0):
|
def apply_setting(self, to_set:list=None, inc:int=0):
|
||||||
|
if self.cam is None:
|
||||||
|
self.cam = self.init_camera()
|
||||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
||||||
# iterate over the settings dictionary
|
# iterate over the settings dictionary
|
||||||
if to_set is None:
|
if to_set is None:
|
||||||
|
@ -592,12 +595,14 @@ class dslr():
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def flip_image(self):
|
def flip_image(self):
|
||||||
self.frame = cv2.flip(self.frame, -1)
|
self.flip_img = True
|
||||||
|
|
||||||
def focus(self, direction:str='-'):
|
def focus(self, direction:str='-'):
|
||||||
self.apply_setting(['shutterspeed'], 1)
|
self.apply_setting(['shutterspeed'], 1)
|
||||||
|
|
||||||
def reset_picture_settings(self):
|
def reset_picture_settings(self):
|
||||||
|
if self.cam is None:
|
||||||
|
self.cam = self.init_camera()
|
||||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
||||||
for setting in self.camera_current_settings:
|
for setting in self.camera_current_settings:
|
||||||
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['default']
|
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['default']
|
||||||
|
@ -992,7 +997,8 @@ def main(args):
|
||||||
index = len(img_list)-1
|
index = len(img_list)-1
|
||||||
playhead = index
|
playhead = index
|
||||||
|
|
||||||
cam.apply_setting()
|
if project_settings['apply_settings_on_startup']:
|
||||||
|
cam.apply_setting()
|
||||||
|
|
||||||
cam.frame = get_onionskin_frame(savepath)
|
cam.frame = get_onionskin_frame(savepath)
|
||||||
cam.o_frame = cam.frame.copy()
|
cam.o_frame = cam.frame.copy()
|
||||||
|
@ -1134,22 +1140,27 @@ def main(args):
|
||||||
img_name = return_next_frame_number(get_last_frame(savepath))
|
img_name = return_next_frame_number(get_last_frame(savepath))
|
||||||
img_path = os.path.join(savepath, img_name)
|
img_path = os.path.join(savepath, img_name)
|
||||||
capture_ok = cam.capture_frame(img_path)
|
capture_ok = cam.capture_frame(img_path)
|
||||||
print(_("File {} written.").format(img_path))
|
if capture_ok:
|
||||||
# Special case when we've no frame yet
|
print(_("File {} written.").format(img_path))
|
||||||
if len(img_list) and (img_list[index] == '{letter}.-001.{ext}'.format(letter=project_letter, ext=project_settings['file_extension'])):
|
# Special case when we've no frame yet
|
||||||
img_list[index] = img_name
|
if len(img_list) and (img_list[index] == '{letter}.-001.{ext}'.format(letter=project_letter, ext=project_settings['file_extension'])):
|
||||||
else:
|
img_list[index] = img_name
|
||||||
index += 1
|
else:
|
||||||
# Display a message if capture was not successfull
|
index += 1
|
||||||
if not capture_ok:
|
|
||||||
cam.frame = generate_text_image(_("Error during capture."),
|
|
||||||
project_settings['screen_w'], project_settings['screen_h']
|
|
||||||
)
|
|
||||||
cam.o_frame = cam.frame.copy()
|
|
||||||
else:
|
|
||||||
cam.frame = get_onionskin_frame(savepath)
|
cam.frame = get_onionskin_frame(savepath)
|
||||||
cam.o_frame = cam.frame.copy()
|
cam.o_frame = cam.frame.copy()
|
||||||
# ~ frame = cam.frame
|
# Display a message if capture was not successfull
|
||||||
|
# This happens when you try to take too much pictures in a short span of time with the DSLR.
|
||||||
|
# With a long exposure, gphoto will sometimes throw a GP_ERROR_CAMERA_BUSY (-110) error.
|
||||||
|
# In this case, the user should try to take the picture again and it should work, so the need
|
||||||
|
# for a message in UI is not obvious, and can be confusing.
|
||||||
|
# Disabled for now
|
||||||
|
# ~ else:
|
||||||
|
# ~ cam.frame = generate_text_image(_("Error during capture."),
|
||||||
|
# ~ project_settings['screen_w'], project_settings['screen_h']
|
||||||
|
# ~ )
|
||||||
|
# ~ cam.o_frame = cam.frame.copy()
|
||||||
|
|
||||||
# Quit app
|
# Quit app
|
||||||
elif k%256 == 27:
|
elif k%256 == 27:
|
||||||
# ESC pressed
|
# ESC pressed
|
||||||
|
|
Loading…
Reference in New Issue