LoginSignup
0
0

More than 1 year has passed since last update.

アフィン変換・射影変換の処理時間比較

Posted at

1.はじめに

Open CVを使って画像を回転させるとき、
・アフィン変換
 dst_img = cv2.warpAffine(src_img, Mat, (width, height))
・射影変換
 dst_img = cv2.warpPerspective(src_img, Mat, (width, height))
という、よく似た2通りのやり方がある。
(実は他にもあるかもしれないが、筆者は知らない)

形の上での違いは、アフィン変換は変換行列が2×3であるのに対して、射影変換は3×3であること。
これは、アフィン変換行列を求める
 Mat = getAffineTransform(src_points, dst_points)
が3点→3点の対応であるのに対し、射影変換の変換行列を求める
 Mat = getPerspectiveTransform(src_points, dst_points)
が4点→4点の対応であることと符合する。

厳密性を犠牲にすれば、
・アフィン変換は矩形を平行四辺形に移す変換(あるいはその逆)
・射影変換は矩形を任意の四角形に移す変換(あるいはその逆)
と考えれば感覚的に理解できる。

単なる回転を考える場合はどちらでも構わないように思うが、どちらの処理が速いか、実際に処理時間を測定して調べてみる。

2.実装

2.1 準備

import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
# OpenCVの画像を画面表示する関数
def show_img_cv2(img_cv2):
    img_RGB = cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB)
    plt.imshow(img_RGB)
# 処理の対象となる画像をread
img = cv2.imread('img/lenna.png')
h, w = img.shape[:2]
print(f'heit: {h}  width: {w}')
show_img_cv2(img)
heit: 512  width: 512

lenna.png

2.2 アフィン変換:cv2.warpAffine()を使って画像を回転

mat1 = cv2.getRotationMatrix2D((300, 200), 10, 1)
print('アフィン行列:')
print(mat1)
rotated_img1 = cv2.warpAffine(img, mat1, (w, h))
cv2.imwrite('affine_img.png', rotated_img1)
show_img_cv2(rotated_img1)
アフィン行列:
[[  0.98480775   0.17364818 -30.17196144]
 [ -0.17364818   0.98480775  55.1329027 ]]

affine_img.png

2.3 射影変換:cv2.warpPerspective()を使って画像を回転

mat2 = np.concatenate([mat1, np.array([[0, 0, 1]])], 0)
print('射影変換行列:')
print(mat2)
rotated_img2 = cv2.warpPerspective(img, mat2, (w, h))
cv2.imwrite('perspected_img.png', rotated_img2)
show_img_cv2(rotated_img2)
射影変換行列:
[[  0.98480775   0.17364818 -30.17196144]
 [ -0.17364818   0.98480775  55.1329027 ]
 [  0.           0.           1.        ]]

perspected_img.png

アフィン変換、射影変換で、同じ回転画像が得られた。

2.4 処理時間の比較

timeitモジュールを使って、10000回ずつ処理を繰り返した際の平均処理時間を求める

import timeit
loop = 10000
result1 = timeit.timeit(lambda: cv2.warpAffine(img, mat1, (w, h)), number=loop)
print(f'warpAffine : {result1 / loop}')

result2 = timeit.timeit(lambda: cv2.warpPerspective(img, mat2, (w, h)), number=loop)
print(f'warpPerspective : {result2 / loop}')

warpAffine : 0.0010326173099980225
warpPerspective : 0.0012882464599970262

3.結論

warpPerspective()はwarpAffine()に比べると少し遅い

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0