| import math | |
| import cv2 | |
| import numpy as np | |
| import numpy.linalg as npla | |
| from .umeyama import umeyama | |
| def get_power_of_two(x): | |
| i = 0 | |
| while (1 << i) < x: | |
| i += 1 | |
| return i | |
| def rotationMatrixToEulerAngles(R) : | |
| sy = math.sqrt(R[0,0] * R[0,0] + R[1,0] * R[1,0]) | |
| singular = sy < 1e-6 | |
| if not singular : | |
| x = math.atan2(R[2,1] , R[2,2]) | |
| y = math.atan2(-R[2,0], sy) | |
| z = math.atan2(R[1,0], R[0,0]) | |
| else : | |
| x = math.atan2(-R[1,2], R[1,1]) | |
| y = math.atan2(-R[2,0], sy) | |
| z = 0 | |
| return np.array([x, y, z]) | |
| def polygon_area(x,y): | |
| return 0.5*np.abs(np.dot(x,np.roll(y,1))-np.dot(y,np.roll(x,1))) | |
| def rotate_point(origin, point, deg): | |
| """ | |
| Rotate a point counterclockwise by a given angle around a given origin. | |
| The angle should be given in radians. | |
| """ | |
| ox, oy = origin | |
| px, py = point | |
| rad = deg * math.pi / 180.0 | |
| qx = ox + math.cos(rad) * (px - ox) - math.sin(rad) * (py - oy) | |
| qy = oy + math.sin(rad) * (px - ox) + math.cos(rad) * (py - oy) | |
| return np.float32([qx, qy]) | |
| def transform_points(points, mat, invert=False): | |
| if invert: | |
| mat = cv2.invertAffineTransform (mat) | |
| points = np.expand_dims(points, axis=1) | |
| points = cv2.transform(points, mat, points.shape) | |
| points = np.squeeze(points) | |
| return points | |
| def transform_mat(mat, res, tx, ty, rotation, scale): | |
| """ | |
| transform mat in local space of res | |
| scale -> translate -> rotate | |
| tx,ty float | |
| rotation int degrees | |
| scale float | |
| """ | |
| lt, rt, lb, ct = transform_points ( np.float32([(0,0),(res,0),(0,res),(res / 2, res/2) ]),mat, True) | |
| hor_v = (rt-lt).astype(np.float32) | |
| hor_size = npla.norm(hor_v) | |
| hor_v /= hor_size | |
| ver_v = (lb-lt).astype(np.float32) | |
| ver_size = npla.norm(ver_v) | |
| ver_v /= ver_size | |
| bt_diag_vec = (rt-ct).astype(np.float32) | |
| half_diag_len = npla.norm(bt_diag_vec) | |
| bt_diag_vec /= half_diag_len | |
| tb_diag_vec = np.float32( [ -bt_diag_vec[1], bt_diag_vec[0] ] ) | |
| rt = ct + bt_diag_vec*half_diag_len*scale | |
| lb = ct - bt_diag_vec*half_diag_len*scale | |
| lt = ct - tb_diag_vec*half_diag_len*scale | |
| rt[0] += tx*hor_size | |
| lb[0] += tx*hor_size | |
| lt[0] += tx*hor_size | |
| rt[1] += ty*ver_size | |
| lb[1] += ty*ver_size | |
| lt[1] += ty*ver_size | |
| rt = rotate_point(ct, rt, rotation) | |
| lb = rotate_point(ct, lb, rotation) | |
| lt = rotate_point(ct, lt, rotation) | |
| return cv2.getAffineTransform( np.float32([lt, rt, lb]), np.float32([ [0,0], [res,0], [0,res] ]) ) | |