~ubuntu-branches/ubuntu/saucy/mago/saucy

« back to all changes in this revision

Viewing changes to xpresser/tests/test_opencvfinder.py

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2011-02-08 13:32:13 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110208133213-m1og7ey0m990chg6
Tags: 0.3+bzr20-0ubuntu1
* debian/rules:
  - updated to debhelper 7
  - use dh_python2 instead of python-central
* debian/pycompat:
  - removed, no longer needed
* debian/control:
  - dropped cdbs and python-central dependencies
* bzr snapshot of the current trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright (c) 2010 Canonical
 
3
#
 
4
# Written by Gustavo Niemeyer <gustavo@niemeyer.net>
 
5
#
 
6
# This file is part of the Xpresser GUI automation library.
 
7
#
 
8
# Xpresser is free software; you can redistribute it and/or modify
 
9
# it under the terms of the GNU Lesser General Public License version 3,
 
10
# as published by the Free Software Foundation.
 
11
#
 
12
# Xpresser is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU Lesser General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU Lesser General Public License
 
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
#
 
20
import opencv
 
21
import gtk
 
22
 
 
23
from xpresser.image import Image
 
24
from xpresser.opencvfinder import OpenCVFinder
 
25
 
 
26
from xpresser.lib.testing import TestCase
 
27
from xpresser.tests.images import get_image_path
 
28
 
 
29
 
 
30
class OpenCVFinderTest(TestCase):
 
31
 
 
32
    def setUp(self):
 
33
        self.screen_image = Image(filename=get_image_path("screen.png"))
 
34
        self.red_square = Image(filename=get_image_path("red-square.png"))
 
35
        self.red_circle = Image(filename=get_image_path("red-circle.png"))
 
36
        self.red_ellipse = Image(filename=get_image_path("red-ellipse.png"))
 
37
        self.green_square = Image(filename=get_image_path("green-square.png"))
 
38
        self.yellow_square = Image(filename=get_image_path("yellow-square.png"))
 
39
        self.yellow_circle = Image(filename=get_image_path("yellow-circle.png"))
 
40
        self.red_circle_with_blue_circle = \
 
41
            Image(filename=get_image_path("red-circle-with-blue-circle.png"))
 
42
        self.finder = OpenCVFinder()
 
43
 
 
44
    def test_loads_widths_and_heights(self):
 
45
        self.finder.find(self.screen_image, self.red_ellipse)
 
46
        self.assertEquals(self.screen_image.width, 300)
 
47
        self.assertEquals(self.screen_image.height, 300)
 
48
        self.assertEquals(self.red_ellipse.width, 40)
 
49
        self.assertEquals(self.red_ellipse.height, 50)
 
50
 
 
51
    def test_find_perfect_match(self):
 
52
        match = self.finder.find(self.screen_image, self.green_square)
 
53
        self.assertEquals(match.image, self.green_square)
 
54
        self.assertEquals(match.x, 200)
 
55
        self.assertEquals(match.y, 0)
 
56
        self.assertEquals(match.similarity, 1.0)
 
57
 
 
58
    def test_find_perfect_match_with_low_threshold(self):
 
59
        self.green_square.similarity = 0.7
 
60
        match = self.finder.find(self.screen_image, self.green_square)
 
61
        self.assertEquals(match.image, self.green_square)
 
62
        self.assertEquals(match.x, 200)
 
63
        self.assertEquals(match.y, 0)
 
64
 
 
65
    def test_find_all_with_perfect_match(self):
 
66
        matches = self.finder.find_all(self.screen_image, self.green_square)
 
67
        self.assertEquals(len(matches), 1)
 
68
        self.assertEquals(matches[0].image, self.green_square)
 
69
        self.assertEquals(matches[0].x, 200)
 
70
        self.assertEquals(matches[0].y, 0)
 
71
        self.assertEquals(matches[0].similarity, 1.0)
 
