2

I was trying to use QImage for loading image and checking the equality with a template sub-image that moves all over the image. The code is as:

for i in range(image.height() - backgroundMask.height() + 1):
        for j in range(image.width() - backgroundMask.width() + 1):
            subsection = image.copy(j, i, j + backgroundMask.width() - 1, i + backgroundMask.height() - 1)
            if subsection == backgroundMask:
                print 'equality action here'
            else:
                print 'non-equality action here'

The problem is that its taking too much time to do this. Similar operation using Python Imaging Library was too fast. The two major operations are copy() and operator==() . I think that major time is being spent in the copy() as it performs the copy there only. If it had been just a lazy copy-on-write operation then it would have been faster.

Is there any way to do it faster?

Xolve
  • 22,298
  • 21
  • 77
  • 125

1 Answers1

0

The faster way to do it is to compare the pixels by hand – the copies you're doing are wasteful. Suppose you want to find backgroundMask as a subimage of 'image'. You start at the top left corner. Now you find that pixel (0, 0) of image doesn't match (0, 0) of backgroundMask. If you're comparing pixels by hand, you just continue over to (0, 1) of image and compare that with (0, 0), and so on. But in your case, you've wasted ages copying width x height pixels already.

start = time.time()
for i in xrange(image.height() - backgroundMask.height() + 1):
    for j in xrange(image.width() - backgroundMask.width() + 1):
        success = True
        for y in xrange(backgroundMask.height()):
            for x in xrange(backgroundMask.width()):
                if image.pixel(j + x, i + y) != backgroundMask.pixel(x, y):
                    success = False
                    break
            if not success:
                break

        if success:
            print 'match'
        else:
            print 'no match'

Admittedly per-pixel access is slow in Python and the equality operator is written in C. But it's still significantly faster than what you posted. For the image I tried on, your code took 27 seconds and mine took 0.8.

However, the best solution is probably to convert the QImage to a PIL Image if this functionality is implemented there. The conversion between QImages and PIL images is simple and well-documented.

PAG
  • 1,836
  • 1
  • 18
  • 19
  • This is the problem nagging me. Python loops are slow and not as optimized. – Xolve Jun 05 '11 at 12:15
  • But this algorithm is significantly better than the one you've used, despite that part of yours is pushed into C++. Else use the PIL method I've suggested. – PAG Jun 05 '11 at 12:29