LoginSignup
3
4

More than 5 years have passed since last update.

Fully Convolutional Networks (FCN) の最終層のfeature mapサイズを求める

Posted at

Segmentationや、SSD, YOLO(v2)といったsingle shot系のベースネットワークとしてFully Convolutional Networks (FCN) を利用していると、入力画像サイズが可変なので、任意の入力画像サイズに対し出力されるfeature mapのサイズを明示的に知りたいときがある。

例えばstride=2にしたダウンサンプルを4回行うと、出力されるfeature mapのサイズは入力画像の大体1/16になる。入力サイズを16の倍数に制限してしまえば単純に16で割れば良いが、端数のケースも考慮したい。Paddingなしの2x2 maxpoolingとかであれば、単純に16で割って端数を切り捨てれば良い。

ResNet系では、paddingあり、stride=2の3x3の畳み込みでダウンサンプルするケースが多いので、そういうケースでfeature mapのサイズを明示的に求めたい。
Kerasで言えば、下記のような畳み込み。

Conv2D(32, 3, strides=2, padding="same")

xを入力サイズ、countをstride=2でダウンサンプルする回数とすると、出力されるfeature mapのサイズは下記で求められる。

def down_sample(x, count):
    for _ in range(count):
        x = (x + 1) // 2

    return x

これは下記でも同じ。

def down_sample(x, count):
    return (x + pow(2, count) - 1) // pow(2, count)

ランダムな入力サイズで確認(Keras実装)。

import numpy as np
from keras.models import Sequential
from keras.layers import Conv2D


def down_sample(x, count):
    return (x + pow(2, count) - 1) // pow(2, count)


def main():
    model = Sequential()
    model.add(Conv2D(16, 3, strides=2, padding="same", activation="relu", input_shape=(None, None, 3)))
    model.add(Conv2D(32, 3, strides=2, padding="same", activation="relu"))
    model.add(Conv2D(64, 3, strides=2, padding="same", activation="relu"))
    model.add(Conv2D(128, 3, strides=2, padding="same", activation="relu"))

    for _ in range(10):
        h, w = np.random.randint(300, 600), np.random.randint(300, 600)
        data = np.ones((1, h, w, 3))
        ch, cw = down_sample(h, 4), down_sample(w, 4)
        result = model.predict(data)
        print("result: {}, calculated: ({}, {})".format(result.shape[1:3], ch, cw))


if __name__ == '__main__':
    main()
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