meshgrid

格子状の2次元配列を作るときに使います。前回の等差数列を作る関数と合わせて使うことも多いと思います。

【書式】X, Y = np.meshgrid(x1, x2)
 引数には2つの1次元配列を指定します。

文章だけだと説明しづらいため、実際に動かしてみます。
まず、元となる1次元配列を作ります。

x = np.arange(0,5)
y = np.arange(0,10)
print(x)
print(y)

# x
array([0, 1, 2, 3, 4])

# y
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

ここで作った配列を引数にして2次元配列を作ります。

xx, yy = np.meshgrid(x,y)
print(xx)
print(yy)

# xx
array([[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4],
[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]])

# yy
array([[0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4],
[5, 5, 5, 5, 5], [6, 6, 6, 6, 6], [7, 7, 7, 7, 7], [8, 8, 8, 8, 8], [9, 9, 9, 9, 9]])

2次元配列のイメージにすると、下図のようになります。
meshgridは2次元の配列の全組み合わせを作ってくれるということですね。

また、\(X=xx(i,j)\)、\(Y=yy(i,j)\)として、\((X, Y)\)をみると、\((i, j)\)と値が一致します。つまりどういうことかというと、座標情報を計算可能な形にできるということです。

PyTorch

pytorchでも同じようなことができます。

x = torch.arange(0,5)
y = torch.arange(0,10)
print(x)
print(y)     

# x
tensor([0, 1, 2, 3, 4])

# y
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

同じように、torchのmeshgridで配列を作ります。

xx, yy = torch.meshgrid(x, y)
print(xx)
print(yy)

# xx
tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]])

# yy
tensor([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])

numpyの時と形状が違いますね。
図にすると、下のような感じです。

メモリの使い方が関係あるようでよくわからないのですが、PyTorchの場合、y方向(画像だと高さ方向)が順序として先に扱うみたいです。

numpyと同じ形状にしたい場合は、xとyの並びを逆にします。この差は意外にハマりどころですので要注意です。

yy, xx = torch.meshgrid(y, x)
print(yy)
print(xx)    

# yy
tensor([[0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4], [5, 5, 5, 5, 5], [6, 6, 6, 6, 6], [7, 7, 7, 7, 7], [8, 8, 8, 8, 8], [9, 9, 9, 9, 9]])

# xx
tensor([[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]])

利用例

meshgridの使い道がいまいちわからないでいたのですが、画像の変形を行うときに使えるのだと気づきました。

PyTorchで画像変形を行うときのやり方のひとつに、grid_sampleという関数を使う方法があります。この関数は、変形元画像と変形パラメータとして、x, yの座標が求められます。

下図のように、変形パラメータの各gridには、変換後の画像の値が、元画像のどこの座標の値を使うのかを指定します。

なので、例えばaffine変換をかけたいよ、という場合、まずは等差数列+meshgridで座標位置が値として格納された配列を作ります。この配列に対してaffine変換をかけるのです。

その結果をもって、
warp_img = F.grid_sample(img, warp)
で変形できます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です