我编写了一个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)
问:
更新:
这种糟糕的表现是由于缺少了“cdef&#39;声明,我的坏。将此功能添加到函数中会产生差异:
cdef int y, x
cdef unsigned char prev, cur
性能差异仍然是大约30倍,这也是一种失望。有任何进一步改进的建议吗?
答案 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
次迭代。