SciPyとNumpyを使用して2Dマトリックスの畳み込みを実行しようとしましたが、失敗しました。私が試したSciPyの場合は、sepfir2dとscipy.signal.convolve、Numpyの場合はConvolve2Dです。 Matlab for Pythonにconv2のような単純な関数はありますか?
次に例を示します。
A= [ 5 4 5 4;
3 2 3 2;
5 4 5 4;
3 2 3 2 ]
[0.707 0.707]
で畳み込みたい
そして、Matlabからのconv2による結果は次のとおりです。
3.5350 6.3630 6.3630 6.3630 2.8280
2.1210 3.5350 3.5350 3.5350 1.4140
3.5350 6.3630 6.3630 6.3630 2.8280
2.1210 3.5350 3.5350 3.5350 1.4140
Pythonでこの出力を計算する関数はありますか?お返事をいただければ幸いです。
scipy
を使用してこれを行うにはさまざまな方法がありますが、2D畳み込みはnumpy
に直接含まれていません。 (scipyの依存関係を回避する必要がある場合は、numpyのみを使用してfftで実装することも簡単です。)
scipy.signal.convolve2d
、scipy.signal.convolve
、scipy.signal.fftconvolve
、およびscipy.ndimage.convolve
はすべて、異なる方法で2D畳み込み(最後の3つはN-d)を処理します。
scipy.signal.fftconvolve
はfftドメインで畳み込みを行います(単純な乗算です)。これは多くの場合はるかに高速ですが、個別の場合よりもエッジ効果にごくわずかな違いが生じる可能性があり、この特定の実装ではデータが浮動小数点に強制変換されます。さらに、小さな配列をはるかに大きな配列で畳み込む場合、不要なメモリ使用量があります。全体として、fftベースのメソッドは劇的に高速になる可能性がありますが、scipy.signal.fftconvolve
が理想的なソリューションではない一般的なユースケースがいくつかあります。
scipy.signal.convolve2d
、scipy.signal.convolve
、およびscipy.ndimage.convolve
はすべて、Cで実装された離散畳み込みを使用しますが、実装方法は異なります。
scipy.ndimage.convolve
は同じデータ型を維持し、メモリ使用量を最小限に抑えるために出力の場所を制御できます。 uint8
(画像データなど)を畳み込む場合は、多くの場合、これが最良のオプションです。出力は常に最初の入力配列と同じ形状になります。これは画像には意味がありますが、より一般的な畳み込みには意味がありません。 ndimage.convolve
を使用すると、mode
kwarg(scipy.signal
のmode
kwargとはまったく異なる機能)を介してエッジ効果を処理する方法を細かく制御できます。
2D配列を使用している場合は、scipy.signal.convolve
を避けてください。これはN-dの場合には機能しますが、2d配列には最適ではなく、まったく同じことをもう少し効率的に行うためにscipy.signal.convolve2d
が存在します。 scipy.signal
の畳み込み関数を使用すると、mode
kwargを使用して出力形状を制御できます。 (デフォルトでは、matlabのconv2
と同じように動作します。)これは、一般的な数学的畳み込みには役立ちますが、画像処理にはあまり役立ちません。ただし、scipy.signal.convolve2d
は一般的にscipy.ndimage.convolve
よりも低速です。
scipy
のさまざまなサブモジュールでの重複と、パフォーマンスのトレードオフが異なる畳み込みを実装するさまざまな方法があるため、さまざまなオプションがあります。
ユースケースについてもう少し詳しく説明していただければ、より良いソリューションをお勧めします。ほぼ同じサイズの2つの配列を畳み込み、それらがすでに浮動小数点になっている場合は、fftconvolve
が最適です。そうでなければ、scipy.ndimage.convolve
がそれを打ち負かす可能性があります。
scipyのconvolved1d()は必要なことを実行し、エッジの扱いを少し変えます。
sp.ndimage.filters.convolve1d(A,[0.707,0.707],axis=1,mode='constant')
あなたに与えるでしょう:
array([[ 6.363, 6.363, 6.363, 2.828],
[ 3.535, 3.535, 3.535, 1.414],
[ 6.363, 6.363, 6.363, 2.828],
[ 3.535, 3.535, 3.535, 1.414]])
まったく同じ結果が必要な場合は、次のようにAにゼロの列を追加するだけです。
sp.ndimage.filters.convolve1d(np.c_[np.zeros((4,1)),A],[0.707,0.707],axis=1,mode='constant')
そして、あなたは得るでしょう:
array([[ 3.535, 6.363, 6.363, 6.363, 2.828],
[ 2.121, 3.535, 3.535, 3.535, 1.414],
[ 3.535, 6.363, 6.363, 6.363, 2.828],
[ 2.121, 3.535, 3.535, 3.535, 1.414]])
私の経験から、Matlabで行うことのほとんど(およびそれ以上)をscipy/numpyで行うことができます。