[8eeb5a]: / utils / mask_generator.py

Download this file

123 lines (98 with data), 4.0 kB

  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
from random import randint
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import binom
bernstein = lambda n, k, t: binom(n, k) * t ** k * (1. - t) ** (n - k)
def bezier(points, num=200):
N = len(points)
t = np.linspace(0, 1, num=num)
curve = np.zeros((num, 2))
for i in range(N):
curve += np.outer(bernstein(N - 1, i, t), points[i])
return curve
class Segment():
def __init__(self, p1, p2, angle1, angle2, **kw):
self.p1 = p1;
self.p2 = p2
self.angle1 = angle1;
self.angle2 = angle2
self.numpoints = kw.get("numpoints", 100)
r = kw.get("r", 0.3)
d = np.sqrt(np.sum((self.p2 - self.p1) ** 2))
self.r = r * d
self.p = np.zeros((4, 2))
self.p[0, :] = self.p1[:]
self.p[3, :] = self.p2[:]
self.calc_intermediate_points(self.r)
def calc_intermediate_points(self, r):
self.p[1, :] = self.p1 + np.array([self.r * np.cos(self.angle1),
self.r * np.sin(self.angle1)])
self.p[2, :] = self.p2 + np.array([self.r * np.cos(self.angle2 + np.pi),
self.r * np.sin(self.angle2 + np.pi)])
self.curve = bezier(self.p, self.numpoints)
def get_curve(points, **kw):
segments = []
for i in range(len(points) - 1):
seg = Segment(points[i, :2], points[i + 1, :2], points[i, 2], points[i + 1, 2], **kw)
segments.append(seg)
curve = np.concatenate([s.curve for s in segments])
return segments, curve
def ccw_sort(p):
d = p - np.mean(p, axis=0)
s = np.arctan2(d[:, 0], d[:, 1])
return p[np.argsort(s), :]
def get_bezier_curve(a, rad=0.2, edgy=0):
""" given an array of points *a*, create a curve through
those points.
*rad* is a number between 0 and 1 to steer the distance of
control points.
*edgy* is a parameter which controls how "edgy" the curve is,
edgy=0 is smoothest."""
p = np.arctan(edgy) / np.pi + .5
a = ccw_sort(a)
a = np.append(a, np.atleast_2d(a[0, :]), axis=0)
d = np.diff(a, axis=0)
ang = np.arctan2(d[:, 1], d[:, 0])
f = lambda ang: (ang >= 0) * ang + (ang < 0) * (ang + 2 * np.pi)
ang = f(ang)
ang1 = ang
ang2 = np.roll(ang, 1)
ang = p * ang1 + (1 - p) * ang2 + (np.abs(ang2 - ang1) > np.pi) * np.pi
ang = np.append(ang, [ang[0]])
a = np.append(a, np.atleast_2d(ang).T, axis=1)
s, c = get_curve(a, r=rad, method="var")
x, y = c.T
return x, y, a
def get_random_points(n=5, scale=0.8, mindst=None, rec=0):
""" create n random points in the unit square, which are *mindst*
apart, then scale them."""
mindst = mindst or .7 / n
a = np.random.rand(n, 2)
d = np.sqrt(np.sum(np.diff(ccw_sort(a), axis=0), axis=1) ** 2)
if np.all(d >= mindst) or rec >= 200:
return a * scale
else:
return get_random_points(n=n, scale=scale, mindst=mindst, rec=rec + 1)
# =======================================
# developer: Vajria
# =======================================
def generate_a_mask(rad=0.25, edgy=0.05, imsize=512, location=None, scale=None):
# for c in np.array([[0,0], [0,1], [1,0], [1,1]]):
if location is None:
location = [randint(0, np.floor(imsize / 1.5)),
randint(0, np.floor(imsize / 1.5))] # location region to generate a mask
else:
location = location
a = get_random_points(n=5, scale=128) + location
x, y, _ = get_bezier_curve(a, rad=rad, edgy=edgy)
c = np.vstack((x, y)).T # make a (x, y) coordinate paires
c = c.astype(int) # covert into integer
img = np.zeros((imsize, imsize, 3), np.uint8) # make a image
pts = c.reshape((-1, 1, 2))
img = cv.fillPoly(img, [pts], (255, 255, 255)) # (255,255, 255) = color (White)
return img[:, :, 0] / 255
if __name__ == '__main__':
mask = generate_a_mask()
plt.imshow(mask)
plt.show()