18

numpyを使用してPythonで2D畳み込みを実行しようとしています

次のような2D配列があり、行にはカーネルH_r、列にはH_cがあります。

data = np.zeros((nr, nc), dtype=np.float32)

#fill array with some data here then convolve

for r in range(nr):
    data[r,:] = np.convolve(data[r,:], H_r, 'same')

for c in range(nc):
    data[:,c] = np.convolve(data[:,c], H_c, 'same')

data = data.astype(np.uint8);

それは私が期待していた出力を生成しません、このコードは大丈夫に見えますか、問題はfloat32から8ビットへのキャストにあると思います。これを行うための最良の方法は何ですか

ありがとう

4

8 に答える 8

6

編集 [2019年1月]

@Tashusのコメントは正しいので、@ dudemeisterの答えはおそらくより的を射ています。彼が提案した関数は、直接の 2D 畳み込みと必要な操作の数を回避することで、より効率的でもあります。

考えられる問題

最初は列ごと、2番目は行ごとの2つの1d畳み込みを行っており、最初の結果を2番目の結果に置き換えていると思います。

numpy.convolve引数を指定すると、'same'指定された最大の配列と同じ形状の配列が返されるため、最初の畳み込みを行うと、配列全体が既に取り込まれていることに注意してくださいdata

これらの手順で配列を視覚化する 1 つの良い方法は、ヒントン ダイアグラムを使用することです。これにより、どの要素が既に値を持っているかを確認できます。

考えられる解決策

畳み込み行列が 1 次元と次のような行列を使用した結果である場合は、2 つの畳み込みの結果を追加してみてください ( 2 番目のループのdata[:,c] += ..代わりに使用します)。data[:,c] =forH_rH_c

畳み込みコア加算

これを行う別の方法はscipy.signal.convolve2d、2 次元畳み込み配列を使用することです。これは、おそらく最初にやりたかったことです。

于 2016-10-04T12:48:23.327 に答える
5

すでにカーネルを分離しているので、scipy の sepfir2d 関数を使用するだけです。

from scipy.signal import sepfir2d
convolved = sepfir2d(data, H_r, H_c)

一方、そこにあるコードは問題ないように見えます...

于 2010-03-15T15:18:42.397 に答える
0

最初にラウンドしてから、uint8 にキャストしてみてください。

data = data.round().astype(np.uint8);
于 2013-01-30T14:51:12.240 に答える
0

最も明白な方法の 1 つは、カーネルをハードコーディングすることです。

img = img.convert('L')
a = np.array(img)
out = np.zeros([a.shape[0]-2, a.shape[1]-2], dtype='float')
out += a[:-2, :-2]
out += a[1:-1, :-2]
out += a[2:, :-2]
out += a[:-2, 1:-1]
out += a[1:-1,1:-1]
out += a[2:, 1:-1]
out += a[:-2, 2:]
out += a[1:-1, 2:]
out += a[2:, 2:]
out /= 9.0
out = out.astype('uint8')
img = Image.fromarray(out)

この例では、完全に展開されたボックス ブラー 3x3 を実行します。異なる値を持つ値を乗算し、異なる量で割ることができます。しかし、正直なところ、最も速くて汚い方法が必要な場合は、これがそれです。Guillaume Mougeot の方法よりも 5 倍優れていると思います。彼の方法は他の方法よりも 10 倍優れています。

ガウスぼかしのようなことをしている場合、いくつかのステップが失われる可能性があります。いくつかのものを増やす必要があります。

于 2020-11-26T04:50:54.187 に答える