[mousetrap/gnome3-wip: 119/240] Add basic configuration system.
- From: Heidi Ellis <heidiellis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mousetrap/gnome3-wip: 119/240] Add basic configuration system.
- Date: Mon, 8 Sep 2014 15:22:33 +0000 (UTC)
commit 72b0144889f75540a2268e186764ca277d98bcc3
Author: Stoney Jackson <dr stoney gmail com>
Date: Mon Jun 23 13:22:38 2014 -0400
Add basic configuration system.
* All constructors now take a `mousetrap.config.Config` as
first parameter (after self).
* `mousetrap.config` contians editable configuration (for now).
* log.py went away since its configuration is now in config.py.
src/mousetrap/config.py | 41 +++++++++++++++++++++
src/mousetrap/gui.py | 19 +++++++---
src/mousetrap/image.py | 3 +-
src/mousetrap/log.py | 18 ---------
src/mousetrap/main.py | 62 +++++++++++++++----------------
src/mousetrap/plugins/camera.py | 3 ++
src/mousetrap/plugins/display.py | 3 ++
src/mousetrap/plugins/eyes.py | 60 +++++++++++++++++-------------
src/mousetrap/plugins/nose.py | 10 +++--
src/mousetrap/plugins/nose_joystick.py | 5 ++-
src/mousetrap/vision.py | 9 +++--
11 files changed, 141 insertions(+), 92 deletions(-)
---
diff --git a/src/mousetrap/config.py b/src/mousetrap/config.py
new file mode 100644
index 0000000..550bd28
--- /dev/null
+++ b/src/mousetrap/config.py
@@ -0,0 +1,41 @@
+class Config(dict):
+ def __init__(self):
+ self['loops_per_second'] = 10
+
+ self['assembly'] = [
+ 'mousetrap.plugins.camera.CameraPlugin',
+ 'mousetrap.plugins.display.DisplayPlugin',
+ 'mousetrap.plugins.nose_joystick.NoseJoystickPlugin',
+ 'mousetrap.plugins.eyes.EyesPlugin',
+ ]
+
+ # See `logging` and `logging.config`
+ self['logging'] = {
+ 'version': 1,
+ 'root': {
+ 'level': 'DEBUG',
+ 'formatters': ['default'],
+ 'handlers': ['console']
+ },
+ 'formatters': {
+ 'default': {
+ 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+ }
+ },
+ 'handlers': {
+ 'console': {
+ 'class': 'logging.StreamHandler',
+ 'level': 'DEBUG',
+ 'formatter' : 'default',
+ 'stream' : 'ext://sys.stdout'
+ }
+ }
+ }
+
+ self['plugins'] = {
+ }
+
+
+ def for_plugin(self, plugin_object):
+ class_ = plugin_object.__class__
+ return self[class_.__module__ + '.' class_.__name__]
diff --git a/src/mousetrap/gui.py b/src/mousetrap/gui.py
index 72c54d2..1ed56cf 100644
--- a/src/mousetrap/gui.py
+++ b/src/mousetrap/gui.py
@@ -2,18 +2,23 @@
All things GUI.
'''
+
+import logging
+LOGGER = logging.getLogger(__name__)
+
+
from gi.repository import Gtk
from gi.repository import Gdk
+
from Xlib.display import Display as XlibDisplay
from Xlib.ext import xtest
from Xlib import X
-import mousetrap.log as log
-LOGGER = log.get_logger(__name__)
class ImageWindow(object):
- def __init__(self, message):
+ def __init__(self, config, message):
+ self._config = config
self._window = Gtk.Window(title=message)
self._canvas = Gtk.Image()
self._window.add(self._canvas)
@@ -34,7 +39,8 @@ class ImageWindow(object):
class Gui(object):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self._windows = {}
def show_image(self, window_name, image):
@@ -42,7 +48,7 @@ class Gui(object):
May reuse named windows.
'''
if window_name not in self._windows:
- self._windows[window_name] = ImageWindow(window_name)
+ self._windows[window_name] = ImageWindow(self._config, window_name)
self._windows[window_name].draw(image)
def start(self):
@@ -59,7 +65,8 @@ class Gui(object):
class Pointer(object):
BUTTON_LEFT = X.Button1
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
gdk_display = Gdk.Display.get_default()
device_manager = gdk_display.get_device_manager()
self._pointer = device_manager.get_client_pointer()
diff --git a/src/mousetrap/image.py b/src/mousetrap/image.py
index 100344e..f1c5ae4 100644
--- a/src/mousetrap/image.py
+++ b/src/mousetrap/image.py
@@ -10,7 +10,8 @@ _GDK_PIXBUF_BIT_PER_SAMPLE = 8
class Image(object):
- def __init__(self, image_cv, is_grayscale=False):
+ def __init__(self, config, image_cv, is_grayscale=False):
+ self._config = config
self._image_cv = image_cv
self._is_grayscale = is_grayscale
self._image_cv_grayscale = None
diff --git a/src/mousetrap/main.py b/src/mousetrap/main.py
index 44b4899..1d0a209 100644
--- a/src/mousetrap/main.py
+++ b/src/mousetrap/main.py
@@ -2,49 +2,46 @@
Where it all begins.
'''
-import mousetrap.log as log
-from gi.repository import GObject, Gdk, Gtk
-from mousetrap.gui import Gui, Pointer
-from mousetrap.vision import Camera
+
+from mousetrap.config import Config
+CONFIG = Config()
-LOGGER = log.get_logger('mousetrap.main')
+import logging
+import logging.config
+logging.config.dictConfig(CONFIG['logging'])
+LOGGER = logging.getLogger('mousetrap.main')
-#TODO: Should be a configuration file.
-DEFAULT_PARTS = [
- ('camera', 'mousetrap.plugins.camera.CameraPlugin'),
- ('display', 'mousetrap.plugins.display.DisplayPlugin'),
- ('nose_joystick', 'mousetrap.plugins.nose_joystick.NoseJoystickPlugin'),
- ('eye_click', 'mousetrap.plugins.eyes.EyesPlugin'),
- ]
-DEFAULT_LOOPS_PER_SECOND = 10
+from gi.repository import GObject, Gdk, Gtk
+from mousetrap.gui import Gui, Pointer
+from mousetrap.vision import Camera
class App(object):
- def __init__(self):
+ def __init__(self, config):
+ self.config = config
self.image = None
- self.loop = Loop(self)
- self.gui = Gui()
- self.camera = Camera()
- self.pointer = Pointer()
+ self.loop = Loop(config, self)
+ self.gui = Gui(config)
+ self.camera = Camera(config)
+ self.pointer = Pointer(config)
self.plugins = []
self._assemble_plugins()
def _assemble_plugins(self):
- self._load_plugins(DEFAULT_PARTS)
+ self._load_plugins()
self._register_plugins_with_loop()
- def _load_plugins(self, plugin_descriptors):
- for name, class_ in plugin_descriptors:
+ def _load_plugins(self):
+ for class_ in self.config['assembly']:
self.plugins.append(self._load_plugin(class_))
- @staticmethod
- def _load_plugin(class_):
+ def _load_plugin(self, class_):
LOGGER.debug('loading %s', class_)
class_path = class_.split('.')
module = __import__('.'.join(class_path[:-1]), {}, {}, class_path[-1])
- return getattr(module, class_path[-1])()
+ return getattr(module, class_path[-1])(self.config)
def _register_plugins_with_loop(self):
for plugin in self.plugins:
@@ -56,7 +53,8 @@ class App(object):
class Observable(object):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self.__observers = []
self.__arguments = {}
@@ -76,21 +74,21 @@ class Loop(Observable):
MILLISECONDS_PER_SECOND = 1000.0
CALLBACK_RUN = 'run'
- def __init__(self, app):
- super(Loop, self).__init__()
- self.set_loops_per_second(DEFAULT_LOOPS_PER_SECOND)
+ def __init__(self, config, app):
+ super(Loop, self).__init__(config)
+ self._set_loops_per_second(app.config['loops_per_second'])
self._timeout_id = None
self._add_argument('app', app)
- def set_loops_per_second(self, loops_per_second):
+ def _set_loops_per_second(self, loops_per_second):
self._loops_per_second = loops_per_second
self._interval = int(round(
self.MILLISECONDS_PER_SECOND / self._loops_per_second))
def start(self):
- self.timeout_id = GObject.timeout_add(self._interval, self.run)
+ self.timeout_id = GObject.timeout_add(self._interval, self._run)
- def run(self):
+ def _run(self):
CONTINUE = True
PAUSE = False
self._fire(self.CALLBACK_RUN)
@@ -98,4 +96,4 @@ class Loop(Observable):
if __name__ == '__main__':
- App().run()
+ App(CONFIG).run()
diff --git a/src/mousetrap/plugins/camera.py b/src/mousetrap/plugins/camera.py
index 1e79d8f..516ded4 100644
--- a/src/mousetrap/plugins/camera.py
+++ b/src/mousetrap/plugins/camera.py
@@ -2,5 +2,8 @@ import mousetrap.plugins.interface as interface
class CameraPlugin(interface.Plugin):
+ def __init__(self, config):
+ self._config = config
+
def run(self, app):
app.image = app.camera.read_image()
diff --git a/src/mousetrap/plugins/display.py b/src/mousetrap/plugins/display.py
index 7bc7aae..2cc6804 100644
--- a/src/mousetrap/plugins/display.py
+++ b/src/mousetrap/plugins/display.py
@@ -3,5 +3,8 @@ import logging
class DisplayPlugin(interface.Plugin):
+ def __init__(self, config):
+ self._config = config
+
def run(self, app):
app.gui.show_image('MouseTrap', app.image)
diff --git a/src/mousetrap/plugins/eyes.py b/src/mousetrap/plugins/eyes.py
index 6cf4543..1f2ce0d 100644
--- a/src/mousetrap/plugins/eyes.py
+++ b/src/mousetrap/plugins/eyes.py
@@ -1,15 +1,16 @@
-import mousetrap.plugins.interface as interface
-from mousetrap.vision import FeatureDetector, FeatureNotFoundException
-import mousetrap.log as log
+import logging
+LOGGER = logging.getLogger(__name__)
-LOGGER = log.get_logger(__name__)
+import mousetrap.plugins.interface as interface
+from mousetrap.vision import FeatureDetector, FeatureNotFoundException
class EyesPlugin(interface.Plugin):
- def __init__(self):
- self._motion_detector = MotionDetector()
- self._closed_detector = ClosedDetector()
+ def __init__(self, config):
+ self._config = config
+ self._motion_detector = MotionDetector(config)
+ self._closed_detector = ClosedDetector(config)
def run(self, app):
self._motion_detector.update(app.pointer)
@@ -22,9 +23,10 @@ class EyesPlugin(interface.Plugin):
class MotionDetector(object):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self._max_samples = 5
- self._history = History(self._max_samples)
+ self._history = History(config, self._max_samples)
def update(self, pointer):
self._history.append(pointer.get_position())
@@ -35,13 +37,14 @@ class MotionDetector(object):
class ClosedDetector(object):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self._max_samples = 15
self._min_fraction_to_be_closed = 0.8
self._min_misses_to_be_closed = int(
self._min_fraction_to_be_closed * self._max_samples)
- self._left_locator = LeftEyeLocator()
- self._detection_history = History(self._max_samples)
+ self._left_locator = LeftEyeLocator(config)
+ self._detection_history = History(config, self._max_samples)
def update(self, image):
self._detection_history.append(self._left_locator.locate(image))
@@ -56,22 +59,26 @@ class ClosedDetector(object):
class LeftEyeLocator(object):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self._face_detector = FeatureDetector(
- "face",
- scale_factor=1.5,
- min_neighbors=5,
- )
+ config,
+ "face",
+ scale_factor=1.5,
+ min_neighbors=5,
+ )
self._open_eye_detector = FeatureDetector(
- "open_eye",
- scale_factor=1.1,
- min_neighbors=3,
- )
+ config,
+ "open_eye",
+ scale_factor=1.1,
+ min_neighbors=3,
+ )
self._left_eye_detector = FeatureDetector(
- "left_eye",
- scale_factor=1.5,
- min_neighbors=10,
- )
+ config,
+ "left_eye",
+ scale_factor=1.5,
+ min_neighbors=10,
+ )
def locate(self, image):
face = None
@@ -101,8 +108,9 @@ class LeftEyeLocator(object):
class History(list):
- def __init__(self, max_length):
+ def __init__(self, config, max_length):
super(History, self).__init__()
+ self._config = config
self._max_length = max_length
def append(self, value):
diff --git a/src/mousetrap/plugins/nose.py b/src/mousetrap/plugins/nose.py
index 284494b..01e5a3b 100644
--- a/src/mousetrap/plugins/nose.py
+++ b/src/mousetrap/plugins/nose.py
@@ -4,7 +4,8 @@ from mousetrap.gui import Gui
class NosePlugin(interface.Plugin):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self._nose_locator = NoseLocator()
self._gui = Gui()
self._location = None
@@ -35,11 +36,12 @@ class NosePlugin(interface.Plugin):
class NoseLocator(object):
- def __init__(self):
+ def __init__(self, config):
+ self._config = config
self._face_detector = FeatureDetector(
- 'face', scale_factor=1.5, min_neighbors=5)
+ config, 'face', scale_factor=1.5, min_neighbors=5)
self._nose_detector = FeatureDetector(
- 'nose', scale_factor=1.1, min_neighbors=5)
+ config, 'nose', scale_factor=1.1, min_neighbors=5)
def locate(self, image):
face = self._face_detector.detect(image)
diff --git a/src/mousetrap/plugins/nose_joystick.py b/src/mousetrap/plugins/nose_joystick.py
index a735815..5f3cc20 100644
--- a/src/mousetrap/plugins/nose_joystick.py
+++ b/src/mousetrap/plugins/nose_joystick.py
@@ -6,8 +6,9 @@ from mousetrap.plugins.nose import NoseLocator
class NoseJoystickPlugin(interface.Plugin):
THRESHOLD = 5
- def __init__(self):
- self._nose_locator = NoseLocator()
+ def __init__(self, config):
+ self._config = config
+ self._nose_locator = NoseLocator(config)
self._initial_image_location = (0, 0)
self._last_delta = (0, 0)
diff --git a/src/mousetrap/vision.py b/src/mousetrap/vision.py
index c6eaae8..f130175 100644
--- a/src/mousetrap/vision.py
+++ b/src/mousetrap/vision.py
@@ -12,7 +12,8 @@ class Camera(object):
S_CAPTURE_READ_ERROR = 'Error while capturing. Camera disconnected?'
SEARCH_FOR_DEVICE = -1
- def __init__(self, device_index=SEARCH_FOR_DEVICE, width=400, height=300):
+ def __init__(self, config, device_index=SEARCH_FOR_DEVICE, width=400, height=300):
+ self._config = config
self._device = self._new_capture_device(device_index)
self.set_dimensions(width, height)
@@ -37,7 +38,7 @@ class Camera(object):
if not ret:
raise IOError(self.S_CAPTURE_READ_ERROR)
- return Image(image)
+ return Image(self._config, image)
class HaarLoader(object):
@@ -86,7 +87,7 @@ class HaarNameError(Exception):
class FeatureDetector(object):
- def __init__(self, name, scale_factor=1.1, min_neighbors=3):
+ def __init__(self, config, name, scale_factor=1.1, min_neighbors=3):
'''
name - name of feature to detect
@@ -96,6 +97,7 @@ class FeatureDetector(object):
min_neighbors - how many neighbors each candidate rectangle should have
to retain it. Default 3.
'''
+ self._config = config
self._name = name
self._single = None
self._plural = None
@@ -140,6 +142,7 @@ class FeatureDetector(object):
to_x = single['x'] + single['width']
image_cv_grayscale = self._image.to_cv_grayscale()
single["image"] = Image(
+ self._config,
image_cv_grayscale[from_y:to_y, from_x:to_x],
is_grayscale=True)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]