Python OpenCV cv2 中的掩码不工作?

5 投票
2 回答
7732 浏览
提问于 2025-04-17 08:09

总的来说,新的Python绑定库用于OpenCV(叫做cv2)非常好用,但“掩码”似乎有点问题——除非我真的搞错了:

比如说,“cv2.add”在没有掩码的情况下还是能正常工作:

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

正确的结果是

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

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

但是当你添加一个掩码(还有一个输出数组“b”,这个是必须的,但不知道为什么没有被赋值)时,你得到的结果是随机的,也就是说,当你多次运行这个命令时,结果会变化

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)

在我的机器上(Win7,32位,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)

... 然后在下次尝试时又会得到不同的结果。现在要么是我真的搞错了,要么就是cv2绑定库有严重问题。

有什么建议吗?

2 个回答

0

为什么不使用numpy的(原地)掩码表达式呢?

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

掩码是一个布尔数组,类似于opencv中的操作(cv2.add),在这里当掩码不等于0时,值会被改变。

顺便说一下,你的代码在我的机器上运行得很好(Win7 64位,Python 2.6(32位),OpenCV 2.3.0)。

5

这是个有趣的问题。我也遇到了同样的问题。我发了个bug,得到了回复。http://code.opencv.org/issues/1748

解决方法很简单。创建时,目标数组(dst)是未定义的,操作只会改变那些目标数组中,满足mask(p)!=0条件的像素。

所以唯一有效的办法就是在进行加法之前先创建好目标数组。

也就是说:

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

下一个版本会在像cv2.add、cv2.subtract、cv2.bitwise_and/or/xor等操作中清空新创建的图像,这样就不会出现问题了。

我的代码看起来是这样的:

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

顺便说一下:时间记录(重复10,000次):

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

顺便提一下:提交bug请按照这里的说明操作:http://code.opencv.org/projects/OpenCV/wiki/WikiStart

撰写回答