5

While in general the new python bindings for opencv (cv2) are a beauty, "masks" don't seem to be working properly - unless I really get something wrong:

For example "cv2.add" still works properly without a mask:

import cv2
a = ones((2,2,3), dtype=uint8)
cv2.add(a,a)

correctly gives

array([[[2, 2, 2],
        [2, 2, 2]],

       [[2, 2, 2],
        [2, 2, 2]]], dtype=uint8)

But when you add a mask (and an out array "b" - which is required by for some reason is not assigned either) you get a RANDOM result, i.e. the result changes when you run the command multiple times

myMask = zeros(a.shape[0:2], dtype = uint8)
mask[1,1] = 255
b = zeros(a.shape)
cv2.add(a,a,b,myMask)
cv2.add(a,a,b,myMask)

gives on my machine (Win7, 32bit,Python 2.7, opencv 2.3.1)

In [34]: cv2.add(a,a,b,myMask)
Out[34]: 
array([[[ 26,   0, 143],
        [  5, 216, 245]],

       [[156,   5, 104],
        [  2,   2,   2]]], dtype=uint8)

In [35]: cv2.add(a,a,b,myMask)
Out[35]: 
array([[[35,  0,  0],
        [ 0,  3,  0]],

       [[ 0,  0,  3],
        [ 2,  2,  2]]], dtype=uint8)

... and something new on the next trial. Now either I get something seriously wrong, or there is a serious problem with the cv2 bindings.

Any suggestions?

2
  • Look like a cv2 issue, prefer to report the issue directly on their website instead of posting the error on stackoverflow! :) Commented Dec 11, 2011 at 17:43
  • Done - thanks for the hint, I did not realize that you can post bugs (i.e. issue "tickets") there. Commented Dec 12, 2011 at 19:29

2 Answers 2

5

Its an interesting question. I am seeing the same problem. I posted a bug and got a reply. http://code.opencv.org/issues/1748

The solution is simple. The dst array is undefined on creation and the operation changes only those destination array pixels p, for which mask(p)!=0.

So the only mechanism that works is to premake dst before addition. I.e.

dst = np.zeros(...)
dst = cv2.add(a, a, dst=dst, mask=mask)

The next release will clear newly created images in operations such as cv2.add, cv2.subtract, cv2.bitwise_and/or/xor - so it will work without problem.

my code looks like:

import cv2
import numpy as np
import time

a = np.ones((2,2,3), dtype=np.uint8)

print "simple add"
t = time.time()
for i in range(10000):
    b = cv2.add(a,a)
print "%5.4f seconds" % (time.time()-t)
print b

print "\nnumpy add"
t = time.time()
for i in range(10000):
    b = a+a
print "%5.4f seconds" % (time.time()-t)
print b

# make mask same dimensions but 1 byte deep(not three)
mask = np.zeros(a.shape[:-1], dtype=np.uint8)
mask[1,1] = 255

print "\nmask", mask.shape
print mask

print "\nmasked add - uninitialised"
t = time.time()
for i in range(10000):
    b = cv2.add(a,a,mask=mask)
print "%5.4f seconds" % (time.time()-t)
print b
print "uninitialised entries are unmodified - so random.\n Inconsistent when run more than once."
print "same calc a second time..."
b = cv2.add(a,a,mask=mask)
print b

print "\nmasked add - using preinitialised dst"
t = time.time()
b = a.copy()
for i in range(10000):
    b = cv2.add(a,a,b,mask=mask)
print "%5.4f seconds" % (time.time()-t)
print b
print "Consistent when run more than once."
print "same calc a second time..."
b = a.copy()
b = cv2.add(a,a,b,mask=mask)
print b

FYI: timings (10k repeats):

cv2.add - no mask            0.0120 seconds
cv2.add - with mask          0.0160 seconds
np.add                       0.0190 seconds
cv2.add - uninitialised mask 0.0220 seconds

FYI: Submit bugs following instructions here: http://code.opencv.org/projects/OpenCV/wiki/WikiStart

Sign up to request clarification or add additional context in comments.

Comments

0

why not use numpy (inplace) masked expression?

b = array(a, copy=True)
b[mask] += a

mask is a boolean array, analog in opencv (cv2.add) where a value is changed when mask != 0

PS: however, your code works fine in my machine (Win7 64, Python 2.6(32bit), OpenCV 2.3.0) though

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.