格子状の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)
で変形できます。