[mousetrap/gnome3-wip: 214/240] Add FeatureDetector caching.
- From: Heidi Ellis <heidiellis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mousetrap/gnome3-wip: 214/240] Add FeatureDetector caching.
- Date: Mon, 8 Sep 2014 15:30:33 +0000 (UTC)
commit 5a0a51b3fdaa2050a6ac6747d8301e92e170da14
Author: Stoney Jackson <dr stoney gmail com>
Date: Sun Jun 29 14:01:00 2014 -0400
Add FeatureDetector caching.
src/mousetrap/image.py | 6 ++++
src/mousetrap/mousetrap.yaml | 1 +
src/mousetrap/plugins/eyes.py | 6 ++--
src/mousetrap/plugins/nose.py | 4 +-
src/mousetrap/vision.py | 57 ++++++++++++++++++++++++++++++++++++-----
5 files changed, 62 insertions(+), 12 deletions(-)
---
diff --git a/src/mousetrap/image.py b/src/mousetrap/image.py
index 02a714b..1eed2be 100644
--- a/src/mousetrap/image.py
+++ b/src/mousetrap/image.py
@@ -36,6 +36,12 @@ class Image(object):
def get_height(self):
return self._image_cv.shape[1]
+ def __hash__(self):
+ return id(self)
+
+ def __eq__(self, other):
+ return hash(self) == hash(other)
+
def _cv_rgb_to_cv_grayscale(image):
return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
diff --git a/src/mousetrap/mousetrap.yaml b/src/mousetrap/mousetrap.yaml
index d9dcf0a..052c358 100644
--- a/src/mousetrap/mousetrap.yaml
+++ b/src/mousetrap/mousetrap.yaml
@@ -5,6 +5,7 @@ assembly:
- mousetrap.plugins.display.DisplayPlugin
- mousetrap.plugins.nose.NoseJoystickPlugin
- mousetrap.plugins.eyes.EyesPlugin
+- mousetrap.vision.FeatureDetectorClearCachePlugin
# camera - Configuration for the built-in camera.
diff --git a/src/mousetrap/plugins/eyes.py b/src/mousetrap/plugins/eyes.py
index bf380d4..25018fb 100644
--- a/src/mousetrap/plugins/eyes.py
+++ b/src/mousetrap/plugins/eyes.py
@@ -62,19 +62,19 @@ class LeftEyeLocator(object):
def __init__(self, config):
self._config = config
- self._face_detector = FeatureDetector(
+ self._face_detector = FeatureDetector.get_detector(
config,
"face",
scale_factor=config[self]['face_detector']['scale_factor'],
min_neighbors=config[self]['face_detector']['min_neighbors'],
)
- self._open_eye_detector = FeatureDetector(
+ self._open_eye_detector = FeatureDetector.get_detector(
config,
"open_eye",
scale_factor=config[self]['open_eye_detector']['scale_factor'],
min_neighbors=config[self]['open_eye_detector']['min_neighbors'],
)
- self._left_eye_detector = FeatureDetector(
+ self._left_eye_detector = FeatureDetector.get_detector(
config,
"left_eye",
scale_factor=config[self]['left_eye_detector']['scale_factor'],
diff --git a/src/mousetrap/plugins/nose.py b/src/mousetrap/plugins/nose.py
index 4192419..12283bc 100644
--- a/src/mousetrap/plugins/nose.py
+++ b/src/mousetrap/plugins/nose.py
@@ -98,13 +98,13 @@ class NoseJoystickPlugin(interface.Plugin):
class NoseLocator(object):
def __init__(self, config):
self._config = config
- self._face_detector = FeatureDetector(
+ self._face_detector = FeatureDetector.get_detector(
config,
'face',
scale_factor=config[self]['face_detector']['scale_factor'],
min_neighbors=config[self]['face_detector']['min_neighbors'],
)
- self._nose_detector = FeatureDetector(
+ self._nose_detector = FeatureDetector.get_detector(
config,
'nose',
scale_factor=config[self]['nose_detector']['scale_factor'],
diff --git a/src/mousetrap/vision.py b/src/mousetrap/vision.py
index 0957f4f..3ea0cf8 100644
--- a/src/mousetrap/vision.py
+++ b/src/mousetrap/vision.py
@@ -6,6 +6,7 @@ import cv2
import cv
from mousetrap.i18n import _
from mousetrap.image import Image
+import mousetrap.plugins.interface as interface
import logging
LOGGER = logging.getLogger(__name__)
@@ -87,6 +88,23 @@ class HaarNameError(Exception):
class FeatureDetector(object):
+
+ _INSTANCES = {}
+
+ @classmethod
+ def get_detector(cls, config, name, scale_factor=1.1, min_neighbors=3):
+ if name in cls._INSTANCES:
+ LOGGER.info("Reusing %s detector." % name)
+ return cls._INSTANCES[name]
+ cls._INSTANCES[name] = FeatureDetector(
+ config, name, scale_factor, min_neighbors)
+ return cls._INSTANCES[name]
+
+ @classmethod
+ def clear_all_detection_caches(cls):
+ for name, instance in cls._INSTANCES.items():
+ instance.clear_cache()
+
def __init__(self, config, name, scale_factor=1.1, min_neighbors=3):
'''
name - name of feature to detect
@@ -97,6 +115,7 @@ class FeatureDetector(object):
min_neighbors - how many neighbors each candidate rectangle should have
to retain it. Default 3.
'''
+ LOGGER.info("Building %s detector." % name)
self._config = config
self._name = name
self._single = None
@@ -106,15 +125,28 @@ class FeatureDetector(object):
self._scale_factor = scale_factor
self._min_neighbors = min_neighbors
self._last_attempt_successful = False
+ self._detect_cache = {}
def detect(self, image):
- self._image = image
- self._detect_plural()
- self._exit_if_none_detected()
- self._unpack_first()
- self._extract_image()
- self._calculate_center()
- return self._single
+ if image in self._detect_cache:
+ LOGGER.debug("Detection cache hit: %(image)d -> %(result)s" %
+ {'image':id(image), 'result':self._detect_cache[image]}
+ )
+ if isinstance(self._detect_cache[image], FeatureNotFoundException):
+ raise FeatureNotFoundException(str(self._detect_cache[image]))
+ return self._detect_cache[image]
+ try:
+ self._image = image
+ self._detect_plural()
+ self._exit_if_none_detected()
+ self._unpack_first()
+ self._extract_image()
+ self._calculate_center()
+ self._detect_cache[image] = self._single
+ return self._detect_cache[image]
+ except FeatureNotFoundException as exception:
+ self._detect_cache[image] = exception
+ raise
def _detect_plural(self):
self._plural = self._cascade.detectMultiScale(
@@ -157,6 +189,17 @@ class FeatureDetector(object):
is_grayscale=True,
)
+ def clear_cache(self):
+ self._detect_cache.clear()
+
+
+class FeatureDetectorClearCachePlugin(interface.Plugin):
+ def __init__(self, config):
+ self._config = config
+
+ def run(self, app):
+ FeatureDetector.clear_all_detection_caches()
+
class FeatureNotFoundException(Exception):
pass
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]