LoginSignup
3
4

More than 5 years have passed since last update.

インデクシングでim2col

Last updated at Posted at 2016-11-26

プーリングをするためにim2colを実装しました。
NumPyのインデクシングのみで書いているので(for文でイタレーションするよりは)高速です。

# im2colした後convolveする関数
def im2col_and_convolve(I, h, hstride=1, wstride=1, is_convolve=False, mode="full"):
    I = I.astype(float64)

    add = array(h.shape) - 1
    if mode=="full":
        I_zeros = zeros(tuple((array(I.atype(int).shape) + 2 * add).tolist()))
        I_zeros[add[0]:-add[0], add[1]:-add[1]] = I
        I = I_zeros
    elif mode == "valid":
        add = array(h.shape)
    else:
        I_zeros = zeros(tuple((array(I.astype(int).shape) + add).tolist()))
        I_zeros[add[0]/2:-add[0]/2-1, add[1]/2:-add[1]/2-1] = I
        I = I_zeros

    i_len = I.shape[0]
    j_len = I.shape[1]
    k_len = h.shape[0]
    l_len = h.shape[1]

    i = arange(0,int(i_len-add[0]),hstride) * j_len 
    j = arange(0,int(j_len-add[0]), wstride)[:-1]
    k = arange(k_len) * j_len
    l = arange(l_len)

    ko = ones_like(k)
    lo = ones_like(l)

    # Generate index array with broadcasting
    idx = (((i [:, None] + 
             j)[:, :, None] + 
             k)[:, :, :, None] + 
             l).flatten()

    # im2col
    I_bar = I.flatten()[idx].reshape(i.size, j.size, k.size * l.size) 

    if is_convolve: 
        return (I_bar*h.flatten()).dot(ones(k.size * l.size))
    else:
        return I_bar

from PIL import Image
#from cupy import *
from numpy import *
import pylab as p
fname = "parrot.jpg" 
raw  = array(Image.open(fname).convert("L"))

# 幅、高さがそれぞれ画像の20分の1の窓関数を定義
row, col = (array(raw.shape) / 20) 
h = ones((int(row),int(col))) * 1.
h /= (row*col) ** 2

from PIL import Image
#from cupy import *
from numpy import *
import pylab as p
fname = "parrot.jpg" 
raw  = array(Image.open(fname).convert("L"))

# 幅、高さがそれぞれ画像の20分の1の窓関数を定義
row, col = (array(raw.shape) / 20) 
h = ones((int(row),int(col))) * 1.
h /= (row*col) ** 2

# im2colして窓関数hでconvolve
v_convolved   = im2col_and_convolve(raw, h, 20,20, True, "valid")  # 20, 20は幅、高さ方向のストライド
v_broadcasted = im2col_and_convolve(raw, h, 20,20, False, "valid") # Falseにするとconvolveしないでbloadcastされた画像配列(3次元)を返す。

print ("原画像")
p.imshow(raw,cmap=p.cm.gray);p.show()
print ("平滑化画像")
p.imshow(v_convolved,cmap=p.cm.gray);p.show()
print ("最大値プーリング画像")
p.imshow(v_broadcasted.max(axis=2),cmap=p.cm.gray);p.show()

出力結果

parrots.png

cupyでためしてみようかなと思ったのですが、cupyは配列の要素に配列を代入するインデクシングに対応していないようです。エラーが出てしまいました。
例えばnumpyが、

In []: import numpy as n
In []: n.arange(10)[n.arange(5)]
Out[]: array([0, 1, 2, 3, 4])

なのにたいして、cupyは

In []: import cupy as c
In []: c.arange(10)[c.arange(5)]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-e479cdecf448> in <module>()
----> 1 c.arange(10)[c.arange(5)]

cupy/core/core.pyx in cupy.core.core.ndarray.__getitem__ (cupy/core/core.cpp:20995)()

ValueError: Advanced indexing is not supported

のようなエラーが出てしまいます。。。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4