2017-02-28

アフィン変形の他の座標を取得する【Python】

前回の「 Python で画像を引っぱるように歪める」に引き続き python を使ったアフィン変形(回転、縮小/拡大、並行移動を一括で行う変形)のお話です。

アフィン変形は3点を使って回転などをするのですが、数学が苦手な私には「じゃあ、その他の座標はどうやって計算するの?」ということがわかりませんでした。
そこで、今回も備忘録的にこの記事を書きたいと思います。



まずはアフィン変形の使い方(Python)

使い方は簡単で、移動前と移動先の3つの点(つまり三角形)を行列にして変形させるだけ。
コードはこんな感じです。

 import cv2
 import numpy as np
 im = cv2.imread('squares.jpg')  
 points1 = [[50,50],[150,50],[50,150]]  
 points2 = [[75,75],[150,50],[50,150]]  
 M = cv2.getAffineTransform(np.float32(points1), np.float32(points2))  
 im2 = cv2.warpAffine(im, M, (200,200))  
 cv2.imwrite('transformed_squares.jpg', im2)  

(流れ)
1.画像を読み込む
2.移動前の点を決める
3.移動後の点を決める
4.上の2つを使って行列を取得
5.200x200サイズでアフィン変形する
6.画像を保存

※つまり、他の2点は同じなので、(50,50) の点を (75,75)に移動させるだけになります。


実際に画像は以下になります。

(変形前)


(変換後)



移動した後、その他の点は?

さぁ、ではここからが本題です。
先ほど見ていただいた画像の右下に「?」マークと少し大きな赤丸があったかと思います。
この点は変形前は (150,150) の位置にあります。
じゃあ、変形後の座標をどうやって計算したらいいの?を解決する方法です。

実際のコードはこんな形です。

 import numpy as np 
 point = np.float32((150,150))  
 x = point[0]
 y = point[1]
 new_x = M[0][0]*x + M[0][1]*y + np.float32(M[0][2])  
 new_y = M[1][0]*x + M[1][1]*y + np.float32(M[1][2])  
 print (int(new_x), int(new_y))  

変形前の点を公式に当てはめるだけでOKです。

※ M は上のコードで作った行列になります。


終わりに

行列という概念は高校の数学ででくる(らしい)のですが、正直言って今回初見ぐらいの気分でした。
ただ、画像処理にはとても便利なのでやはりきちんと数学(幾何学?)も勉強していこうと思います。
学生の頃は何に役に立つんだ?と思ってましたが、これはとても役に立つし、正直やってて面白いですね。

新しい発見でした(^o^)



0 件のコメント:

コメントを投稿