Flexible module system for Camera and Gui implementations added

This commit is contained in:
Balthasar Reuter
2018-04-17 23:45:17 +02:00
parent cf9e687102
commit cb5c2d6870
9 changed files with 73 additions and 46 deletions

View File

@@ -1,20 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Config import Config
from PictureList import PictureList
from PictureDimensions import PictureDimensions
import Gui
from PyQt5Gui import PyQt5Gui
from PIL import Image, ImageOps
from multiprocessing import Pipe, Process
from time import time, sleep, localtime, strftime
import importlib
from PIL import Image, ImageOps
from Config import Config
from PictureList import PictureList
from PictureDimensions import PictureDimensions
import camera, gui
class Photobooth:
@@ -88,7 +87,7 @@ class Photobooth:
self.trigger()
except RuntimeError as e:
print('Camera error: ' + str(e))
self._send.send( Gui.ErrorState('Camera error', str(e)) )
self._send.send( gui.ErrorState('Camera error', str(e)) )
return 0
@@ -109,7 +108,7 @@ class Photobooth:
tic, toc = time(), 0
while toc < self.countdownTime:
self._send.send( Gui.PreviewState(
self._send.send( gui.PreviewState(
message = str(self.countdownTime - int(toc)),
picture = ImageOps.mirror(self._cap.getPreview()) ) )
toc = time() - tic
@@ -118,7 +117,7 @@ class Photobooth:
def showCounterNoPreview(self):
for i in range(self.countdownTime):
self._send.send( Gui.PreviewState(
self._send.send( gui.PreviewState(
message = str(i),
picture = Image.new('RGB', (1,1), 'white') ) )
sleep(1)
@@ -126,7 +125,7 @@ class Photobooth:
def showPose(self):
self._send.send( Gui.PoseState() )
self._send.send( gui.PoseState() )
def captureSinglePicture(self):
@@ -155,43 +154,52 @@ class Photobooth:
def trigger(self):
self._send.send(Gui.GreeterState())
self._send.send(gui.GreeterState())
self.setCameraActive()
sleep(self.greeterTime)
img = self.capturePictures()
img.save(self.getNextFilename(), 'JPEG')
self._send.send(Gui.PictureState(img))
self._send.send(gui.PictureState(img))
self.setCameraIdle()
sleep(self.displayTime)
self._send.send(Gui.IdleState())
self._send.send(gui.IdleState())
def lookup_and_import(module_list, name, package=None):
result = next(((mod_name, class_name)
for config_name, mod_name, class_name in module_list
if name == config_name), None)
print(result)
if package == None:
import_module = importlib.import_module(result[0])
else:
import_module = importlib.import_module('.' + result[0], package)
if result[1] == None:
return import_module
else:
return getattr(import_module, result[1])
def main_photobooth(config, send, recv):
while True:
try:
if config.get('Camera', 'module') == 'python-gphoto2':
from CameraGphoto2 import CameraGphoto2 as Camera
elif config.get('Camera', 'module') == 'gphoto2-cffi':
from CameraGphoto2Cffi import CameraGphoto2Cffi as Camera
elif config.get('Camera', 'module') == 'gphoto2-commandline':
from CameraGphoto2CommandLine import CameraGphoto2CommandLine as Camera
elif config.get('Camera', 'module') == 'opencv':
from CameraOpenCV import CameraOpenCV as Camera
else:
raise ModuleNotFoundError('Unknown camera module "' + config.get('Camera', 'module') + '"')
Camera = lookup_and_import(camera.modules, config.get('Camera', 'module'), 'camera')
with Camera() as cap:
photobooth = Photobooth(config, cap)
return photobooth.run(send, recv)
except BaseException as e:
send.send( Gui.ErrorState('Camera error', str(e), True) )
send.send( gui.ErrorState('Camera error', str(e)) )
event = recv.recv()
if str(event) != 'ack':
print('Unknown event received: ' + str(event))
@@ -208,8 +216,8 @@ def run(argv):
photobooth = Process(target=main_photobooth, args=(config, gui_send, event_recv), daemon=True)
photobooth.start()
gui = PyQt5Gui(argv, config)
return gui.run(event_send, gui_recv)
Gui = lookup_and_import(gui.modules, config.get('Gui', 'module'), 'gui')
return Gui(argv, config).run(event_send, gui_recv)
def main(argv):

View File

@@ -7,7 +7,7 @@ from PIL import Image
import gphoto2 as gp
from Camera import Camera
from . import Camera
class CameraGphoto2(Camera):

View File

@@ -7,7 +7,7 @@ from PIL import Image
import gphoto2cffi as gp
from Camera import Camera
from . import Camera
class CameraGphoto2Cffi(Camera):

View File

@@ -1,11 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Camera import Camera
from PIL import Image
import os, subprocess
from . import Camera
class CameraGphoto2CommandLine(Camera):
def __init__(self):

View File

@@ -1,11 +1,12 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Camera import Camera
from PIL import Image
import cv2
from . import Camera
class CameraOpenCV(Camera):
def __init__(self):

View File

@@ -1,6 +1,15 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Available camera modules as tuples of (config name, module name, class name)
modules = (
('python-gphoto2', 'CameraGphoto2', 'CameraGphoto2'),
('gphoto2-cffi', 'CameraGphoto2Cffi', 'CameraGphoto2Cffi'),
('gphoto2-commandline', 'CameraGphoto2CommandLine', 'CameraGphoto2CommandLine'),
('opencv', 'CameraOpenCV', 'CameraOpenCV') )
class Camera:
def __init__(self):
@@ -87,4 +96,4 @@ class Camera:
if not self.hasIdle:
raise RuntimeError('Camera does not support idle state')
raise NotImplementedError()
raise NotImplementedError()

View File

@@ -1,4 +1,6 @@
[Gui]
# Gui module to use (qt5)
module = qt5
# Start Photobooth in fullscreen mode (True/False)
fullscreen = False
# Width of Photobooth (if not fullscreen)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import Gui
# import Gui
from PIL import ImageQt
@@ -9,7 +9,9 @@ from PyQt5.QtCore import Qt, QObject, QThread, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QFormLayout, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLayout, QLineEdit, QMainWindow, QMessageBox, QPushButton, QVBoxLayout)
from PyQt5.QtGui import QImage, QPainter, QPixmap
class PyQt5Gui(Gui.Gui):
from . import *
class PyQt5Gui(Gui):
def __init__(self, argv, config):
@@ -67,26 +69,26 @@ class PyQt5Gui(Gui.Gui):
def handleState(self, state):
if not isinstance(state, Gui.GuiState):
if not isinstance(state, GuiState):
raise ValueError('Invalid data received')
if isinstance(state, Gui.IdleState):
if isinstance(state, IdleState):
self.showIdle()
elif isinstance(state, Gui.GreeterState):
elif isinstance(state, GreeterState):
global cfg
num_pictures = ( cfg.getInt('Picture', 'num_x') *
cfg.getInt('Picture', 'num_y') )
self._p.setCentralWidget(
PyQt5PictureMessage('Will capture {} pictures!'.format(num_pictures)))
elif isinstance(state, Gui.PreviewState):
elif isinstance(state, PreviewState):
img = ImageQt.ImageQt(state.picture)
self._p.setCentralWidget(PyQt5PictureMessage(state.message, img))
elif isinstance(state, Gui.PoseState):
elif isinstance(state, PoseState):
self._p.setCentralWidget(PyQt5PictureMessage('Pose!'))
elif isinstance(state, Gui.PictureState):
elif isinstance(state, PictureState):
img = ImageQt.ImageQt(state.picture)
self._p.setCentralWidget(PyQt5PictureMessage('', img))
elif isinstance(state, Gui.ErrorState):
elif isinstance(state, ErrorState):
self.showError(state.title, state.message)
else:
raise ValueError('Unknown state')

View File

@@ -1,6 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Available gui modules as tuples of (config name, module name, class name)
modules = ( ('qt5', 'PyQt5Gui', 'PyQt5Gui'), )
class Gui:
def __init__(self):