LoginSignup
1
1

More than 3 years have passed since last update.

RetinaNetを詳しく紹介(一)データ前処理

Last updated at Posted at 2020-05-27

背景

前回物体検出のモデルであるSSDを紹介しました。
今回物体検出の一つモデルRetinaNetを紹介したいと思います
(本文書はこちらのソースコード https://github.com/yhenon/pytorch-retinanet を参考に整理したものです)
本節はデータの前処理を紹介いたします。

データの種類

二つがあります
1.画像

image(H,W,C)

2.目標物体のカテゴリーと範囲を表す座標(Annotations)

cx1,cy1,w1,h1,category1

データ前処理の流れ

1. Annotationsの前処理

cx_start,cy_start,width,height
から
cx_start,cy_start,cx_end,cy_end
まで
変更します
RetinaNet物体検出1.001.jpeg
図のように、変更されたAnnotationsは左上の開始点と右下の終了点になります。

2. 画像の前処理

RetinaNet物体検出1.002.jpeg
図のより、もともとの画像は次元が(H,W,C)のTensorです
以下の四つのスッテプを経由します。最後のOutputはモデルのinputとしてモデルに入れます。
1. /255処理
2. Normalizaer処理
3. Argumenter処理
4. Resize処理

2-1. /255処理

RetinaNet物体検出1.003.jpeg
図のように、画像データは次元が(H,W,C)のTensorです。各要素は0から255までの値です。
多分、計算量を減らすため、0から255の値を最大値255に割り算して、0から1までの値に変更します。

2-2. Normalizaer処理

RetinaNet物体検出1.004.jpeg
図のように、Cチャンネル画像データの各要素を事前に定められた該当するmeanと引き算して、事前に定められたstdと割り算します。

3. Argumenter処理

RetinaNet物体検出1.005.jpeg
データの多様性を保つために、データの水増しが行います。今回は0.5の確率で画像を横逆転します。
そして、関連するAnnotation情報も左右逆転します。

RetinaNet物体検出1.006.jpeg
図のようにAnnotation情報も左右逆転します。感覚的には、開始点を左上から右上に移動したり、終了点を右下から左下に移動します。

4. Resize処理

画像データはさまざまがあります。それは入力された画像のサイズによります。
640*480
1024*640
などいろいろサイズがあります。

4-1. Resizeされるサイズの条件

それらのサイズを以下の条件を満たすように変形します
短い辺の長さを608、もしくは長い辺の長さを1024にします
短い辺の長さを最長608、長い辺の長さを最長1024のサイズに変形します。

4-2. 横幅が小さい場合ケースA

RetinaNet物体検出1.007.jpeg
図のように、予め定められた横幅が608,縦幅が1024の基準ボックスがあります。まず画像データの横幅を基準ボックスの横幅に当てはまってみって、画像データの縦幅を同比例に変形します。
変形された縦幅は基準ボックスの縦幅より小さいなら、変形はそのまま成功になります。
scale = 基準ボックスの横幅/画像データの横幅

4-3. 横幅が小さい場合ケースB

RetinaNet物体検出1.008.jpeg
4-1とは別に、横幅を当てはまってみて、縦幅は基準ボックスの縦幅よりおおきいなら、縦幅を嵌ってみます。
scale = 基準ボックスの縦幅/画像データの縦幅

4-4. 縦幅が小さい場合ケースA

RetinaNet物体検出1.009.jpeg
図のように、画像データの縦幅は横幅とくらべたら、小さい場合。予め定められた横幅が1024,縦幅が608の基準ボックスがあります。
先に縦幅を608に当てはまってみます。算出された横幅が基準ボックスの縦幅1024より小さいなら、そのままにします。

4-5. 縦幅が小さい場合ケースB

RetinaNet物体検出1.010.jpeg
図のように、画像データの縦幅は横幅とくらべたら、小さい場合。予め定められた横幅が1024,縦幅が608の基準ボックスがあります。
先に縦幅を608に当てはまってみます。算出された横幅が基準ボックスの縦幅1024より大きいです。それはだめですので、次に横幅を1024に当てはまめます。

4-6. AnnotationsのResize処理

RetinaNet物体検出1.009.jpeg
図のように、画像データのResizeが行うとともに、AnnotationsのResizeも行う必要があります。具体的には4-1、4-2から計算されたscaleとAnnotations掛け算します。

4-7. Padding処理

RetinaNet物体検出1.010.jpeg
最後に、Padding処理を行います。現在の縦幅と横幅を32個の1X1の要素を入れようとします。
どれぐらい1X1の要素を入れるのは横幅と縦幅から32とのMOD計算の結果によります。

padding_w = w + 32 - w % 32
padding_h = h + 32 - h % 32

ソースコード

test_image_flip

def test_image_flip(path):
    image = skimage.io.imread(path)  # (H,W,C)

    b = image.astype(np.float32) / 255.0
    skimage.io.imshow(b)
    skimage.io.show()

    c = b[:, ::-1, :]
    skimage.io.imshow(c)
    skimage.io.show()

retina1.png

test_normalization


def test_normalization(path):
    image = skimage.io.imread(path)  # (H,W,C)

    image = image.astype(np.float32) / 255.0
    skimage.io.imshow(image)
    skimage.io.show()


    mean = np.array([[[0.485, 0.456, 0.406]]])
    std = np.array([[[0.229, 0.224, 0.225]]])
    transformedImage = (image.astype(np.float32) - mean) / std

    skimage.io.imshow(transformedImage)
    skimage.io.show()

retina2.png

test_resize

def test_resize(path):
    smallerLineMaxLength = 608
    largerLineMaxLength = 1024

    image = skimage.io.imread(path)

    skimage.io.imshow(image)
    skimage.io.show()

    imageWidth = image.shape[1]
    imageHeight = image.shape[0]

    matchMin = min(imageWidth, imageHeight)
    matchMax = max(imageWidth, imageHeight)

    scale = smallerLineMaxLength / matchMin

    resizedMax = int(matchMax * scale)

    if resizedMax > largerLineMaxLength:
        scale = largerLineMaxLength / matchMax

    resizedWidth = int(imageWidth * scale)
    resizedHeight = int(imageHeight * scale)
    trasformedImage = skimage.transform.resize(image, (resizedHeight, resizedWidth))

    skimage.io.imshow(trasformedImage)
    skimage.io.show()

    paddingHeight = 32 - int(resizedHeight) % 32
    paddingWidth = 32 - int(resizedWidth) % 32

    newImageStruc = np.zeros((resizedHeight + paddingHeight, resizedWidth + paddingWidth, 3))
    print(newImageStruc.shape)
    newImageStruc[:resizedHeight, :resizedWidth, :] = trasformedImage

    skimage.io.imshow(newImageStruc)
    skimage.io.show()

retina3.png

まとめ

今回RetineNet第一節はデータの前処理を紹介しました
次回はモデルを詳しく紹介します

1
1
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
1
1