表现:扩展二元图像(形态膨胀)

时间:2016-07-04 21:30:11

标签: python performance numpy optimization cython

我编写了一个Cython函数,它将二进制图像(numpy数组)扩展了1个像素。所以我想简单地扩展数组值为1的区域。 这是我天真的做法:

def expand_1px (numpy.ndarray[numpy.uint8_t, ndim = 2] A):
    cdef int  h = A.shape[0]
    cdef int  w = A.shape[1]
    cdef numpy.ndarray[numpy.uint8_t, ndim = 2] RES = numpy.zeros([h, w], dtype = numpy.uint8)
    # These Two lines below were originally missing 
    cdef int  y, x
    cdef unsigned char  prev, cur

    for x in range (0, w):
        for y in range (1, h):
            prev = A[y-1,x]
            cur = A[y,x]
            if cur > prev:
                RES[y-1, x] = 1
            if cur < prev:
                RES[y,x] = 1
    for y in range (0, h):
        for x in range (1, w):
            prev = A[y,x-1]
            cur = A[y,x]
            if cur > prev:
                RES[y, x-1] = 1
            if cur < prev:
                RES[y,x] = 1
    return numpy.bitwise_or(A,RES)

这可以正常工作,但很慢。 一个OpenCV函数dilate()比我的Cython变体快 1000 ~30倍,并给出相同的结果。我这样用它:

kernel = numpy.ones((3,3), dtype="uint8")
kernel[0,0] = 0
kernel[2,2] = 0
kernel[0,2] = 0
kernel[2,0] = 0
...
IMG = cv2.dilate(IMG,kernel,iterations = 1)

  • OpenCV的变体怎么这么快?它实际上做了什么?
  • 如何让我的Cython功能如此快速地工作?

更新

这种糟糕的表现是由于缺少了“cdef&#39;声明,我的坏。将此功能添加到函数中会产生差异:

cdef int  y, x
cdef unsigned char  prev, cur

性能差异仍然是大约30倍,这也是一种失望。有任何进一步改进的建议吗?

1 个答案:

答案 0 :(得分:1)

你的功能存在一个很大的问题:你正在做更多你需要的循环。

  $log.info("classes info",info);

最初,您正在进行import cython @wraparound(false) def expand_1px(numpy.ndarray[numpy.uint8_t, ndim = 2] A): cdef int h = A.shape[0] cdef int w = A.shape[1] cdef numpy.ndarray[numpy.uint8_t, ndim = 2] RES = numpy.zeros([h, w], dtype = numpy.uint8) cdef int y, x cdef unsigned char prev, cur for x in range(1, w): for y in range(1, h): cur = A[y,x] prev = A[y-1,x] if prev < cur: RES[y-1,x] = 1 elif cur < prev: RES[y,x] = 1 prev = A[y, x-1] if prev < cur: RES[y,x-1] = 1 elif cur < prev: RES[y,x] = 1 for x in range(1, w): cur = A[0,x] prev = A[0,x-1] if prev < cur: RES[0,x-1] = 1 elif cur < prev: RES[0,x] = 1 for y in range(1, h): cur = A[y,0] prev = A[y-1,0] if prev < cur: RES[y-1,0] = 1 elif cur < prev: RES[y,0] = 1 return numpy.bitwise_or(A,RES) 次迭代,只需进行此更改,您将只进行2wh次迭代。