動画の解説を参照
長方形や平行四辺形のような特徴のない「ただの歪んだ四角形」から「長方形」に変形させる、アフィン変換の中で最も一般的な変換を考えます。

このような変換を行うと、例えばこのような画像 (課題ではこの画像は使わないでください) から
このように一部だけを取り出して整形することができます。

変換行列 \(M\) は元画像の選択エリアの4つの端点 \((x_0, y_0)\) ~ \((x_3, y_3)\) と、出力画像のサイズ new_w, new_h で決まります。
そのため、この変換を行うにはまず4つの端点の座標を調べる必要があります。
Windows環境であれば、ペイントで画像上の座標を調べられます。
「被写体としては長方形だが、斜めに撮ったために歪んでいるもの」が含まれる元画像を使い、その中の使いたい部分の
- 左上の座標
- 右上の座標
- 右下の座標
- 左下の座標
をテキストファイル「ex1.txt」に記録してください。
※ 左上からスタートして時計回りの順番です。
※ Mac環境の人は「プレビュー」などで座標を調べてください (
参考)
元画像の選び方についての注意
変形することで歪みがとれることがわかるような元画像にする必要があります。
大きく写っている本来長方形の、凹凸がなく、斜めに撮影されたせいで歪んでいる被写体があるものを使ってください。
以下は悪い例です。
NG例1 : 被写体がほぼ長方形に写ってしまっているので、次項のコードが正しく動作しているかの検証になりません。
NG例2 : 一応「長方形の被写体 (銅像のプレート)」がありますが、小さすぎて変換後の結果が検証できません。
NG例3 : 長方形の被写体がない画像ももちろんNGです。
NG例4 : 窓や門など、立体的で奥行きがある形もきれいに変換できません。
動画の解説を参照
変換後の形がベストになるように試行錯誤するため、画像のアップロードとサイズを調べる処理だけを別のコードセルとして分けて先に実行しておきます。
import cv2
import numpy as np
from google.colab import files
file = files.upload()
filename = next(iter(file))
img = cv2.imread(filename)
h, w = img.shape[:2]
ここで行う変換もアフィン変換ですが、第2, 3回の「warpAffine」ではなく「warpPerspective」を使います (引数の構成は同じです)。
変換行列 \(M\)
は、「getPerspectiveTransform」で得られます。その第1引数が「変形前の4つの端点の座標の配列」(corners)、第2引数が「変形後の4つの端点の座標の配列」(new_corners) です。
corners には 元画像の中の「使いたいエリア」の4つの端点の座標が入るので、使う画像、使いたいエリアによって値は変わります。
出力画像の横・縦のサイズは、被写体の縦横比に応じて適切な値が変わります。
以下は射影変換を行って画像として保存するコードですが、「
?」には画像に応じた適切な数値を入れる必要があります。
corners = np.array(
[
[?, ?],
[?, ?],
[?, ?],
[?, ?]
], dtype=np.float32)
new_width = ?
new_height = ?
new_corners = np.array(
[
[0, 0],
[new_width, 0],
[new_width, new_height],
[0, new_height]
], dtype=np.float32)
M = cv2.getPerspectiveTransform(corners, new_corners)
img2 = cv2.warpPerspective(img, M, (new_width, new_height))
cv2.imwrite('ex2.jpg', img2)
課題1で調べた4つの座標の値を使い、なるべく縦横の比率の違和感がなくなるように new_width, new_height の値を調整して変形させた画像 ex2.jpg を出力してください。