OpenCVは2つの変換関数cv2.warpAffine と cv2.warpPerspective を提供している. cv2.warpAffine
は2x3の変換行列を入力するのに対して cv2.warpPerspective は3x3の変換行列を入力とする.
スケーリングは画像のサイズ変更のみを行う.この変換のために cv2.resize() 関数が用意されている.変更後の画像サイズもしくは縮尺を指定する必要がある.補間方法には複数あるが,縮小にはcv2.INTER_AREA
,拡大には cv2.INTER_CUBIC
(処理が遅い) や cv2.INTER_LINEAR
が適している.デフォルトnの補間方法は cv2.INTER_LINEAR
である.以下に示すいずれかの方法を使ってスケーリングができる (対象画像):
import cv2
import numpy as np
img = cv2.imread('messi5.jpg')
res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
#OR
# height, width = img.shape[:2]
# res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
%matplotlib inline
import matplotlib.pyplot as plt
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
res=cv2.cvtColor(res,cv2.COLOR_BGR2RGB)
plt.figure(figsize=(15,8))
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(res)
plt.show()
%matplotlib inline
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
plt.figure(figsize=(15,8))
plt.subplot(1,2,1)
plt.imshow(img,cmap='gray')
plt.subplot(1,2,2)
plt.imshow(dst,cmap='gray')
plt.show()
Warning: cv2.warpAffine(img,M,Size)
関数の第3引数Sizeには出力画像のサイズを (width, height)
という形式で指定しなければならない。ここでwidth
は列の数,height
は行の数である.
画像を $\theta$ラジアン回転させるための変換行列は次である.
$\boldsymbol{M} = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix}$
OpenCVが提供する回転は拡大縮小(スケーリング)も同時に行い,回転の中心位置も変更できる.回転変換を表す変換行列は以下のようになる.
$\begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot \textrm{center}.x - \beta \cdot \textrm{center}.y \\ - \beta & \alpha & \beta \cdot \textrm{center}.x + (1- \alpha ) \cdot \textrm{center}.y \end{bmatrix}$
ここで center.x
とcenter.y
は回転中心の座標、scale
は拡大率で、$\alpha$と$\beta$は以下:
$\begin{array}{l} \alpha = scale \cdot \cos \theta , \\ \beta = scale \cdot \sin \theta \end{array}$
この変換行列を計算するために cv2.getRotationMatrix2D
関数が用意されている.次の例はスケーリングをせずに画像中心に対して90度回転する変換を行う(対象画像) :
%matplotlib inline
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.figure(figsize=(15,8))
plt.subplot(1,2,1)
plt.imshow(img,cmap='gray')
plt.subplot(1,2,2)
plt.imshow(dst,cmap='gray')
plt.show()
%matplotlib inline
import matplotlib.pyplot as plt
import cv2
import numpy as np
img = cv2.imread('drawing.png')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.figure(figsize=(10,5))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
%matplotlib inline
import matplotlib.pyplot as plt
import cv2
import numpy as np
img = cv2.imread('sudokusmall.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))
plt.figure(figsize=(10,5))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()