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

@@ -0,0 +1,108 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import io, logging
from PIL import Image
import gphoto2 as gp
from . 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,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import io, logging
from PIL import Image
import gphoto2cffi as gp
from . import Camera
class CameraGphoto2Cffi(Camera):
def __init__(self):
super().__init__()
self.hasPreview = True
self.hasIdle = True
# Avoid output cluttered
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s',
level=logging.CRITICAL)
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 PIL import Image
import os, subprocess
from . import Camera
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

@@ -0,0 +1,51 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from PIL import Image
import cv2
from . import Camera
class CameraOpenCV(Camera):
def __init__(self):
super().__init__()
self.hasPreview = True
self.hasIdle = True
self._cap = cv2.VideoCapture()
def setActive(self):
if not self._cap.isOpened():
self._cap.open(0)
if not self._cap.isOpened():
raise RuntimeError('Camera could not be opened')
def setIdle(self):
if self._cap.isOpened():
self._cap.release()
def getPreview(self):
return self.getPicture()
def getPicture(self):
self.setActive()
status, frame = self._cap.read()
if not status:
raise RuntimeError('Failed to capture picture')
# OpenCV yields frames in BGR format, conversion to RGB necessary.
# (See https://stackoverflow.com/a/32270308)
return Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

View File

@@ -0,0 +1,99 @@
#!/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):
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):
return self._has_preview
@hasPreview.setter
def hasPreview(self, value):
if not isinstance(value, bool):
raise ValueError('Expected bool')
self._has_preview = value
@property
def hasIdle(self):
return self._has_idle
@hasIdle.setter
def hasIdle(self, value):
if not isinstance(value, bool):
raise ValueError('Expected bool')
self._has_idle = value
def setActive(self):
if not self.hasIdle:
pass
else:
raise NotImplementedError()
def setIdle(self):
if not self.hasIdle:
raise RuntimeError('Camera does not have idle functionality')
raise NotImplementedError()
def getPreview(self):
if not self.hasPreview:
raise RuntimeError('Camera does not have preview functionality')
raise NotImplementedError()
def getPicture(self):
raise NotImplementedError()
def setIdle(self):
if not self.hasIdle:
raise RuntimeError('Camera does not support idle state')
raise NotImplementedError()