-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathboundary_modification.py
90 lines (67 loc) · 3.02 KB
/
boundary_modification.py
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
import cv2
import numpy as np
import random
import math
try:
from util.de_transform import perturb_seg
except:
from de_transform import perturb_seg
def modify_boundary(image, regional_sample_rate=0.1, sample_rate=0.1, move_rate=0.0, iou_target = 0.8):
# modifies boundary of the given mask.
# remove consecutive vertice of the boundary by regional sample rate
# ->
# remove any vertice by sample rate
# ->
# move vertice by distance between vertice and center of the mask by move rate.
# input: np array of size [H,W] image
# output: same shape as input
# get boundaries
if int(cv2.__version__[0]) >= 4:
contours, _ = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
else:
_, contours, _ = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
#only modified contours is needed actually.
sampled_contours = []
modified_contours = []
for contour in contours:
if contour.shape[0] < 10:
continue
M = cv2.moments(contour)
#remove region of contour
number_of_vertices = contour.shape[0]
number_of_removes = int(number_of_vertices * regional_sample_rate)
idx_dist = []
for i in range(number_of_vertices-number_of_removes):
idx_dist.append([i, np.sum((contour[i] - contour[i+number_of_removes])**2)])
idx_dist = sorted(idx_dist, key=lambda x:x[1])
remove_start = random.choice(idx_dist[:math.ceil(0.1*len(idx_dist))])[0]
#remove_start = random.randrange(0, number_of_vertices-number_of_removes, 1)
new_contour = np.concatenate([contour[:remove_start], contour[remove_start+number_of_removes:]], axis=0)
contour = new_contour
#sample contours
number_of_vertices = contour.shape[0]
indices = random.sample(range(number_of_vertices), int(number_of_vertices * sample_rate))
indices.sort()
sampled_contour = contour[indices]
sampled_contours.append(sampled_contour)
modified_contour = np.copy(sampled_contour)
if (M['m00'] != 0):
center = round(M['m10'] / M['m00']), round(M['m01'] / M['m00'])
#modify contours
for idx, coor in enumerate(modified_contour):
change = np.random.normal(0,move_rate) # 0.1 means change position of vertex to 10 percent farther from center
x,y = coor[0]
new_x = x + (x-center[0]) * change
new_y = y + (y-center[1]) * change
modified_contour[idx] = [new_x,new_y]
modified_contours.append(modified_contour)
#draw boundary
gt = np.copy(image)
image = np.zeros_like(image)
modified_contours = [cont for cont in modified_contours if len(cont) > 0]
if len(modified_contours) == 0:
image = gt.copy()
else:
image = cv2.drawContours(image, modified_contours, -1, (255, 0, 0), -1)
image = perturb_seg(image, iou_target)
return image