Flexible module system for Camera and Gui implementations added
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -7,7 +7,7 @@ from PIL import Image
|
||||
|
||||
import gphoto2 as gp
|
||||
|
||||
from Camera import Camera
|
||||
from . import Camera
|
||||
|
||||
|
||||
class CameraGphoto2(Camera):
|
||||
@@ -7,7 +7,7 @@ from PIL import Image
|
||||
|
||||
import gphoto2cffi as gp
|
||||
|
||||
from Camera import Camera
|
||||
from . import Camera
|
||||
|
||||
|
||||
class CameraGphoto2Cffi(Camera):
|
||||
@@ -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):
|
||||
@@ -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):
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
@@ -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):
|
||||
Reference in New Issue
Block a user