Different gPhoto2 backends implemented. Functionally is working on a very basic level

This commit is contained in:
Balthasar Reuter
2018-04-17 01:06:20 +02:00
parent 7a02d36c80
commit ee80244f69
8 changed files with 262 additions and 27 deletions

View File

@@ -1,3 +1,8 @@
pip install pyqt5
pip install opencv-python
pip install Pillow
apt install gphoto2 libgphoto2-dev
pip install gphoto2
-or-
pip install gphoto2-cffi

View File

@@ -8,6 +8,22 @@ class Camera:
self.hasPreview = False
self.hasIdle = False
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.cleanup()
def cleanup(self):
pass
@property
def hasPreview(self):

108
photobooth/CameraGphoto2.py Normal file
View File

@@ -0,0 +1,108 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import io, logging
from PIL import Image
import gphoto2 as gp
from Camera import Camera
class CameraGphoto2(Camera):
def __init__(self):
super().__init__()
self.hasPreview = True
self.hasIdle = False
self._isActive = False
self._setupLogging()
self._setupCamera()
def cleanup(self):
self._cap.exit(self._ctxt)
# self.setIdle()
def _setupLogging(self):
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s',
level=logging.ERROR)
gp.check_result(gp.use_python_logging())
def _setupCamera(self):
self._ctxt = gp.Context()
self._cap = gp.Camera()
self._cap.init(self._ctxt)
self._printSummary()
# get configuration tree
config = gp.check_result(gp.gp_camera_get_config(self._cap))
# find the image format config item
OK, image_format = gp.gp_widget_get_child_by_name(config, 'imageformat')
if OK >= gp.GP_OK:
# get current setting
value = gp.check_result(gp.gp_widget_get_value(image_format))
# make sure it's not raw
if 'raw' in value.lower():
raise RuntimeError('Camera file format is set to RAW')
print(config)
def _printSummary(self):
# self.setActive()
text = self._cap.get_summary(self._ctxt)
print('Summary')
print('=======')
print(str(text))
# self.setIdle()
# def setActive(self):
# self._cap.init(self._ctxt)
# if not self._isActive:
# self._cap.init(self._ctxt)
# self._isActive = True
# def setIdle(self):
# self._cap.exit(self._ctxt)
# if self._isActive:
# self._cap.exit(self._ctxt)
# self._isActive = False
def getPreview(self):
# self.setActive()
camera_file = self._cap.capture_preview() #gp.check_result(gp.gp_camera_capture_preview(self._cap))
file_data = camera_file.get_data_and_size() # gp.check_result(gp.gp_file_get_data_and_size(camera_file))
return Image.open(io.BytesIO(file_data))
def getPicture(self):
# self.setActive()
file_path = self._cap.capture(gp.GP_CAPTURE_IMAGE)
camera_file = self._cap.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL)
file_data = camera_file.get_data_and_size()
return Image.open(io.BytesIO(file_data))

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import io
from PIL import Image
import gphoto2cffi as gp
from Camera import Camera
class CameraGphoto2Cffi(Camera):
def __init__(self):
super().__init__()
self.hasPreview = True
self.hasIdle = True
self._setupCamera()
def _setupCamera(self):
self._cap = gp.Camera()
print(self._cap.supported_operations)
if 'raw' in self._cap.config['imgsettings']['imageformat'].value.lower():
raise RuntimeError('Camera file format is set to RAW')
def setActive(self):
self._cap._get_config()['actions']['viewfinder'].set(True)
def setIdle(self):
self._cap._get_config()['actions']['viewfinder'].set(False)
def getPreview(self):
return Image.open(io.BytesIO(self._cap.get_preview()))
def getPicture(self):
return Image.open(io.BytesIO(self._cap.capture()))

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Camera import Camera
from PIL import Image
import os, subprocess
class CameraGphoto2CommandLine(Camera):
def __init__(self):
super().__init__()
self.hasPreview = False
self.hasIdle = False
if os.access('/dev/shm', os.W_OK):
self._tmp_filename = '/dev/shm/photobooth.jpg'
else:
self._tmp_filename = '/tmp/photobooth.jpg'
self.setActive()
def setActive(self):
print(self._callGphoto('-a', '/dev/null'))
def getPicture(self):
self._callGphoto('--capture-image-and-download', self._tmp_filename)
return Image.open(self._tmp_filename)
def _callGphoto(self, action, filename):
cmd = 'gphoto2 --force-overwrite --quiet ' + action + ' --filename ' + filename
return subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)

