Jjtumarai's picture
deploy: bodyfat estimation app
1cac303
Raw
History Blame Contribute Delete
5.41 kB
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)