[mousetrap/gnome3-wip: 56/240] Add gui, main, and vision. Lots of renames.
- From: Heidi Ellis <heidiellis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mousetrap/gnome3-wip: 56/240] Add gui, main, and vision. Lots of renames.
- Date: Mon, 8 Sep 2014 15:17:15 +0000 (UTC)
commit 07177f8964883f1176de6372255760a98c9a1311
Author: Stoney Jackson <dr stoney gmail com>
Date: Wed Jun 4 20:11:18 2014 -0400
Add gui, main, and vision. Lots of renames.
src/mousetrap/Makefile.am | 6 +-
src/mousetrap/camera.py | 32 -----------
src/mousetrap/gui.py | 66 ++++++++++++++++++++++
src/mousetrap/main.py | 34 +++++++++++
src/mousetrap/{mouse.py => pointer.py} | 2 +-
src/mousetrap/test_camera.py | 24 --------
src/mousetrap/{test_mouse.py => test_pointer.py} | 13 ++--
src/mousetrap/test_vision.py | 25 ++++++++
src/mousetrap/vision.py | 37 ++++++++++++
9 files changed, 173 insertions(+), 66 deletions(-)
---
diff --git a/src/mousetrap/Makefile.am b/src/mousetrap/Makefile.am
index 78deb2d..9e4e8de 100644
--- a/src/mousetrap/Makefile.am
+++ b/src/mousetrap/Makefile.am
@@ -5,8 +5,10 @@ mousetrap_pathdir=$(pyexecdir)
mousetrap_python_PYTHON = \
__init__.py \
- camera.py \
- mouse.py
+ vision.py \
+ pointer.py \
+ main.py \
+ gui.py
#SUBDIRS =
diff --git a/src/mousetrap/gui.py b/src/mousetrap/gui.py
new file mode 100644
index 0000000..7c6cde8
--- /dev/null
+++ b/src/mousetrap/gui.py
@@ -0,0 +1,66 @@
+from gi.repository import Gtk
+from gi.repository import GdkPixbuf
+
+
+_GDK_PIXBUF_BIT_PER_SAMPLE = 8
+
+
+class ImageWindow(object):
+ def __init__(self, message):
+ self._window = Gtk.Window(title=message)
+ self._canvas = Gtk.Image()
+ self._window.add(self._canvas)
+
+ # FIXME: Closing any window kills the application. Need a mechanism
+ # that allows windows to be openned and closed, and only kill the
+ # application when the last window is closed.
+ self._window.connect("delete-event", Gtk.main_quit)
+
+ self._window.show_all()
+
+ def draw(self, image):
+ '''Draw image to this window.
+ '''
+ image = _get_pixbuf_from_image(image)
+ self._canvas.set_from_pixbuf(image)
+ self._canvas.queue_draw()
+
+
+def _get_pixbuf_from_image(image):
+ if isinstance(image, GdkPixbuf.Pixbuf):
+ return image
+ return _cvimage_to_pixbuf(image)
+
+
+def _cvimage_to_pixbuf(cvimage):
+ data = cvimage.tostring()
+ colorspace = GdkPixbuf.Colorspace.RGB
+ has_alpha_channel = False
+ width = cvimage.shape[1]
+ height = cvimage.shape[0]
+ return GdkPixbuf.Pixbuf.new_from_data(
+ data,
+ colorspace, # FIXME: Need to handle grayscale.
+ has_alpha_channel,
+ _GDK_PIXBUF_BIT_PER_SAMPLE,
+ width,
+ height,
+ cvimage.strides[0], # FIXME: what is this parameter?
+ None, # FIXME: what is this parameter?
+ None # FIXME: what is this parameter?
+ )
+
+
+_WINDOWS = {}
+def show_image(window_name, image):
+ '''Displays image in window named by window_name.
+ May reuse named windows.
+ '''
+ if window_name not in _WINDOWS:
+ _WINDOWS[window_name] = ImageWindow(window_name)
+ _WINDOWS[window_name].draw(image)
+
+
+def start():
+ '''Start handling events.'''
+ Gtk.main()
diff --git a/src/mousetrap/main.py b/src/mousetrap/main.py
new file mode 100644
index 0000000..4d78855
--- /dev/null
+++ b/src/mousetrap/main.py
@@ -0,0 +1,34 @@
+from gi.repository import GObject
+
+import mousetrap.vision as vision
+import mousetrap.gui as gui
+
+
+# OpenCV will automatically search for a working camera device if we use the
+# index -1.
+DEVICE_INDEX = -1
+IMAGE_MAX_WIDTH = 400
+IMAGE_MAX_HEIGHT = 300
+FPS = 5
+INTERVAL = int(round(1000.0 / FPS))
+
+
+class Main(object):
+ def __init__(self):
+ self.image = None
+ self.timeout_id = None
+ self.camera = vision.Camera(DEVICE_INDEX,
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT)
+
+ def run(self):
+ self.timeout_id = GObject.timeout_add(INTERVAL, self.on_timeout, None)
+ gui.start()
+
+ def on_timeout(self, user_data):
+ self.image = self.camera.read_image()
+ gui.show_image('diff', self.image)
+ return True
+
+
+if __name__ == '__main__':
+ Main().run()
diff --git a/src/mousetrap/mouse.py b/src/mousetrap/pointer.py
similarity index 95%
rename from src/mousetrap/mouse.py
rename to src/mousetrap/pointer.py
index 1011ec5..060b865 100644
--- a/src/mousetrap/mouse.py
+++ b/src/mousetrap/pointer.py
@@ -1,7 +1,7 @@
from gi.repository import Gdk
-class Mouse(object):
+class Pointer(object):
def __init__(self):
gdk_display = Gdk.Display.get_default()
diff --git a/src/mousetrap/test_mouse.py b/src/mousetrap/test_pointer.py
similarity index 59%
rename from src/mousetrap/test_mouse.py
rename to src/mousetrap/test_pointer.py
index 2bb215d..f02d11e 100644
--- a/src/mousetrap/test_mouse.py
+++ b/src/mousetrap/test_pointer.py
@@ -1,15 +1,14 @@
import unittest
-from mousetrap.mouse import Mouse
+import mousetrap.pointer as pointer
-class test_mouse(unittest.TestCase):
+class test_pointer(unittest.TestCase):
def setUp(self):
- self.mouse = Mouse()
+ self.pointer = pointer.Pointer()
def test_get_position(self):
- x, y = self.mouse.get_position()
-
+ x, y = self.pointer.get_position()
try:
x += 1
y += 1
@@ -17,8 +16,8 @@ class test_mouse(unittest.TestCase):
self.assertTrue(False, msg='x or y is not a number')
def test_set_position(self):
- self.mouse.set_position((3, 4))
- x, y = self.mouse.get_position()
+ self.pointer.set_position((3, 4))
+ x, y = self.pointer.get_position()
self.assertEquals(3, x)
self.assertEquals(4, y)
diff --git a/src/mousetrap/test_vision.py b/src/mousetrap/test_vision.py
new file mode 100644
index 0000000..f01528a
--- /dev/null
+++ b/src/mousetrap/test_vision.py
@@ -0,0 +1,25 @@
+import unittest
+import mousetrap.vision as vision
+
+# OpenCV will automatically search for a working camera device if we use the
+# index -1.
+DEVICE_INDEX = -1
+IMAGE_MAX_WIDTH = 400
+IMAGE_MAX_HEIGHT = 300
+
+class test_camera(unittest.TestCase):
+
+ def setUp(self):
+ self.camera = vision.Camera(DEVICE_INDEX,
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT)
+
+ def test_get_image_imageReturned(self):
+ image = self.camera.read_image()
+ self.assertTrue(
+ image is not None,
+ msg="Error: Image not captured"
+ )
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/mousetrap/vision.py b/src/mousetrap/vision.py
new file mode 100644
index 0000000..23d9cfb
--- /dev/null
+++ b/src/mousetrap/vision.py
@@ -0,0 +1,37 @@
+'''
+All things computer vision. Isolates OpenCV from the rest of the system.
+If you see another file using OpenCV directly, it should probably be using
+this module instead.
+'''
+
+import cv2
+from cv2 import cv
+
+
+S_CAPTURE_OPEN_ERROR = 'Device #%s does not support video capture interface'
+S_CAPTURE_READ_ERROR = 'Error while capturing. Camera disconnected?'
+
+
+class Camera(object):
+ def __init__(self, device_index, width, height):
+ self.device = self._new_capture_device(device_index)
+ self._set_dimensions(width, height)
+
+ @staticmethod
+ def _new_capture_device(device_index):
+ capture = cv2.VideoCapture(device_index)
+ if not capture.isOpened():
+ capture.release()
+ raise IOError(S_CAPTURE_OPEN_ERROR % device_index)
+ return capture
+
+ def _set_dimensions(self, width, height):
+ self.device.set(cv.CV_CAP_PROP_FRAME_WIDTH, width)
+ self.device.set(cv.CV_CAP_PROP_FRAME_HEIGHT, height)
+
+ def read_image(self):
+ ret, image = self.device.read()
+ if not ret:
+ raise IOError(S_CAPTURE_READ_ERROR)
+ return image
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]