Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python嵌套用于RGB平均值中的循环_Python_Performance_Numpy_Vectorization - Fatal编程技术网

Python嵌套用于RGB平均值中的循环

Python嵌套用于RGB平均值中的循环,python,performance,numpy,vectorization,Python,Performance,Numpy,Vectorization,我想优化的一些代码有一个相当慢的点。在蒙版图像中,我计算R、G和B通道的平均值。我想摆脱嵌套for循环,但不确定如何实现。有什么想法吗 maskimage = cv2.imread(filename) hsv = cv2.cvtColor(maskimage, cv2.COLOR_BGR2HSV) boundaries = [([25, 146, 190], [62, 174, 250])] for (lower, upper) in boundaries: # create N

我想优化的一些代码有一个相当慢的点。在蒙版图像中,我计算R、G和B通道的平均值。我想摆脱嵌套for循环,但不确定如何实现。有什么想法吗

maskimage = cv2.imread(filename)
hsv = cv2.cvtColor(maskimage, cv2.COLOR_BGR2HSV)
boundaries = [([25, 146, 190], [62, 174, 250])]
for (lower, upper) in boundaries:
        # create NumPy arrays from the boundaries
        lower = np.array(lower, dtype = "uint8")
        upper = np.array(upper, dtype = "uint8")
        # find the colors within the specified boundaries and apply
        # the mask
        mask = cv2.inRange(hsv, lower, upper)
        masked_img = cv2.bitwise_and(bgimage, bgimage, mask = mask)
        meanblue = 0
        meangreen = 0
        meanred = 0
        count = 0
        H, W, b = masked_img.shape
        for i in range(0,H,1):
           for j in range(0,W,1):
            if masked_img[i,j,0] > 1 or masked_img[i,j,1] > 1 or masked_img[i,j,2] > 1:
                meanblue = meanblue + masked_img[i,j,0]
                meangreen = meangreen + masked_img[i,j,1]
                meanred = meanred + masked_img[i,j,2]
                count = count+1
        if count !=0:
            omeanb = meanblue/count
            omeang = meangreen/count
            omeanr = meanred/count
        if count ==0:
            omeanb = 255
            omeang = 255
            omeanr = 255    

您可以使用

例如:

>>> from itertools import product
>>> [(i,j) for i, j in product((1,2,3), (4, 5, 6))]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

可以使用矢量化方法替换最里面的两个嵌套循环

因此,有人可以取代这一点-

H, W, b = masked_img.shape
for i in range(0,H,1):
   for j in range(0,W,1):
    if masked_img[i,j,0] > 1 or masked_img[i,j,1] > 1 or masked_img[i,j,2] > 1:
        meanblue = meanblue + masked_img[i,j,0]
        meangreen = meangreen + masked_img[i,j,1]
        meanred = meanred + masked_img[i,j,2]
        count = count+1
因此—

mask = (masked_img > 1).any(2)
count = mask.sum()
mean_bgr = (masked_img*(mask[...,None])).sum(axis=(0,1))
一个人可以冒险一点,在最后一步使用,这可能会进一步提高性能,就像这样-

mean_bgr = np.einsum('ijk,ij->k',masked_img.astype(int),mask)
运行时测试

函数定义-

def original_app(masked_img):
    meanblue = 0
    meangreen = 0
    meanred = 0
    count = 0
    H, W, b = masked_img.shape
    for i in range(0,H,1):
       for j in range(0,W,1):
        if masked_img[i,j,0] > 1 or masked_img[i,j,1] > 1 or masked_img[i,j,2] > 1:
            meanblue = meanblue + masked_img[i,j,0]
            meangreen = meangreen + masked_img[i,j,1]
            meanred = meanred + masked_img[i,j,2]
            count = count+1
    return [meanblue, meangreen, meanred], count

def vectorized_app1(masked_img):
    mask = (masked_img > 1).any(2)
    count = mask.sum()
    mean_bgr = (masked_img*(mask[...,None])).sum(axis=(0,1))
    return mean_bgr, count

def vectorized_app2(masked_img):
    mask = (masked_img > 1).any(2)
    count = mask.sum()
    mean_bgr = np.einsum('ijk,ij->k',masked_img.astype(int),mask)
    return mean_bgr, count
时间安排-

In [235]: # Random image input array
     ...: masked_img = np.random.randint(0,255,(512,512,3)).astype('uint8')

In [236]: original_app(masked_img)
Out[236]: ([33273503, 33274596, 33323215], 262144)

In [237]: vectorized_app1(masked_img)
Out[237]: (array([33273503, 33274596, 33323215], dtype=uint32), 262144)

In [238]: vectorized_app2(masked_img)
Out[238]: (array([ 33273503,  33274596,  33323215]), 262144)

In [239]: %timeit original_app(masked_img)
1 loops, best of 3: 2.08 s per loop

In [240]: %timeit vectorized_app1(masked_img)
100 loops, best of 3: 17.9 ms per loop

In [241]: %timeit vectorized_app2(masked_img)
10 loops, best of 3: 16.5 ms per loop

这是一个
100+x
加速

看看itertools.product:试试
np.average(masked\u img,axis=-1)
,再加上一些修改以满足您的其他需求。np.average似乎很有希望,尽管我有点困惑。打印出来的结果是:[[0.0.0.0,0.0.0.][0.0.0,0.0.0.][0.0.0,0.0.0.][0.0.0.0,0.0.0.][0.0.0.0.0.][0.0.0.0,0.0.][0.0.0.0.][0.0.0.0.]这仍然需要通过所有(i,j)对并用python进行计算。这并没有多大的改进,因为没有嵌套for循环来做N(i,j)对,而是有一个for循环来做N(i,j)对。是的,我希望通过去掉这些循环来提高性能,而itertools似乎没有这样做。的确,它只是稍微优雅一点,但如果Numpy有一种使您的生活更轻松、代码更可读的特定方式,请按照lija的建议使用它。mean_bgr=(masked_img*(mask[…,None])。sum(axis=(0.1))似乎有一个错误,因为我得到的值高于255。然而,np.einsum似乎完成了这个任务,比以前快得多。你能解释一下ijk的情况吗,ij->k?@MarkBrown是的,你需要缩小到
255
。正如在文章中所述,我们只是删除嵌套循环。所以,所有其他的事情都必须完成,包括接下来的两个IF条件语句。希望这是有道理的。另外,
einsum
的解释有点复杂。我建议您遵循官方文件。@MarkBrown请查看编辑内容。很抱歉,我的意思是按
计数的比例缩小
仍然保留,之后的值将在
[0255]
范围内。所以要快得多。我已经等了好几个小时了,现在只剩几分钟了。@MarkBrown,太好了!