~xpresser-team/xpresser/cleanup

« back to all changes in this revision

Viewing changes to xpresser/opencvfinder.py

  • Committer: Chris Wayne
  • Date: 2012-07-05 13:52:37 UTC
  • mfrom: (10.1.6 gtk3-port-with-cairo)
  • Revision ID: chris.wayne@canonical.com-20120705135237-7f52h9sfxwu279dr
Merging in gtk3 support with simple cv, adding debian packaging

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
# You should have received a copy of the GNU Lesser General Public License
18
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
19
#
20
 
import math
21
 
import time
22
 
 
23
 
import numpy
24
 
 
25
 
import opencv
26
 
import opencv.highgui
27
 
import opencv.adaptors
28
 
 
 
20
import SimpleCV
29
21
from xpresser.imagematch import ImageMatch
30
22
 
31
23
 
32
24
FILTER_MARGIN = 25 # %
33
25
 
34
 
DEBUG_PERFORMANCE = False
35
 
 
36
26
 
37
27
class OpenCVFinder(object):
38
28
 
39
29
    def find(self, screen_image, area_image):
40
30
        matches = self._find(screen_image, area_image, best_match=True)
41
31
        if matches:
42
 
            matches.sort(key=lambda match: -match.similarity)
43
32
            return matches[0]
44
33
        return None
45
34
 
49
38
    def _load_image(self, image):
50
39
        if "opencv_image" not in image.cache:
51
40
            if image.filename is not None:
52
 
                opencv_image = opencv.highgui.cvLoadImage(image.filename)
 
41
                opencv_image = SimpleCV.Image(image.filename)
53
42
            elif image.array is not None:
54
 
                # The adaptor function can't deal with the alpha channel.
55
 
                array = image.array[:,:,:3]
56
 
                opencv_image = opencv.adaptors.NumPy2Ipl(array)
 
43
                opencv_image = image.array
57
44
            else:
58
45
                raise RuntimeError("Oops. Can't load image.")
59
46
            image.cache["opencv_image"] = opencv_image
62
49
        return image.cache["opencv_image"]
63
50
 
64
51
    def _find(self, screen_image, area_image, best_match=False):
65
 
        if DEBUG_PERFORMANCE:
66
 
            started = time.time()
67
 
        screen = self._load_image(screen_image)
68
 
        area = self._load_image(area_image)
69
 
        if DEBUG_PERFORMANCE:
70
 
            print "LOADING IMAGES: %.5fs" % (time.time()-started)
71
 
 
72
 
        result_width = screen.width - area.width + 1
73
 
        result_height = screen.height - area.height + 1
74
 
        result = opencv.cvCreateImage(opencv.cvSize(result_width, result_height),
75
 
                                      opencv.IPL_DEPTH_32F, 1)
76
 
        if DEBUG_PERFORMANCE:
77
 
            started = time.time()
78
 
        opencv.cvMatchTemplate(screen, area, result, opencv.CV_TM_CCORR_NORMED)
79
 
        if DEBUG_PERFORMANCE:
80
 
            print "MATCHING: %.5fs" % (time.time()-started)
81
 
 
82
 
        result = opencv.adaptors.Ipl2NumPy(result)
83
 
 
84
 
        if DEBUG_PERFORMANCE:
85
 
            started = time.time()
86
 
        matches = []
87
 
        for y, x in numpy.argwhere(result >= area_image.similarity):
88
 
            matches.append(ImageMatch(area_image, x, y, result[y, x]))
89
 
            if best_match and result[y, x] == 1.0:
90
 
                return [matches[-1]]
91
 
        if DEBUG_PERFORMANCE:
92
 
            print "FINDING POSITIONS: %.5fs" % (time.time()-started)
 
52
        source = self._load_image(screen_image)
 
53
        template = self._load_image(area_image)
 
54
        results = []
 
55
        matches = source.findTemplate(template, method="CCOEFF_NORM")
 
56
        if matches:
 
57
            for m in [m for m in matches if m.quality >= area_image.similarity]:
 
58
                results.append(
 
59
                    ImageMatch(area_image, m.x, m.y, m.quality))
 
60
                if best_match and m.quality == 1.0:
 
61
                    return [results[-1]]
93
62
 
94
63
        x_margin = int(FILTER_MARGIN/100.0 * area_image.width)
95
64
        y_margin = int(FILTER_MARGIN/100.0 * area_image.height)
96
65
 
97
 
        if DEBUG_PERFORMANCE:
98
 
            started = time.time()
99
 
        matches = self._filter_nearby_positions(matches, x_margin, y_margin)
100
 
        if DEBUG_PERFORMANCE:
101
 
            print "FILTERING: %.5fs" % (time.time()-started)
102
 
        return matches
 
66
        results = self._filter_nearby_positions(results, x_margin, y_margin)
 
67
        if results:
 
68
            results.sort(key=lambda match: -match.similarity)
 
69
 
 
70
        return results
103
71
 
104
72
    def _filter_nearby_positions(self, matches, x_margin, y_margin):
105
73
        """Remove nearby positions by taking the best one.
106
 
        
 
74
 
107
75
        Doing this is necessary because around a good match there will
108
76
        likely be other worse matches.
109
77
        """