【问题标题】:TypeError with Numba when averaging rows in numpy array对 numpy 数组中的行进行平均时 Numba 出现 TypeError
【发布时间】:2020-08-26 00:27:45
【问题描述】:

我想取一帧中所有行的平均值并打印出如下所示的列表。

import numpy as np
import cv2, time
from numba import jit

cap = cv2.VideoCapture(0)

@jit(nopython=True)
def test(frame):
    print(frame.mean(axis=1))     # to take the mean of each row
        
fc = 0
frame_rate = 30
prev = 0
while(cap.isOpened()):
    ret, frame = cap.read()
    time_elapsed = time.time() - prev
    if time_elapsed > 1/frame_rate:
        prev = time.time()
        if ret == True:
            
            cv2.imshow("Video", frame)
            print(frame.shape)   #(480, 640, 3)
            
            test(frame)
            
            if cv2.waitKey(27) & 0xFF == ord('q'):
                break

        # if no frame found
        else:
            break

cap.release()
cv2.destroyAllWindows()

但我不断收到以下错误。 Numba 应该可以很好地处理数值计算,比如平均一个 numpy 数组,所以我对我的函数的问题有点困惑。

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
- Resolution failure for literal arguments:
AssertionError()
- Resolution failure for non-literal arguments:
AssertionError()

During: resolving callee type: BoundFunction(array.mean for array(uint8, 3d, C))
During: typing of call at <ipython-input-2-3d43e63d267e> (11)


File "<ipython-input-2-3d43e63d267e>", line 11:
def test(frame):
    print(frame.mean(axis=1))     # to take the mean of each row

【问题讨论】:

  • 您可以尝试np.mean(frame,axis=1),而不是错误消息更有意义(不支持轴关键字)。所以你必须自己实现它。打印和测量性能也没有意义(打印成本很高)。我猜你的最后一个维度总是大小为 3,对吧?这是优化解决方案的重要一点。
  • 我想我应该手动遍历帧的每一行并将其平均

标签: python arrays numba


【解决方案1】:

正如在 cmets 中已经说过的那样,np.mean 仅支持不带任何关键字。 supported functions。您可以自己轻松实现它,但如果您有更多关于实际问题的信息,可以直接进一步优化它。

一般解决方案

import numpy as np
import numba as nb
@nb.njit(fastmath=True)
def mean_gen(frame):
    res=np.zeros((frame.shape[0],3),dtype=np.float64)
    for i in range(frame.shape[0]):
        for j in range(frame.shape[1]):
            for k in range(frame.shape[2]):
                res[i,k]+=frame[i,j,k]
    return res/frame.shape[1]

如果最后一个维度总是大小为 3 的解决方案

In this case the inner loop can be unrolled to get better performance. The assertion `assert frame.shape[2]==3` is not only safety (there is no bounds checking), but also informs the compiler about the exact memory layout, which is often necessary for SIMD-vectorization. Some basic experience in C helps a lot in writing efficient code in Numba.

@nb.njit(fastmath=True,parallel=False)
def mean_3(frame):
    assert frame.shape[2]==3
    res=np.empty((frame.shape[0],3),dtype=np.float64)
    for i in nb.prange(frame.shape[0]):
        acc1=0.
        acc2=0.
        acc3=0.
        for j in range(frame.shape[1]):
            acc1+=frame[i,j,0]
            acc2+=frame[i,j,1]
            acc3+=frame[i,j,2]
        res[i,0]=acc1/frame.shape[1]
        res[i,1]=acc2/frame.shape[1]
        res[i,2]=acc3/frame.shape[1]
    return res

时间

#generate some date
frame=np.random.rand(1280,720,3)*255
frame=frame.astype(np.uint8)

#Numpy
%timeit np.mean(frame,axis=1)
#17.6 ms ± 557 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit mean_gen(frame)
#2.27 ms ± 22.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit mean_3(frame)
#606 µs ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-11
    • 2012-06-06
    • 2013-04-04
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    相关资源
    最近更新 更多