第2回 回転

本題に入る前に、必ず 連絡 の動画を見てください。
Google Colabへのリンク

1. 画像を時計回りに90°回転させる

動画の解説を参照

OpenCVのライブラリにある関数「rotate」を使えば、画像を回転させられます。
第1引数が元画像の情報が入った変数、第2引数は「どれだけ回転させるか」を表す量です。
特に、時計回りに90°回転させる場合はもともと用意されている「cv2.ROTATE_90_CLOCKWISE」をいれるだけです。
(以下のコードの1~6行目は第1回の1つ目の項目のコードと同じです)
import cv2
from google.colab import files

file = files.upload()
filename = next(iter(file))
img = cv2.imread(filename)
img1 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
cv2.imwrite('ex1.jpg', img1)
このコードを実行すると、例えばこのような元画像

からこのような ex1.jpg ができます。

課題1

適当な画像を読み込んで、概要のコードで時計回りに90°回転させた画像「ex1.jpg」を出力してください。

2. 画像を反時計回りに90°回転させる

動画の解説を参照

rotate関数の第2引数を「cv2.ROTATE_90_COUNTERCLOCKWISE」にすると、反時計回りに90°回転します。
img2 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
cv2.imwrite('ex2.jpg', img2)

課題2

課題1と同じ画像を概要のコードで反時計回りに90°回転させた画像「ex2.jpg」を出力してください。

3. 画像を180°回転させる

動画の解説を参照

rotate関数の第2引数を「cv2.ROTATE_180」にすると、180°回転します。
img3 = cv2.rotate(img, cv2.ROTATE_180)
cv2.imwrite('ex3.jpg', img3)

課題3

課題1と同じ画像を概要のコードで180°回転させた画像「ex3.jpg」を出力してください。

4. 画像を反時計回りに30°回転させる (はみ出しを考慮しない)

動画の解説を参照

90°や180°のような、回転後もちょうど長方形に収まるような回転ではなく、30°のような半端な回転では少し複雑になります。
使うのは「warpAffine」関数です。これは回転だけでなく、拡大・縮小や平行移動、次回行う「スキュー」を含んだ変換ができる命令です。
第1引数は画像の情報が入った変数、第2引数が変換行列、第3引数が出力画像のサイズです。
変換行列は
\(M= \begin{bmatrix} a & b & c \\ d & e & f \end{bmatrix} \)
という、2行3列の形の行列です。
回転角を \(\theta\), 回転の中心の座標を \((x_c, y_c)\) とすると、
\( \begin{eqnarray} a&=&\cos\theta\\ b&=&\sin\theta\\ c&=&x_c(1-\cos\theta)-y_c\sin\theta\\ d&=&-\sin\theta\\ e&=&\cos\theta\\ f&=&x_c\sin\theta+y_c(1-\cos\theta) \end{eqnarray} \)
です。ただし、これら6つの値をそれぞれ計算する必要はなく、「getRotationMatrix2D」関数で求められます。
第1引数は回転中心の座標、第2引数は回転角、第3引数は拡大率 (この場合は1.0) です。
h, w = img.shape[:2]
center = (w / 2, h / 2)
angle = 30
M = cv2.getRotationMatrix2D(center, angle, 1.0)
print (M) # 変換行列の値をコンソールに表示
img4 = cv2.warpAffine(img, M, (w, h))
cv2.imwrite('ex4.jpg', img4)
このコードでは回転の中心を元画像の中心に設定しているので、このように端の部分が画像からはみ出してしまいます。

課題4

課題1と同じ画像を概要のコードで反時計回りに30°回転させた画像「ex4.jpg」を出力してください。

5. 画像を反時計回りに30°回転させる (はみ出さないようにサイズを修正)

動画の解説を参照

前の項のようなはみ出しを防ぐには、回転させた形に合わせて出力画像の大きさを変え、回転の中心の位置もずらす必要があります。
そのような画像の横・縦の幅は、元画像の横・縦の幅と \(\sin\theta, \cos\theta\) の絶対値から計算できます。
以下のコードでは、絶対値を取る関数「abs」を使うためにライブラリ「numpy」を読み込んでいます。
(前項で求めた M を再度計算しているのは、それ以降の行で M の成分の値を書き替えているためです。これがないと、複数回実行すると成分の値がどんどんずれていってしまいます)
import numpy as np

M = cv2.getRotationMatrix2D(center, angle, 1.0)
co = np.abs(M[0, 0])
si = np.abs(M[0, 1])
new_w = int(w * co + h * si)
new_h = int(w * si + h * co)
M[0, 2] += (new_w - w) /2.0
M[1, 2] += (new_h - h) /2.0
img5 = cv2.warpAffine(img, M, (new_w, new_h))
cv2.imwrite('ex5.jpg', img5)

課題5

課題1と同じ画像を概要のコードで反時計回りに30°回転させ、全体が収まるようにサイズを調整した画像「ex5.jpg」を出力してください。

提出

動画の解説を参照

今回作成したノートブックと画像の入ったフォルダを「imgprc2024@gmail.com」と共有してください。
※ 課題の再提出の際は、ノートブックやフォルダの再度の共有はせずにチャットで連絡してください。