72
 
 
73
    def test_find_all_with_low_threshold_containing_perfect_match(self):
 
74
        self.red_circle.similarity = 0.8
 
75
        matches = self.finder.find_all(self.screen_image, self.red_circle)
 
76
        self.assertTrue(len(matches) > 1)
 
77
        self.assertTrue(min(m.similarity for m in matches) >= 0.8)
 
78
 
 
79
    def test_no_matches(self):
 
80
        match = self.finder.find(self.screen_image,
 
81
                                 self.red_circle_with_blue_circle)
 
82
        self.assertEquals(match, None)
 
83
 
 
84
    def test_fuzzy_match(self):
 
85
        self.red_circle_with_blue_circle.similarity = 0.9
 
86
        match = self.finder.find(self.screen_image,
 
87
                                 self.red_circle_with_blue_circle)
 
88
        self.assertEquals(match.image, self.red_circle_with_blue_circle)
 
89
        self.assertEquals(match.x, 100)
 
90
        self.assertEquals(match.y, 200)
 
91
 
 
92
    def test_self_match(self):
 
93
        """
 
94
        This test will explore a bug in the Python OpenCV bindings.  It
 
95
        will handle the dimensions of the result matrix in a different
 
96
        way when there's a single result.
 
97
        """
 
98
        match = self.finder.find(self.red_circle, self.red_circle)
 
99
        self.assertEquals(match.x, 0)
 
100
        self.assertEquals(match.y, 0)
 
101
 
 
102
    def test_opencv_image_cache(self):
 
103
        match = self.finder.find(self.red_circle, self.yellow_circle)
 
104
        opencv_image = self.red_circle.cache.get("opencv_image")
 
105
        self.assertEquals(match, None)
 
106
        self.assertNotEquals(opencv_image, None)
 
107
        self.assertEquals(type(opencv_image), opencv.CvMat)
 
108
 
 
109
        # Let's ensure the cache is *actually* in use.
 
110
        self.red_circle.cache["opencv_image"] = \
 
111
            self.yellow_circle.cache["opencv_image"]
 
112
 
 
113
        match = self.finder.find(self.red_circle, self.yellow_circle)
 
114
        self.assertNotEquals(match, None)
 
115
 
 
116
    def test_filtering_of_similar_matches(self):
 
117
        """
 
118
        This example would actually have hundreds of matches if there was
 
119
        no filtering per proximity and match quality.  The filtering
 
120
        algorithm is not entirely trivial, and likely has other cases
 
121
        which need to be covered by individual unit tests too.
 
122
        """
 
123
        self.red_circle.similarity = 0.8
 
124
        matches = self.finder.find_all(self.screen_image, self.red_circle)
 
125
        matches.sort(key=lambda match: -match.similarity)
 
126
        self.assertEquals(len(matches), 2)
 
127
        self.assertEquals(matches[0].x, 100)
 
128
        self.assertEquals(matches[0].y, 200)
 
129
        self.assertEquals(matches[1].x, 198)
 
130
        self.assertEquals(matches[1].y, 100)
 
131
 
 
132
    def test_find_with_array_image(self):
 
133
        # Reset the image, including the cache (shouldn't be needed, but
 
134
        # just to be 100% sure).
 
135
        self.green_square.cache.clear()
 
136
        filename = self.green_square.filename
 
137
        self.green_square.filename = None
 
138
 
 
139
        # Use gtk to transform the image into a numpy array, and set it
 
140
        # back into the image.
 
141
        pixbuf = gtk.image_new_from_file(filename).get_pixbuf()
 
142
        self.green_square.array = pixbuf.get_pixels_array()
 
143
 
 
144
        # Try to match normally.
 
145
        match = self.finder.find(self.screen_image, self.green_square)
 
146
        self.assertEquals(match.image, self.green_square)
 
147
        self.assertEquals(match.x, 200)
 
148
        self.assertEquals(match.y, 0)
 
149
        self.assertEquals(match.similarity, 1.0)
 
150