クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

移動・回転・拡大縮小の行列

このレッスンのあとで: 行列を使って、図形の点を移動、拡大縮小、回転できる。

75分のレッスンコマンド3件コンピュータビジョンラボ:JupyterLab でピクセル、しきい値、物の数え方

2D変換は点を動かす計算

2D変換とは、図形の点を動かして、移動、回転、拡大縮小をする計算です。ゲームの絵が動くのも、地図が拡大されるのも、この変換でできています。

変換は、3 × 3 の数の表、行列を使うと、すべて同じ形の計算で書けます。このレッスンでは、行列で三角形の点を動かします。

このレッスンのゴール

メモ

行列を使って、図形の点を移動、拡大縮小、回転できる。

キーワード

ことばいみれい
変換図形の点を、決まった規則で動かすこと
行列数を行と列に並べた表3 × 3
同次座標点 (x, y) を (x, y, 1) と書く方法
移動すべての点を、同じだけずらすこと
拡大縮小x と y を何倍かにすること
回転原点を中心に、点をまわすこと

学生が入力するセルは、このプレビューでは空白です。

移動は足し算、拡大縮小はかけ算

点 (x, y) を右へ 5、下へ 2 ずらすには、x に 5、y に 2 を足します。これが移動です。

拡大縮小は、x と y に倍率をかけます。倍率が 2 なら、原点から見て 2 倍の遠さになります。

点 (3, 1) を動かす3つの例

変換規則結果
右へ 5、下へ 2 の移動x + 5、y + 2(8, 3)
2 倍の拡大x × 2、y × 2(6, 2)
x だけ 3 倍x × 3、y はそのまま(9, 1)

学生が入力するセルは、このプレビューでは空白です。

行列を使うと、すべて同じ形で書ける

移動は足し算、拡大縮小はかけ算で、形が違います。そこで点を (x, y, 1) と書き、3 × 3 の行列をかけると、どちらも同じかけ算になります。この書き方が同次座標です。

新しい x は、行列の1行目と (x, y, 1) の、対応する数をかけて足した値です。2行目から新しい y が求まり、3行目は、いつも 1 になります。

3つの行列の形

変換行列の行点の結果
移動 (dx, dy)(1, 0, dx)、(0, 1, dy)、(0, 0, 1)(x + dx, y + dy)
拡大縮小 (sx, sy)(sx, 0, 0)、(0, sy, 0)、(0, 0, 1)(x × sx, y × sy)
90 度の回転(0, -1, 0)、(1, 0, 0)、(0, 0, 1)(-y, x)

学生が入力するセルは、このプレビューでは空白です。

行列と点をかけ算する

コード: python
move = [[1, 0, 4], [0, 1, 2], [0, 0, 1]]
point = [3, 1, 1]
result = []
for row in range(3):
    total = 0
    for column in range(3):
        total = total + move[row][column] * point[column]
    result.append(total)
print(result)
# move の 4 を 10 に変えて、もう一度実行します。
# x の結果は、いくつになりますか。

90 度の回転は、整数だけで書ける

原点を中心に点を 90 度回す行列は、0 と 1 と -1 だけでできています。点 (3, 1) を回すと、(-1, 3) になります。

数学の図では y が上向きなので、反時計回りです。画面では y が下向きなので、見た目は時計回りになります。次のコマンドで、numpy でも確かめます。

90 度の行列を点 (3, 1) にかける

コマンド
docker exec jupyter python3 -c "import numpy as np; m = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]]); print(m @ np.array([3, 1, 1]))"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

かける順番で、結果が変わる

2つの変換を続けるには、行列どうしをかけて1つにまとめます。ただし、かける順番を変えると、結果が変わります。

点にいちばん近い、右側の行列が、最初に働きます。「拡大してから移動」と「移動してから拡大」は、別の変換です。次のコマンドは、点 (1, 1) で2つの順を比べます。

拡大と移動の順番を入れかえる

コマンド
docker exec jupyter python3 -c "import numpy as np; move = np.array([[1, 0, 5], [0, 1, 0], [0, 0, 1]]); big = np.array([[2, 0, 0], [0, 2, 0], [0, 0, 1]]); p = np.array([1, 1, 1]); print(move @ big @ p, big @ move @ p)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

行列をかける順番は、読む順と同じと考えがちです。実際は、点に近い右側の行列が先に働きます。「拡大してから移動」は、移動の行列 × 拡大の行列 と書きます。

三角形を動かして、画像に描く

次のコマンドは、三角形の3つの点を、右へ 40、下へ 10 動かします。元の三角形と動かした三角形を、白い線で同じ画像に描き、moved.png に保存します。

moved.png を開くと、黒い地に、同じ形の三角形が2つ見えます。右の三角形は、左の三角形より右下にずれています。

三角形を動かして moved.png に保存

コマンド
docker exec jupyter python3 -c "import numpy as np; from PIL import Image, ImageDraw; im = Image.new('L', (80, 60), 0); d = ImageDraw.Draw(im); tri = [(10, 10), (30, 10), (10, 40)]; d.polygon(tri, outline=255); m = np.array([[1, 0, 40], [0, 1, 10], [0, 0, 1]]); moved = [tuple(int(v) for v in (m @ np.array([x, y, 1]))[:2]) for x, y in tri]; d.polygon(moved, outline=255); im.resize((320, 240), Image.NEAREST).save('moved.png'); print(moved); print(im.getpixel((10, 10)), im.getpixel((50, 20)), im.getpixel((30, 30)))"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

このラボとソースについて: コンピュータビジョンラボ:JupyterLab でピクセル、しきい値、物の数え方

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。