Spaces:
Paused
Paused
File size: 5,407 Bytes
1cac303 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import math
import numpy as np
import random
# ** core **
def get_affine_matrix(center, angle, translate, scale, shear=0):
# Helper method to compute affine transformation
# As it is explained in PIL.Image.rotate
# We need compute affine transformation matrix: M = T * C * RSS * C^-1
# where T is translation matrix: [1, 0, tx | 0, 1, ty | 0, 0, 1]
# C is translation matrix to keep center: [1, 0, cx | 0, 1, cy | 0, 0, 1]
# RSS is rotation with scale and shear matrix
# RSS(a, scale, shear) = [ cos(a)*sx -sin(a + shear)*sy 0]
# [ sin(a)*sx cos(a + shear)*sy 0]
# [ 0 0 1]
angle = math.radians(angle)
shear = math.radians(shear)
T = np.array([[1, 0, translate[0]], [0, 1, translate[1]], [0, 0, 1]]).astype(np.float32)
C = np.array([[1, 0, center[0]], [0, 1, center[1]], [0, 0, 1]]).astype(np.float32)
RSS = np.array([[ math.cos(angle)*scale[0], -math.sin(angle + shear)*scale[1], 0],
[ math.sin(angle)*scale[0], math.cos(angle + shear)*scale[1], 0],
[ 0, 0, 1]]).astype(np.float32)
C_inv = np.linalg.inv(np.mat(C))
M = T.dot(C).dot(RSS).dot(C_inv)
return M
# ** tools **
def get_aug_matrix(srcW, srcH, dstW, dstH, angle_range=(-45, 45), scale_range=(0.5, 1.5), trans_range=(-0.3, 0.3)):
center = (srcW/2.0, srcH/2.0)
init_scale = min(float(dstW)/srcW, float(dstH)/srcH)
angle = random.random()*(angle_range[1]-angle_range[0])+angle_range[0]
sx = sy = random.random()*(scale_range[1]-scale_range[0])+scale_range[0]
scale = (sx*init_scale, sy*init_scale)
tx = random.random()*(trans_range[1]-trans_range[0])+trans_range[0]
ty = random.random()*(trans_range[1]-trans_range[0])+trans_range[0]
translate = (tx*dstW + (dstW-srcW)/2, ty*dstH + (dstH-srcH)/2)
H = get_affine_matrix(center, angle, translate, scale, shear=0)
params = {'center':center, 'angle':angle, 'translate':translate, 'scale':scale, 'shear':0}
return H, params
def warpAffinePoints(pts, H):
# pts: (N, (x,y))
pts = np.array(pts, dtype=np.float32)
assert H.shape in [(3,3), (2,3)], 'H.shape must be (2,3) or (3,3): {}'.format(H.shape)
ext = np.ones((len(pts), 1), dtype=pts.dtype)
return np.array(np.hstack((pts, ext)).dot(H[0:2, :].transpose(1, 0)), dtype=np.float32)
def warpAffineKpts(kpts, H):
# kpts: (N, 17, 3)
warped_kpts = np.array(kpts)
warped_kpts[:, :, 0:2] = warpAffinePoints(warped_kpts[:, :, 0:2].reshape(-1, 2), H).reshape(-1, 17, 2)
inds = np.where(warped_kpts[:, :, 2] == 0)
warped_kpts[inds[0], inds[1], :] = 0
return warped_kpts
def warpAffineBoxes(boxes, H, outer=False):
# pts: (N, (x1,y1,x2,y2))
assert H.shape in [(3,3), (2,3)], 'H.shape must be (2,3) or (3,3): {}'.format(H.shape)
boxes = np.array(boxes, dtype=np.float32)
if outer==False:
assert H[0,1] == H[1,0] == 0, 'warpAffineBoxes(outer=False) do not support rotation: {}'.format(H)
pts1 = warpAffinePoints(boxes[:, 0:2], H)
pts2 = warpAffinePoints(boxes[:, 2:4], H)
return np.hstack((pts1,pts2))
else:
pts1 = warpAffinePoints(boxes[:, 0:2], H)
pts2 = warpAffinePoints(boxes[:, 2:4], H)
pts3 = warpAffinePoints(boxes[:, [0,3]], H)
pts4 = warpAffinePoints(boxes[:, [2,1]], H)
xs = np.hstack((pts1[:, 0:1], pts2[:, 0:1], pts3[:, 0:1], pts4[:, 0:1]))
ys = np.hstack((pts1[:, 1:2], pts2[:, 1:2], pts3[:, 1:2], pts4[:, 1:2]))
xmin, xmax = [np.min(xs, axis = 1, keepdims=True), np.max(xs, axis = 1, keepdims=True)]
ymin, ymax = [np.min(ys, axis = 1, keepdims=True), np.max(ys, axis = 1, keepdims=True)]
return np.hstack((xmin, ymin, xmax, ymax))
def get_cropalign_matrix(box, dstW, dstH, keep_ratio=False):
# box: [x1, y1, x2, y2]
cropM = get_crop_matrix(box)
srcW = box[2] - box[0]
srcH = box[3] - box[1]
if keep_ratio:
alignM = get_resize_padding_matrix(srcW, srcH, dstW, dstH, iscenter=True)
else:
alignM = get_resize_matrix(srcW, srcH, dstW, dstH)
return alignM.dot(cropM)
def get_crop_matrix(box):
# box: [x1, y1, x2, y2]
# This function simply translate the coordinate.
return np.array([[1, 0, -box[0]],
[0, 1, -box[1]],
[0, 0, 1]], dtype=np.float32)
def get_resize_padding_matrix(srcW, srcH, dstW, dstH, iscenter=False):
# this function keep ratio
scalex = scaley = min(float(dstW)/srcW, float(dstH)/srcH)
if iscenter:
translate = ((dstW - srcW * scalex)/2.0, (dstH - srcH * scaley)/2.0)
else:
translate = (0, 0)
return get_affine_matrix(center=(0, 0), angle=0, translate=translate, scale=(scalex, scaley))
def get_resize_matrix(srcW, srcH, dstW, dstH):
# this function do not keep ratio
scalex, scaley = (float(dstW)/srcW, float(dstH)/srcH)
return get_affine_matrix(center=(0, 0), angle=0, translate=(0, 0), scale=(scalex, scaley))
def xfilp_matrix(srcW):
return np.array([[-1, 0, srcW],
[ 0, 1, 0],
[ 0, 0, 1]], dtype=np.float32)
def stride_matrix(factor):
return np.array([[factor, 0, 0],
[ 0, factor, 0],
[ 0, 0, 1]], dtype=np.float32)
|