Search code examples
pythonc++opencvbitwise-and

How to simulate short circuit and in opencv


I am trying to check whether a binary image (template) is contained inside another image (source). To do that, I first started doing something like this:

(its a pseudo code resembling python, but I'm more interested in the right technique than in the language implementation)

#this code runs once at startup
template_nonzero = count_nonzero(template)

#this code is run inside a function
mask = bitwise_and(template, source)
is_contained = count_nonzero(mask) == template_nonzero

Then I realized I could speed things up by avoiding count_nonzero:

mask = bitwise_and(template, source)
mask_against_template = bitwise_xor(template, mask)
is_contained = not mask_against_template.any()

This code is almost 3 times faster than the first one. I'm now wondering if there is such a thing as a short circuit and operator in opencv that would return true if bitwise_and is true for all white pixels or false upon finding the first false operation. This way I wouldnt have to use xor or even run through the entire image in a bitwise_and.

Any ideas?

Edit:

I forgot to mention that I even tried this code, but using xor is a bit faster than using ==:

mask = bitwise_and(template, source)
mask_against_template = template == mask
is_contained = mask_against_template.all()

Solution

  • I ended up finding a solution. I implemented the short-circuit and operation in python which turned out to be a lot slower than the cv2.bitwise_and followed by a cv2.bitwise_xor. But then I used numba to pre compile that function and I ended up having a function that runs 4x as fast as the cv2 one. Here's the code:

    @numba.jit("b1(u1[:,:],u1[:,:])")
    def is_template_in(template, image):
        for y in range(0, template.shape[0]):
            for x in range(0, template.shape[1]):
                if template[y][x] and not image[y][x]:
                    return False
        return True