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] ]) )