Python + OpenCV4プログラミングの学習(4)〜アフィン変換〜
本記事はOpenCVによるアフィン変換を行ったときの備忘録である。
アフィン変換とは...
図形を回転させたり引き延ばしたりする変換 ja.wikipedia.org
事前準備
以下の記事で仮想環境opencvEnvを構築していることを前提とする。 kawakeee.hatenablog.com
また、任意の画像を用意しておく。今回はLenna.jpgを用意した。
フリップ
以下のコードを写経しflip.pyのファイルを作成。
import cv2 try: img = cv2.imread('img/Lenna.jpg') if img is None: print('ファイルを読み込めません') import sys sys.exit() # 画像を上下反転させる dst = cv2.flip(img, 0) cv2.imwrite('img/flip0.jpg', img) cv2.imshow('dst1', dst) # 画像を左右反転させる dst = cv2.flip(img, 1) cv2.imwrite('img/flip1.jpg', img) cv2.imshow('dst2', dst) # 画像を両軸反転させる dst = cv2.flip(img, -1) cv2.imwrite('img/flip2.jpg', img) cv2.imshow('dst3', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
- cv2.flip(...):画像をフリップ(反転)させる
使用例:cv2.flip(img, 0)
引数は、順に(対象画像データ, フリップ方向)を表す。 以下のように、フリップ方向の値により反転軸を指定できる。
フリップ方向の値 | 反転方向 |
---|---|
0に等しい | 上下反転 |
正 | 左右反転 |
負 | 両軸反転 |
実行結果
(opencvEnv)$ python filp.py
指定フォルダ配下にフリップされた画像が生成されていることを確認。
リサイズ
以下のコードを写経しresize.pyのファイルを作成。
import cv2 try: img = cv2.imread('img/Lenna.jpg') if img is None: print('ファイルを読み込めません') import sys sys.exit() SCALE = 0.5 SCALE2 = 1.62 # 画像の高さ・幅を取得 height = img.shape[0] width = img.shape[1] # 画像を半分(0.5乗じる)のサイズにリサイズ dst = cv2.resize(img, (int(width*SCALE), int(height*SCALE))) cv2.imwrite('img/resize0.5.jpg', dst) cv2.imshow('dst1', dst) # 画像を1.62乗じてリサイズ dst = cv2.resize(img, (int(width*SCALE2), int(height*SCALE2))) cv2.imwrite('img/resize1.62.jpg', dst) cv2.imshow('dst2', dst) # 画像を縦を圧縮してリサイズ dst = cv2.resize(img, (400, 200)) cv2.imwrite('img/resize400*200.jpg', dst) cv2.imshow('dst3', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
変数SCALE
を用意して半分(0.5をかける)のサイズにリサイズしている。
- cv2.resize(...):画像をリサイズする
使用例:cv2.resize(img, (400, 200))
引数は、順に(対象画像,幅, 高さ)を表す。実行結果
(opencvEnv)$ python resize.py
指定フォルダ配下にリサイズされた画像が生成されていることを確認。
回転
以下のコードを写経しrotate.pyのファイルを作成。
import cv2 try: img = cv2.imread('img/Lenna.jpg') if img is None: print('ファイルを読み込めません') import sys sys.exit() # 画像の高さ・幅を取得 height = img.shape[0] width = img.shape[1] # 回転原点座標を生成 center = (int(width/2), int(height/2)) # 回転変換行列の生成 (回転原点座標, 回転角度, スケーリング値) affin_trans = cv2.getRotationMatrix2D(center, 33.0, 1.0) # 回転変換処理 (対象画像, 回転変換行列, 出力配列(画像サイズの指定)) dst = cv2.warpAffine(img, affin_trans, (width, height)) cv2.imwrite('img/rotate033.jpg', dst) cv2.imshow('dst1', dst) affin_trans = cv2.getRotationMatrix2D(center, 110.0, 1.2) dst = cv2.warpAffine(img, affin_trans, (width, height), flags=cv2.INTER_CUBIC) cv2.imwrite('img/rotate110.jpg', dst) cv2.imshow('dst2', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
順に、対象画像を反時計周りの方向に33°、110°回転させる。
- cv2.getRotationMatrix2D(...):回転変換行列の生成
使用例:cv2.getRotationMatrix2D(center, 33.0, 1.0)
引数は、順に(回転原点座標,回転角度,スケーリング値)を表す。 - cv2.warpAffine(...):画像のアフィン変換を実行
使用例:cv2.warpAffine(img, affin_trans, (width, height))
引数は、順に(対象画像,変換行列,出力配列(画像サイズ))を表す。
実行結果
(opencvEnv)$ python rotate.py
指定フォルダ配下に回転された画像が生成されていることを確認。
透視投影
以下のコードを写経しperspective.pyのファイルを作成。
import cv2 import numpy as np try: # (225 * 225)の画像 img = cv2.imread('img/Lenna.jpg') if img is None: print('ファイルを読み込めません') import sys sys.exit() # 画像の列・行の大きさを取得 rows,cols = img.shape[:2] x0 = cols/4 x1 = (cols*3)/4 y0 = rows/4 y1 = (rows*3)/4 # 入力の座標を指定 list_srcs = np.float32([ [x0, y0], [x0, y1], [x1, y1], [x1, y0] ]) # pattern-0 x_margin = cols/10 y_margin = rows/10 # 出力の座標を指定(台形) list_dsts = np.float32([ [x0+x_margin, y0+y_margin], list_srcs[1], list_srcs[2], [x1-x_margin, y0+y_margin] ]) # 透視変換行列の生成 (入力座標, 出力座標) perspective_matrix = cv2.getPerspectiveTransform(list_srcs, list_dsts) # 画像の透視投影処理 (対象画像, 透視変換行列, 出力配列(画像サイズの指定)) dst = cv2.warpPerspective(img, perspective_matrix, (cols, rows)) cv2.imwrite('img/dst0.jpg', dst) cv2.imshow('dst0', dst) #pattern-1 x_margin = cols/8 y_margin = rows/8 list_dsts = np.float32([list_srcs[0],list_srcs[1],[x1-x_margin, y1-y_margin],[x1-x_margin, y0+y_margin]]) perspective_matrix = cv2.getPerspectiveTransform(list_srcs,list_dsts) dst = cv2.warpPerspective(img, perspective_matrix, (cols, rows)) cv2.imwrite('img/dst1.jpg', dst) cv2.imshow('dst1', dst) #pattern-2 x_margin = cols/6 y_margin = rows/6 list_dsts = np.float32([[x0+x_margin, y0+y_margin],list_srcs[1],[x1-x_margin, y1-y_margin],list_srcs[3]]) perspective_matrix = cv2.getPerspectiveTransform(list_srcs,list_dsts) dst = cv2.warpPerspective(img, perspective_matrix, (cols, rows)) cv2.imwrite('img/dst2.jpg', dst) cv2.imshow('dst2', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
list_srcs
に入力座標、list_dsts
に出力座標を指定し、3パターンの透視投影を実行。
- cv2.getPerspectiveTransform(...):透視変換行列の生成
使用例:cv2.getPerspectiveTransform(list_srcs, list_dsts)
引数は、順に(入力座標,出力座標)を表す。返戻値は引数に対する透視変換行列。 - cv2.warpPerspective(...):画像の透視投影を実行
使用例:cv2.warpPerspective(img, perspective_matrix, (cols, rows))
引数は、順に(対象画像,透視変換行列,出力配列(画像サイズ))を表す。
実行結果
(opencvEnv)$ python perspective.py
指定フォルダ配下に透視投影された画像が生成されていることを確認。
トリミング
以下のコードを写経しtrimming.pyのファイルを作成。
import cv2 try: img = cv2.imread('img/Lenna.jpg') if img is None: print('ファイルを読み込めません') import sys sys.exit() # 画像の高さ・幅を取得 height = img.shape[0] width = img.shape[1] # imgをスライス処理してトリミング dst = img[40:height, 40:width] cv2.imwrite('img/Trimming.jpg', dst) cv2.imshow('dst0', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
トリミングはimgに対してスライスする事で可能。元画像の上部、左側の40pxを除去させる。
実行結果
(opencvEnv)$ python trimming.py
指定フォルダ配下にトリミングされた画像が生成されていることを確認。
まとめ
- cv2.flip(...):画像をフリップ(反転)させる
- cv2.getRotationMatrix2D(...):回転変換行列の生成
- cv2.warpAffine(...):画像のアフィン変換を実行
- cv2.getPerspectiveTransform(...):透視変換行列の生成
- cv2.warpPerspective(...):画像の透視投影を実行