プーリングをするために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()
出力結果
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
のようなエラーが出てしまいます。。。