|
import random |
|
import numpy as np |
|
import cv2 |
|
|
|
def random_bbox(img_height, img_width, vertical_margin, horizontal_margin, mask_height, mask_width): |
|
maxt = img_height - vertical_margin - mask_height |
|
maxl = img_width - horizontal_margin - mask_width |
|
|
|
t = random.randint(vertical_margin, maxt) |
|
l = random.randint(horizontal_margin, maxl) |
|
h = random.randint(mask_height // 2, mask_height) |
|
w = random.randint(mask_width // 2, mask_width) |
|
return (t, l, h, w) |
|
|
|
|
|
def mid_bbox_mask(img_height, img_width, mask_height, mask_width): |
|
def npmask(bbox, height, width): |
|
mask = np.zeros((height, width, 1), np.float32) |
|
mask[bbox[0]: bbox[0] + bbox[2], bbox[1]: bbox[1] + bbox[3], :] = 255. |
|
return mask |
|
|
|
bbox = (img_height * 3 // 8, img_width * 3 // 8, mask_height, mask_width) |
|
mask = npmask(bbox, img_height, img_width) |
|
|
|
return mask |
|
|
|
|
|
def bbox2mask(img_height, img_width, max_delta_height, max_delta_width, bbox): |
|
"""Generate mask tensor from bbox. |
|
|
|
Args: |
|
bbox: configuration tuple, (top, left, height, width) |
|
config: Config should have configuration including IMG_SHAPES, |
|
MAX_DELTA_HEIGHT, MAX_DELTA_WIDTH. |
|
|
|
Returns: |
|
tf.Tensor: output with shape [B, 1, H, W] |
|
|
|
""" |
|
|
|
def npmask(bbox, height, width, delta_h, delta_w): |
|
mask = np.zeros((height, width, 1), np.float32) |
|
h = np.random.randint(delta_h // 2 + 1) |
|
w = np.random.randint(delta_w // 2 + 1) |
|
mask[bbox[0] + h: bbox[0] + bbox[2] - h, bbox[1] + w: bbox[1] + bbox[3] - w, :] = 255. |
|
return mask |
|
|
|
mask = npmask(bbox, img_height, img_width, |
|
max_delta_height, |
|
max_delta_width) |
|
|
|
return mask |
|
|
|
|
|
def matrix2bbox(img_height, img_width, mask_height, mask_width, row, column): |
|
"""Generate masks with a matrix form |
|
@param img_height |
|
@param img_width |
|
@param mask_height |
|
@param mask_width |
|
@param row: number of blocks in row |
|
@param column: number of blocks in column |
|
@return mbbox: multiple bboxes in (y, h, h, w) manner |
|
""" |
|
assert img_height - column * mask_height > img_height // 2, "Too many masks across a column" |
|
assert img_width - row * mask_width > img_width // 2, "Too many masks across a row" |
|
|
|
interval_height = (img_height - column * mask_height) // (column + 1) |
|
interval_width = (img_width - row * mask_width) // (row + 1) |
|
|
|
mbbox = [] |
|
for i in range(row): |
|
for j in range(column): |
|
y = interval_height * (j+1) + j * mask_height |
|
x = interval_width * (i+1) + i * mask_width |
|
mbbox.append((y, x, mask_height, mask_width)) |
|
return mbbox |
|
|
|
|
|
def mbbox2masks(img_height, img_width, mbbox): |
|
|
|
def npmask(mbbox, height, width): |
|
mask = np.zeros((height, width, 1), np.float32) |
|
for bbox in mbbox: |
|
mask[bbox[0]: bbox[0] + bbox[2], bbox[1]: bbox[1] + bbox[3], :] = 255. |
|
return mask |
|
|
|
mask = npmask(mbbox, img_height, img_width) |
|
|
|
return mask |
|
|
|
|
|
def draw_line(mask, startX, startY, angle, length, brushWidth): |
|
"""assume the size of mask is (H,W,1) |
|
""" |
|
assert len(mask.shape) == 2 or mask.shape[2] == 1, "The channel of mask doesn't fit the opencv format" |
|
offsetX = int(np.round(length * np.cos(angle))) |
|
offsetY = int(np.round(length * np.sin(angle))) |
|
endX = startX + offsetX |
|
endY = startY + offsetY |
|
if endX > mask.shape[1]: |
|
endX = mask.shape[1] |
|
if endY > mask.shape[0]: |
|
endY = mask.shape[0] |
|
mask_processed = cv2.line(mask, (startX, startY), (endX, endY), 255, brushWidth) |
|
return mask_processed, endX, endY |
|
|
|
|
|
def draw_circle(mask, circle_x, circle_y, brushWidth): |
|
radius = brushWidth // 2 |
|
assert len(mask.shape) == 2 or mask.shape[2] == 1, "The channel of mask doesn't fit the opencv format" |
|
mask_processed = cv2.circle(mask, (circle_x, circle_y), radius, 255) |
|
return mask_processed |
|
|
|
|
|
def freeFormMask(img_height, img_width, maxVertex, maxLength, maxBrushWidth, maxAngle): |
|
mask = np.zeros((img_height, img_width)) |
|
numVertex = random.randint(1, maxVertex) |
|
startX = random.randint(10, img_width) |
|
startY = random.randint(10, img_height) |
|
brushWidth = random.randint(10, maxBrushWidth) |
|
for i in range(numVertex): |
|
angle = random.uniform(0, maxAngle) |
|
if i % 2 == 0: |
|
angle = 2 * np.pi - angle |
|
length = random.randint(10, maxLength) |
|
mask, endX, endY = draw_line(mask, startX, startY, angle, length, brushWidth) |
|
startX = startX + int(length * np.sin(angle)) |
|
startY = startY + int(length * np.cos(angle)) |
|
mask = draw_circle(mask, endX, endY, brushWidth) |
|
|
|
if random.random() < 0.5: |
|
mask = np.fliplr(mask) |
|
if random.random() < 0.5: |
|
mask = np.flipud(mask) |
|
|
|
if len(mask.shape) == 2: |
|
mask = mask[:, :, np.newaxis] |
|
|
|
return mask |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pass |
|
|
|
|
|
|