2012-03-14 22 views
3

あなたはRGBイメージを持っており、すべてのピクセルを処理したいと想像:numpyの:複数の値のためのベクトル化

import numpy as np 
image = np.zeros((1024, 1024, 3)) 

def rgb_to_something(rgb): 
    pass 

vfunc = np.vectorize(rgb_to_something) 
vfunc(image) 

vfuncは今、すべてのRGB値を取得する必要があります。問題は、numpyが 配列を平坦化し、 rgb0, rgb1, rgb2, ...を取得するときに関数がr0, g0, b0, r1, g1, b1, ...を取得することです。 これは何とかできますか?あらかじめいくつかの特殊なデータ型にnumpyの配列を変換することにより多分

http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html

?例えば

(もちろん動作していない):

image = image.astype(np.float32) 
import ctypes 
RGB = ctypes.c_float * 3 
image.astype(RGB) 
ValueError: shape mismatch: objects cannot be broadcast to a single shape 

更新: 主な目的は、ここに効率です。非ベクトル化バージョンは、単純に次のようになります。

import numpy as np 
image = np.zeros((1024, 1024, 3)) 
shape = image.shape[0:2] 
image = image.reshape((-1, 3)) 
def rgb_to_something((r, g, b)): 
    return r + g + b 
transformed_image = np.array([rgb_to_something(rgb) for rgb in image]).reshape(shape) 
+1

3dアレイを3つの別々の1dアレイ(各チャネルに1つ)に分けて、ベクトル化された関数の引数として使用できますか? – jeff7

+0

はいはい!しかし、それがいかに効率的であるかをプロファイリングする必要があります。 – tauran

+0

配列の分離はループよりはるかに高速ですが、larsmansの解決策はまだあります(私は単純なテストで2.7s、0.8s、0.3sを得ました)。しかし、既存の関数(例えば、colorsysモジュールから)を使用したい場合は、まだ興味深いです。 – tauran

答えて

4

この種の問題を解決する簡単な方法は、関数とその内部の使用ベクトル化イディオムに配列全体を渡すことです。具体的には、あなたのrgb_to_something

バージョンよりも約15倍高速である
def rgb_to_something(pixels): 
    return pixels.sum(axis=1) 

を書くことができます。

In [16]: %timeit np.array([old_rgb_to_something(rgb) for rgb in image]).reshape(shape) 
1 loops, best of 3: 3.03 s per loop 

In [19]: %timeit image.sum(axis=1).reshape(shape) 
1 loops, best of 3: 192 ms per loop 

np.vectorizeの問題は適用されたとき、それは必ずしもPythonの関数呼び出しのオーバーヘッドの多くを負担するということです大きなアレイに

+0

これは単なる例です。 numpyに組み込まれていないより複雑な操作はどうでしょうか? (純粋なPythonをしてください、Cエクステンションを書いても大丈夫ですが、何かを試したいのであれば退屈です。)目次どのようにベクトルの配列(rgb、velocity、...)を扱いますか? – tauran

+0

私の例から一般化すると、y軸に沿ってベクトル化する式を使用します。つまり、一度に多数の短いベクトルを扱う式を使用します。多数の 'a、b'ペアに対して' f(a、b) 'を計算したい場合は、同じ大きさの配列のペアをとる関数を実装します。 –

+1

"vectorize関数は、パフォーマンスのためではなく、便宜上提供されます。実装は本質的にforループです。" http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html – endolith

2

場合によってはNumexprを使用できます。たとえば、

import numpy as np 
import numexpr 
rgb = np.random.rand(3,1000,1000) 
r,g,b = rgb 

この場合、numexprは「ベクトル化」numpy式よりも5倍高速です。しかし、すべての関数をこのように書くことはできません。

%timeit r*2+g*3/b 
10 loops, best of 3: 20.8 ms per loop 

%timeit numexpr.evaluate("(r*2+g*3)/b") 
100 loops, best of 3: 4.2 ms per loop 
関連する問題