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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With