View File

@@ -9,8 +9,6 @@ from PictureDimensions import PictureDimensions
import Gui
from PyQt5Gui import PyQt5Gui
from CameraOpenCV import CameraOpenCV as Camera
from PIL import Image, ImageOps
from multiprocessing import Pipe, Process
@@ -21,11 +19,11 @@ from time import time, sleep, localtime, strftime
class Photobooth:
def __init__(self, config):
def __init__(self, config, camera):
picture_basename = strftime(config.get('Picture', 'basename'), localtime())
self._cap = Camera()
self._cap = camera
self._pic_dims = PictureDimensions(config, self._cap.getPicture().size)
self._pic_list = PictureList(picture_basename)
@@ -117,7 +115,9 @@ class Photobooth:
def showCounterNoPreview(self):
for i in range(self.countdownTime):
self._send.send( Gui.PreviewState(str(i)) )
self._send.send( Gui.PreviewState(
message = str(i),
picture = Image.new('RGB', (1,1), 'white') ) )
sleep(1)
@@ -165,7 +165,19 @@ class Photobooth:
def main_photobooth(config, send, recv):
photobooth = Photobooth(config)
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 ImportError('Unknown camera module "' + config.get('Camera', 'module') + '"')
with Camera() as cap:
photobooth = Photobooth(config, cap)
return photobooth.run(send, recv)

View File

@@ -324,26 +324,27 @@ class PyQt5Settings(QFrame):
global cfg
wrapper = QComboBox()
wrapper.addItem('command line')
wrapper.addItem('piggyphoto')
wrapper.addItem('gphoto2-cffi')
self._camera_modules = [
('gphoto2-commandline', 'gphoto2 via command line'),
# ('piggyphoto', 'piggyphoto'),
('gphoto2-cffi', 'gphoto2-cffi'),
('python-gphoto2', 'python-gphoto2'),
('opencv', 'OpenCV'),
('', 'none') ]
current_wrapper = cfg.get('Camera', 'gphoto2_wrapper')
if current_wrapper == 'commandline':
wrapper.setCurrentIndex(0)
elif current_wrapper == 'piggyphoto':
wrapper.setCurrentIndex(1)
elif current_wrapper == 'gphoto2-cffi':
wrapper.setCurrentIndex(2)
else:
wrapper.setCurrentIndex(-1)
wrapper = QComboBox()
for m in self._camera_modules:
wrapper.addItem(m[1])
current_wrapper = cfg.get('Camera', 'module')
idx = [x for x, m in enumerate(self._camera_modules) if m[0] == current_wrapper]
wrapper.setCurrentIndex(idx[0] if len(idx) > 0 else -1)
self._value_widgets['Camera'] = {}
self._value_widgets['Camera']['gphoto2_wrapper'] = wrapper
self._value_widgets['Camera']['module'] = wrapper
layout = QFormLayout()
layout.addRow(QLabel('gPhoto2 wrapper:'), self._value_widgets['Camera']['gphoto2_wrapper'])
layout.addRow(QLabel('Camera module:'), self._value_widgets['Camera']['module'])
widget = QGroupBox('Camera settings')
widget.setLayout(layout)
@@ -467,8 +468,9 @@ class PyQt5Settings(QFrame):
cfg.set('Picture', 'min_dist_y', self._value_widgets['Picture']['min_dist_y'].text())
cfg.set('Picture', 'basename', self._value_widgets['Picture']['basename'].text())
wrapper_idx2val = [ 'commandline', 'piggyphoto', 'gphoto2-cffi' ]
cfg.set('Camera', 'gphoto2_wrapper', wrapper_idx2val[self._value_widgets['Camera']['gphoto2_wrapper'].currentIndex()])
# wrapper_idx2val = [ 'commandline', 'piggyphoto', 'gphoto2-cffi', '' ]
# cfg.set('Camera', 'module', wrapper_idx2val[self._value_widgets['Camera']['module'].currentIndex()])
cfg.set('Camera', 'module', self._camera_modules[self._value_widgets['Camera']['module'].currentIndex()][0])
cfg.write()
self._gui.restart()

View File

@@ -7,8 +7,8 @@ width = 1024
height = 600
[Camera]
# Wrapper to use gPhoto2 (gphoto2-cffi, piggyphoto, commandline)
gphoto2_wrapper = commandline
# Camera module to use (python-gphoto2, gphoto2-cffi, gphoto2-commandline, opencv)
module = python-gphoto2
[Gpio]
# Enable use of GPIO (True/False)