|
|
import cv2 |
|
|
|
|
|
import numpy as np |
|
|
|
|
|
def get_random_structure(size): |
|
|
|
|
|
|
|
|
|
|
|
choice = np.random.randint(1, 5) |
|
|
|
|
|
if choice == 1: |
|
|
return cv2.getStructuringElement(cv2.MORPH_RECT, (size, size)) |
|
|
elif choice == 2: |
|
|
return cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (size, size)) |
|
|
elif choice == 3: |
|
|
return cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (size, size//2)) |
|
|
elif choice == 4: |
|
|
return cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (size//2, size)) |
|
|
|
|
|
def random_dilate(seg, min=3, max=10): |
|
|
size = np.random.randint(min, max) |
|
|
kernel = get_random_structure(size) |
|
|
seg = cv2.dilate(seg,kernel,iterations = 1) |
|
|
return seg |
|
|
|
|
|
def random_erode(seg, min=3, max=10): |
|
|
size = np.random.randint(min, max) |
|
|
kernel = get_random_structure(size) |
|
|
seg = cv2.erode(seg,kernel,iterations = 1) |
|
|
return seg |
|
|
|
|
|
def compute_iou(seg, gt): |
|
|
intersection = seg*gt |
|
|
union = seg+gt |
|
|
return (np.count_nonzero(intersection) + 1e-6) / (np.count_nonzero(union) + 1e-6) |
|
|
|
|
|
def perturb_seg(gt, iou_target=0.6): |
|
|
h, w = gt.shape |
|
|
seg = gt.copy() |
|
|
|
|
|
_, seg = cv2.threshold(seg, 127, 255, 0) |
|
|
|
|
|
|
|
|
if h <= 2 or w <= 2: |
|
|
print('GT too small, returning original') |
|
|
return seg |
|
|
|
|
|
|
|
|
for _ in range(250): |
|
|
for _ in range(4): |
|
|
lx, ly = np.random.randint(w), np.random.randint(h) |
|
|
lw, lh = np.random.randint(lx+1,w+1), np.random.randint(ly+1,h+1) |
|
|
|
|
|
|
|
|
if np.random.rand() < 0.25: |
|
|
cx = int((lx + lw) / 2) |
|
|
cy = int((ly + lh) / 2) |
|
|
seg[cy, cx] = np.random.randint(2) * 255 |
|
|
|
|
|
if np.random.rand() < 0.5: |
|
|
seg[ly:lh, lx:lw] = random_dilate(seg[ly:lh, lx:lw]) |
|
|
else: |
|
|
seg[ly:lh, lx:lw] = random_erode(seg[ly:lh, lx:lw]) |
|
|
|
|
|
if compute_iou(seg, gt) < iou_target: |
|
|
break |
|
|
|
|
|
return seg |
|
|
|