strexp / augmentation /geometry.py
markytools's picture
added strexp
d61b9c7
raw
history blame
5.93 kB
import cv2
import numpy as np
from PIL import Image, ImageOps
'''
PIL resize (W,H)
Torch resize is (H,W)
'''
class Shrink:
def __init__(self):
self.tps = cv2.createThinPlateSplineShapeTransformer()
self.translateXAbs = TranslateXAbs()
self.translateYAbs = TranslateYAbs()
def __call__(self, img, mag=-1, prob=1.):
if np.random.uniform(0,1) > prob:
return img
W, H = img.size
img = np.array(img)
srcpt = list()
dstpt = list()
W_33 = 0.33 * W
W_50 = 0.50 * W
W_66 = 0.66 * W
H_50 = 0.50 * H
P = 0
#frac = 0.4
b = [.2, .3, .4]
if mag<0 or mag>=len(b):
index = 0
else:
index = mag
frac = b[index]
# left-most
srcpt.append([P, P])
srcpt.append([P, H-P])
x = np.random.uniform(frac-.1, frac)*W_33
y = np.random.uniform(frac-.1, frac)*H_50
dstpt.append([P+x, P+y])
dstpt.append([P+x, H-P-y])
# 2nd left-most
srcpt.append([P+W_33, P])
srcpt.append([P+W_33, H-P])
dstpt.append([P+W_33, P+y])
dstpt.append([P+W_33, H-P-y])
# 3rd left-most
srcpt.append([P+W_66, P])
srcpt.append([P+W_66, H-P])
dstpt.append([P+W_66, P+y])
dstpt.append([P+W_66, H-P-y])
# right-most
srcpt.append([W-P, P])
srcpt.append([W-P, H-P])
dstpt.append([W-P-x, P+y])
dstpt.append([W-P-x, H-P-y])
N = len(dstpt)
matches = [cv2.DMatch(i, i, 0) for i in range(N)]
dst_shape = np.array(dstpt).reshape((-1, N, 2))
src_shape = np.array(srcpt).reshape((-1, N, 2))
self.tps.estimateTransformation(dst_shape, src_shape, matches)
img = self.tps.warpImage(img)
img = Image.fromarray(img)
if np.random.uniform(0, 1) < 0.5:
img = self.translateXAbs(img, val=x)
else:
img = self.translateYAbs(img, val=y)
return img
class Rotate:
def __init__(self, square_side=224):
self.side = square_side
def __call__(self, img, iscurve=False, mag=-1, prob=1.):
if np.random.uniform(0,1) > prob:
return img
W, H = img.size
if H!=self.side or W!=self.side:
img = img.resize((self.side, self.side), Image.BICUBIC)
b = [20., 40, 60]
if mag<0 or mag>=len(b):
index = 1
else:
index = mag
rotate_angle = b[index]
angle = np.random.uniform(rotate_angle-20, rotate_angle)
if np.random.uniform(0, 1) < 0.5:
angle = -angle
#angle = np.random.normal(loc=0., scale=rotate_angle)
#angle = min(angle, 2*rotate_angle)
#angle = max(angle, -2*rotate_angle)
expand = False if iscurve else True
img = img.rotate(angle=angle, resample=Image.BICUBIC, expand=expand)
img = img.resize((W, H), Image.BICUBIC)
return img
class Perspective:
def __init__(self):
pass
def __call__(self, img, mag=-1, prob=1.):
if np.random.uniform(0,1) > prob:
return img
W, H = img.size
# upper-left, upper-right, lower-left, lower-right
src = np.float32([[0, 0], [W, 0], [0, H], [W, H]])
#low = 0.3
b = [.1, .2, .3]
if mag<0 or mag>=len(b):
index = 2
else:
index = mag
low = b[index]
high = 1 - low
if np.random.uniform(0, 1) > 0.5:
toprightY = np.random.uniform(low, low+.1)*H
bottomrightY = np.random.uniform(high-.1, high)*H
dest = np.float32([[0, 0], [W, toprightY], [0, H], [W, bottomrightY]])
else:
topleftY = np.random.uniform(low, low+.1)*H
bottomleftY = np.random.uniform(high-.1, high)*H
dest = np.float32([[0, topleftY], [W, 0], [0, bottomleftY], [W, H]])
M = cv2.getPerspectiveTransform(src, dest)
img = np.array(img)
img = cv2.warpPerspective(img, M, (W, H) )
img = Image.fromarray(img)
return img
class TranslateX:
def __init__(self):
pass
def __call__(self, img, mag=-1, prob=1.):
if np.random.uniform(0,1) > prob:
return img
b = [.03, .06, .09]
if mag<0 or mag>=len(b):
index = 2
else:
index = mag
v = b[index]
v = np.random.uniform(v-0.03, v)
v = v * img.size[0]
if np.random.uniform(0,1) > 0.5:
v = -v
return img.transform(img.size, Image.AFFINE, (1, 0, v, 0, 1, 0))
class TranslateY:
def __init__(self):
pass
def __call__(self, img, mag=-1, prob=1.):
if np.random.uniform(0,1) > prob:
return img
b = [.07, .14, .21]
if mag<0 or mag>=len(b):
index = 2
else:
index = mag
v = b[index]
v = np.random.uniform(v-0.07, v)
v = v * img.size[1]
if np.random.uniform(0,1) > 0.5:
v = -v
return img.transform(img.size, Image.AFFINE, (1, 0, 0, 0, 1, v))
class TranslateXAbs:
def __init__(self):
pass
def __call__(self, img, val=0, prob=1.):
if np.random.uniform(0,1) > prob:
return img
v = np.random.uniform(0, val)
if np.random.uniform(0,1) > 0.5:
v = -v
return img.transform(img.size, Image.AFFINE, (1, 0, v, 0, 1, 0))
class TranslateYAbs:
def __init__(self):
pass
def __call__(self, img, val=0, prob=1.):
if np.random.uniform(0,1) > prob:
return img
v = np.random.uniform(0, val)
if np.random.uniform(0,1) > 0.5:
v = -v
return img.transform(img.size, Image.AFFINE, (1, 0, 0, 0, 1, v))