Skip to content
This repository has been archived by the owner on Jul 2, 2021. It is now read-only.

add scale_mask #799

Merged
merged 1 commit into from
Feb 20, 2019
Merged

add scale_mask #799

merged 1 commit into from
Feb 20, 2019

Conversation

yuyu2172
Copy link
Member

@yuyu2172 yuyu2172 commented Feb 19, 2019

What this is

This code exploits sparsity of mask used for instance segmentation to speed up scale operation.
When scaling factor is an integer, there is no difference between resize.
When scaling factor is not an integer, there is one pixel error in horizontal or vertical direction.

Benchmark

The script below benchmarks performance in comparison to the normal resize.
The comparison is made by varying the number of instances in an image.
figure_1-11
The figure shows the execution time in seconds.
Blue is the time taken by resize and orange is the execution time of scale_mask.

from chainercv.datasets import COCOInstanceSegmentationDataset
from chainercv import transforms
import PIL.Image
import numpy as np
import time
from chainercv.utils import mask_to_bbox
import matplotlib.pyplot as plt

from chainercv.utils import scale_mask


def old(mask, scale):
    _, H, W = mask.shape
    return transforms.resize(
        mask.astype(np.float32),
        (int(scale * H), int(scale * W)),
        interpolation=PIL.Image.NEAREST).astype(np.bool)


def measure_speed(func, args, n_call=20):
    exec_times = []
    for _ in range(n_call):
        start = time.time()
        func(*args)
        exec_times.append(time.time() - start)
    exec_times = np.sort(exec_times)
    return np.mean(exec_times[n_call // 10:-n_call // 10])


dataset = COCOInstanceSegmentationDataset(split='val', return_bbox=True)


count_to_id = {i: [] for i in range(100)}
for i in range(len(dataset)):
    label, = dataset.slice[:, ['label']][i]
    count_to_id[len(label)].append(i)

n = 40
old_times = np.zeros((n,))
new_times = np.zeros((n,))
for n_inst in range(1, n):
    if len(count_to_id[n_inst]) == 0:
        continue
    idx = count_to_id[n_inst][0]
    img = dataset[idx][0]
    mask = dataset[idx][1]
    bbox = mask_to_bbox(mask)
    assert len(bbox) == n_inst

    scale = 2
    H, W = mask.shape[1:]
    size = min(H, W) * scale

    old_times[n_inst] = measure_speed(old, (mask, scale))
    new_times[n_inst] = measure_speed(scale_mask, (mask, bbox, size))

    old_mask = old(mask, scale)
    fast_mask = scale_mask(mask, bbox, size)
    np.testing.assert_equal(fast_mask, old_mask)
    print('n_instance: {} old: {}  new: {}'.format(
        n_inst, old_times[n_inst], new_times[n_inst]))
plt.plot(old_times)
plt.plot(new_times)
plt.show()

@yuyu2172 yuyu2172 changed the title add scale_mask [WIP] add scale_mask Feb 19, 2019
@yuyu2172 yuyu2172 changed the title [WIP] add scale_mask add scale_mask Feb 19, 2019
@knorth55 knorth55 added this to the 0.13 milestone Feb 19, 2019
@yuyu2172 yuyu2172 merged commit 3f2a580 into chainer:master Feb 20, 2019
@yuyu2172 yuyu2172 deleted the scale-mask branch February 20, 2019 06:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants