22380


Pythonで`convolve2d`を使う下記のプログラムをかきました。

[code]

    #coding:utf-8
    
    import numpy as np
    from scipy import signal
    
    
    a = np.array([
        [1,2,3,4,5,6],
        [7,8,9,10,11,12],
        [13,14,15,16,17,18],
        [19,20,21,22,23,24],
        [25,26,27,28,29,30],
        [31,32,33,34,35,36]
        ])
    
    f = np.array([
        [0,1,0],
        [0,0,0],
        [0,0,0]
        ])
    
    print a
    print f
    p = signal.convolve2d(a, f, 'valid')
    print p
    
[/code]

結果は

[code]

    [[ 1  2  3  4  5  6]
     [ 7  8  9 10 11 12]
     [13 14 15 16 17 18]
     [19 20 21 22 23 24]
     [25 26 27 28 29 30]
     [31 32 33 34 35 36]]
    [[0 1 0]
     [0 0 0]
     [0 0 0]]
    [[14 15 16 17]
     [20 21 22 23]
     [26 27 28 29]
     [32 33 34 35]]
    
[/code]

このようになりました。

この[サイト](https://docs.gimp.org/2.6/ja/plug-in-
convmatrix.html)を参考にすると畳み込み演算は元の行列の右上、左上、右下、左下を除くすべての点における近傍8ピクセルとフィルタの要素をそれぞれ掛けて足してその結果を新しい行列上のフィルタの中心座標にセットするようなので行列が1行下がると考えられましたが、結果を見ると上がっているように見えます。  
更に`valid`を`same`にすると

[code]

    [[ 7  8  9 10 11]
     [13 14 15 16 17]
     [19 20 21 22 23]
     [25 26 27 28 29]
     [ 0  0  0  0  0]]
    
[/code]

このようになります。  
これはどちらが正しいのでしょうか。


CC BY-SA 3.0
2016-02-21T14:29:19.067
22363
2016-02-24T06:22:52.137
2016-02-22T07:07:38.797
7837
7232
question
python numpy scipy
Pythonのconvolve2dについて


リンク先と同じ計算をするにはcross-correlateで計算します。

[code]

    import numpy as np
    from scipy import signal
    
    
    a = np.array([
        [1,2,3,4,5,6],
        [7,8,9,10,11,12],
        [13,14,15,16,17,18],
        [19,20,21,22,23,24],
        [25,26,27,28,29,30],
        [31,32,33,34,35,36]
        ])
    
    f = np.array([
        [0,1,0],
        [0,0,0],
        [0,0,0]
        ])
    
    print a
    print f
    p = signal.correlate(a, f, 'same')
    print p
    
[/code]

**出力**

期待通り(?)一つ下がっています。

[code]

    [[ 1  2  3  4  5  6]
     [ 7  8  9 10 11 12]
     [13 14 15 16 17 18]
     [19 20 21 22 23 24]
     [25 26 27 28 29 30]
     [31 32 33 34 35 36]]
    [[0 1 0]
     [0 0 0]
     [0 0 0]]
    [[ 0  0  0  0  0  0]
     [ 1  2  3  4  5  6]
     [ 7  8  9 10 11 12]
     [13 14 15 16 17 18]
     [19 20 21 22 23 24]
     [25 26 27 28 29 30]]
    
[/code]

# Convolutionについて

Convolutionは電気信号にフィルターを適用した時の波形を求めるのによく使われるそうです(大学の授業以来なので分かったようなことは書けませんが)。画像に対するフィルターは縦横に拡張したものと同等です。

信号gに対してフィルターfを適用するとき、過去の信号をフィルターした結果と、より最近の信号をフィルターした結果が重なることから、出力yは次のようになります。要するに過去の積み重ねで、scipyもこの定義に従っています。

[![画像の説明をここに入力](https://i.stack.imgur.com/z0iF8.png)](https://i.stack.imgur.com/z0iF8.png)

Cross-
Correlation([相互相関関数](https://ja.wikipedia.org/wiki/%E7%9B%B8%E4%BA%92%E7%9B%B8%E9%96%A2%E9%96%A2%E6%95%B0))はtauの符号が逆さまになっています。コンボユーションではフィルターを逆方向から当てていて、Cross-
Correlationでは順方向に当てていることになり、それがシフトした方向の違いの理由でした。

参考までにscipyを使わないコンボリューションの実装との比較を示します。１次元のみ。パディングの代わりに周囲は無限の0の信号とフィルターになっています。scipyではfullモードが一番近いです。

[code]

    A = [1,2,3,4,5,6] # t, t+1, t+2, ...
    F = [1,0,0] #t, t-1, t-2, ...
    
    def g(t):
        "signal at time t"
        if t < 0 or t >= len(A):
            return 0
        return A[t]
    
    def f(t):
        "stationary filter function"
        if t < 0 or t >= len(F):
            return 0
        return F[t]
    
    def y(t):
        s = 0
        for tau in range(t+1):
            s += f(t-tau)*g(tau)
            # 可換なので次でも同じ
            # s += f(tau)*g(t-tau)
        return s
    
    # 二つの配列がギリギリ重ね合わさった時の長さ
    l = len(A) + len(F)   
    print [y(t) for t in range(l+1)]
    
    # scipy version
    import numpy as np
    from scipy import signal
    a = np.array([A])
    f = np.array([F])
    p = signal.convolve2d(a, f, 'full')
    print p
    
[/code]

実行結果

[code]

    [1, 2, 3, 4, 5, 6, 0, 0, 0, 0]
    [[1 2 3 4 5 6 0 0]]
    
[/code]

参考リンク  
[人生畳み込み](http://www.ice.tohtech.ac.jp/~nakagawa/laplacetrans/convolution1.htm)
(積分が苦手な人向け)  
[SciPy
correlate](http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.signal.correlate.html)  
[NumPy
convolve](http://docs.scipy.org/doc/numpy/reference/generated/numpy.convolve.html)
(離散の定義sum(a[m]*v[n-m])が載っている。本質的に上の積分と同じ)


CC BY-SA 3.0
2016-02-22T06:46:11.220
22380
2016-02-24T06:22:52.137
2016-02-24T06:22:52.137
7837
7837
22363
answer