Pyhonでアフィン変換をつかって2次元の画像を回転、平行移動させる
座標(x,y)のピクセルをアフィン変換で回転させる場合、変換後の座標(x', y')は以下の式で表すことができます。
それからx軸にx_t, y軸にy_t平行移動も加える場合、は以下の式になります。
これをPythonで実装する場合、変換対象の画像が2次元の配列で表せられるのであれば以下のようになります。
import cv2 import math import numpy as np from matplotlib import pyplot as plt rotate_matrix = lambda radian, x_t, y_t : [[math.cos(radian), math.sin(radian), x_t], [-math.sin(radian), math.cos(radian), y_t]] def dot_gen(map_matrix): return lambda x: np.dot(map_matrix, x) def afin_image(afintrans, image, x_length, y_length, ): afin_result = np.zeros((y_length, x_length)) for y in range(len(image)): for x in range(len(image[y])): if image[y][x] == 0: continue trans_posi = afintrans([[x],[y],[1]]) new_x = math.floor(trans_posi[0][0]) new_y = math.floor(trans_posi[1][0]) if new_x >= 0 and new_x < x_length and new_y >= 0 and new_y < y_length: afin_result[new_y][new_x] = image[y][x] return afin_result afintrans = dot_gen(rotate_matrix(math.radians(-10), 30, 10)) rows,cols = edges.shape afin_result = afin_image(afintrans, edges, cols, rows) plt.subplot(122),plt.imshow(afin_result,cmap = 'gray') plt.title('Rotate Edge Image'), plt.xticks([]), plt.yticks([]) plt.show() cv2.imwrite("rotate.png", afin_result)
ここでは画像を-10度回転させてx軸に30, y軸に10移動させています。 これにより以下のように画像が変換されます。
変換前
変換後
OpenCVのアフィン変換で回転、平行移動させる
Pythonで愚直に実装する場合はこのようになると思うのですが、実際使うとしたら遅かったり、OpenCVですでに実装されているのでそちらで動かしてみたいと思います。 OpenCVでは以下のように簡単に使えます。
import cv2 import numpy as np from matplotlib import pyplot as plt radian = math.radians(-10) rows,cols = edges.shape afin_matrix = np.float32([[math.cos(radian), math.sin(radian), 30], [-math.sin(radian), math.cos(radian), 10]]) dst = cv2.warpAffine(edges,afin_matrix,(cols,rows)) plt.subplot(122),plt.imshow(dst,cmap = 'gray') plt.title('Rotate Edge Image'), plt.xticks([]), plt.yticks([]) plt.show() cv2.imwrite("rotate.png", afin_result)