summer_tree_home

Check iOでPython3をマスターするぜっ

Pattern Recognition (Mine) - パターン認識

どんな問題?

Pattern Recognition
http://www.checkio.org/mission/matrix-pattern/

0と1のモノクロ画像データから、指定のパターンを見つけ出せ。

引数では、パターンと画像が、0と1 の list of list で指定される。
画像の上から順にスキャンしていき、パターンが見つかれば、画像データの 0→2、1→3 の変換を行う。パターンが重なっている場合は、最初に見つかったパターン(左上)が優先される。
戻り値は、変換した画像データを返す。

パターン、画像とも、幅と高さは10以下。

例題:

checkio([[1, 0], [1, 1]],
        [[0, 1, 0, 1, 0],
         [0, 1, 1, 0, 0],
         [1, 0, 1, 1, 0],
         [1, 1, 0, 1, 1],
         [0, 1, 1, 0, 0]]) == [[0, 3, 2, 1, 0],
                               [0, 3, 3, 0, 0],
                               [3, 2, 1, 3, 2],
                               [3, 3, 0, 3, 3],
                               [0, 1, 1, 0, 0]]
checkio([[1, 1], [1, 1]],
        [[1, 1, 1],
         [1, 1, 1],
         [1, 1, 1]]) == [[3, 3, 1],
                         [3, 3, 1],
                         [1, 1, 1]]

どうやって解く?

画像の左上から順番に、パターンと同じサイズを切り出して調べていけばいいかな。
画像 image から、位置(x,y)とサイズ(pw,ph)を指定して取り出すには、

[image[iy][x:x + pw] for iy in range(y, y + ph)]

となる。これをパターンと比較すればいい。

パターンが見つかったときの、0→2、1→3 の変換もスライスを使って行った。

for iy in range(y, y + ph):
    image[iy][x:x + pw] = [e + 2 for e in image[iy][x:x + pw]]

メモ:スライスを使ったリストの置換

今まであまり使ったことがなかったが、Pythonでは、スライスを使ってリストの要素を置換できる。

>>> a = [1, 2, 3, 4, 5]
>>> a[2:4]
[3, 4]
>>> a[2:4] = [6, 7]  # スライスに代入
>>> a
[1, 2, 6, 7, 5]
>>> a[2:4] = [8, 9, 10]  # 要素数が異なってもOK
>>> a
[1, 2, 8, 9, 10, 5]

まとめ

def checkio(pattern, image):
    pw, ph = len(pattern[0]), len(pattern)
    iw, ih = len(image[0]), len(image)
    for y in range(ih - ph + 1):
        for x in range(iw - pw + 1):
            if [image[iy][x:x + pw] for iy in range(y, y + ph)] == pattern:
                for iy in range(y, y + ph):
                    image[iy][x:x + pw] = [e + 2 for e in image[iy][x:x + pw]]
    return image

http://www.checkio.org/mission/matrix-pattern/publications/natsuki/python-3/first/