Opencv python: 对每个像素应用任意函数而不需要迭代

3

在使用Python的OpenCV时,是否有一种方法可以在利用NumPy的优化的同时对图像中的每个像素应用任意函数?

例如,我想获取单通道图像的Sigmoid:

out_image[:,:] = 1 / (1 + math.exp(-in_img[:,:]))

但这并不起作用(不出所料):TypeError: only length-1 arrays can be converted to Python scalars

有没有办法诱使numpy做类似于此的事情?

当然,我可以遍历像素,这在C++中可能很好,但在Python中非常慢。


1
尝试将 math.exp 替换为 np.exp - Divakar
这是解决这个特定问题的方案。我能否定义一个操作单个像素的任意函数,并诱使numpy快速运行它?还是我编写的任何函数都需要直接在numpy数组上操作? - StaringFrog
1个回答

3

正如@Divakar所建议的那样,用只知道标量的math.exp替换为也知道ndarraynumpy.exp是正确的方法。

另外一些基准测试:

in_img = numpy.random.random((1000, 1000))

在CPython中:

%timeit (1 / (1 + numpy.exp(-in_img[:,:])))

执行10次,3次取最佳结果:每次循环耗时51.1毫秒。

使用numexpr:

import numexpr
%timeit numexpr.evaluate("1 / (1 + exp(-in_img))")
10 loops, best of 3: 27.9 ms per loop

使用Numba(假设您已经像下面这样正确注释了函数)

import numpy
from numba import vectorize, float64
@vectorize([float64(float64)])
def f(x):
    return 1 / (1 + numpy.exp(-x))

你将得到:

%timeit f(in_img)
100 loops, best of 3: 5.34 ms per loop

使用Pythran(假设您已编译以下功能)

#pythran export f(float[][])
def f(in_img):
    return 1 / (1 + numpy.exp(-in_img[:,:]))

使用以下命令进行编译:

pythran f.py -DUSE_BOOST_SIMD -march=native

并且测试它:

100 loops, best of 3: 5.07 ms per loop

1
这是解决这个特定问题的方案。我能否定义一个操作单个像素的任意函数,并诱使numpy快速运行它?还是我编写的任何函数都需要直接在numpy数组上操作? - StaringFrog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接