A bit of cleanup. Failed pictures can now produce recoverable errors (e.g., failed focus) and retry up to 3 times

This commit is contained in:
Balthasar Reuter
2015-06-30 23:38:34 +02:00
parent 234d4bddb5
commit 02f636ecca
2 changed files with 62 additions and 18 deletions

View File

@@ -11,7 +11,9 @@ except ImportError:
class CameraException(Exception):
"""Custom exception class to handle camera class errors"""
pass
def __init__(self, message, recoverable=False):
self.message = message
self.recoverable = recoverable
class Camera_cv:
@@ -35,23 +37,28 @@ class Camera_gPhoto:
def __init__(self, picture_size):
self.picture_size = picture_size
# Print the abilities of the connected camera
# print(self.call_gphoto("-a", "/dev/null"))
# Print the capabilities of the connected camera
try:
print(self.call_gphoto("-a", "/dev/null"))
except:
print("Warning: Can't list camera capabilities. Do you have gPhoto2 installed?")
def call_gphoto(self, action, filename):
# Try to run the command
try:
cmd = "gphoto2 --force-overwrite --quiet " + action + " --filename " + filename
cmd = [ "gphoto2", "--force-overwrite", "--quiet", action, "--filename " + filename ]
output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
if "ERROR" in output:
raise subprocess.CalledProcessError(returncode=0, cmd=cmd, output=output)
except subprocess.CalledProcessError as e:
if "Canon EOS Capture failed: 2019" in e.output:
raise CameraException("Can't focus! Move and try again!")
raise CameraException("Can't focus! Move a little bit!", True)
elif "No camera found" in e.output:
raise CameraException("No (supported) camera detected!")
raise CameraException("No (supported) camera detected!", False)
elif "command not found" in e.output:
raise CameraException("gPhoto2 not found!", False)
else:
raise CameraException("Unknown error!\n" + '\n'.join(e.output.split('\n')[1:3]))
raise CameraException("Unknown error!\n" + '\n'.join(e.output.split('\n')[1:3]), False)
return output
def take_picture(self, filename="/tmp/picture.jpg"):

View File

@@ -49,19 +49,31 @@ display_time = 10
###############
class PictureList:
"""Class to manage images and count them"""
"""A simple helper class.
It provides the filenames for the assembled pictures and keeps count
of taken and previously existing pictures.
"""
def __init__(self, basename):
"""Initialize filenames to the given basename and search for
existing files. Set the counter accordingly.
"""
# Set basename and suffix
self.basename = basename
self.suffix = ".jpg"
self.count_width = 5
# Ensure directory exists
dirname = os.path.dirname(self.basename)
if not os.path.exists(dirname):
os.makedirs(dirname)
# Find existing files
count_pattern = "[0-9]" * self.count_width
pictures = glob(self.basename + count_pattern + self.suffix)
# Get number of latest file
if len(pictures) == 0:
self.counter = 0
@@ -69,8 +81,10 @@ class PictureList:
pictures.sort()
last_picture = pictures[-1]
self.counter = int(last_picture[-(self.count_width+len(self.suffix)):-len(self.suffix)])
print("Number of last existing file: " + str(self.counter) + "(" + str(len(pictures)) + ")")
print("Saving as: " + self.basename)
# Print initial infos
print("Info: Number of last existing file: " + str(self.counter))
print("Info: Saving assembled pictures as: " + self.basename + "XXXXX.jpg")
def get(self, count):
return self.basename + str(count).zfill(self.count_width) + self.suffix
@@ -84,6 +98,11 @@ class PictureList:
class Photobooth:
"""The main class.
It contains all the logic for the photobooth.
"""
def __init__(self, display_size, picture_basename, picture_size, pose_time, display_time,
trigger_channel, shutdown_channel, lamp_channel):
self.display = GuiModule('Photobooth', display_size)
@@ -277,16 +296,34 @@ class Photobooth:
# Take pictures
filenames = [i for i in range(4)]
for x in range(4):
self.display.clear()
self.display.show_message("S M I L E !!!\n\n" + str(x+1) + " of 4")
self.display.apply()
# Try each picture up to 3 times
for attempt in range(3):
self.display.clear()
self.display.show_message("S M I L E !!!\n\n" + str(x+1) + " of 4")
self.display.apply()
tic = clock()
filenames[x] = self.camera.take_picture("/tmp/photobooth_%02d.jpg" % x)
toc = clock() - tic
tic = clock()
if toc < 1.0:
sleep(1.0 - toc)
try:
filenames[x] = self.camera.take_picture("/tmp/photobooth_%02d.jpg" % x)
break
except CameraException as e:
# On recoverable errors: display message and retry
if e.recoverable:
if attempt < 3:
self.display.clear()
self.display.show_message(e.message)
self.display.apply()
sleep(1)
else:
raise CameraException("Giving up! Please start again!", False)
else:
raise e
# Sleep for a little bit if necessary
toc = clock() - tic
if toc < 1.0:
sleep(1.0 - toc)
# Show 'Wait'
self.display.clear()