示例#1
0
def _devcheck_sample_full_image():
    """
    """
    import kwimage
    import numpy as np

    sampler = grab_camvid_sampler()

    cid_to_cidx = sampler.catgraph.id_to_idx
    classes = sampler.catgraph

    # Try loading an entire image
    img, annots = sampler.load_image_with_annots(1)

    file = img['imdata']
    imdata = file[:]

    aids = [ann['id'] for ann in annots]
    _annots = sampler.dset.annots(aids)

    sseg_list = []
    for s in _annots.lookup('segmentation'):
        m = kwimage.MultiPolygon.coerce(s)
        sseg_list.append(m)

    aids = _annots.aids
    cids = _annots.cids
    boxes = _annots.boxes
    segmentations = kwimage.PolygonList(sseg_list)
    class_idxs = np.array([cid_to_cidx[cid] for cid in cids])

    dets = kwimage.Detections(
        aids=aids,
        boxes=boxes,
        class_idxs=class_idxs,
        segmentations=segmentations,
        classes=classes,
        datakeys=['aids'],
    )

    if 1:
        print('dets = {!r}'.format(dets))
        print('dets.data = {!r}'.format(dets.data))
        print('dets.meta = {!r}'.format(dets.meta))

    if ub.argflag('--show'):
        import kwplot

        with ub.Timer('dets.draw_on'):
            canvas = imdata.copy()
            canvas = dets.draw_on(canvas)
            kwplot.imshow(canvas, pnum=(1, 2, 1), title='dets.draw_on')

        with ub.Timer('dets.draw'):
            kwplot.imshow(imdata,
                          pnum=(1, 2, 2),
                          docla=True,
                          title='dets.draw')
            dets.draw()
示例#2
0
def fastfill_multipolygon():
    kwplot.autompl()
    shape = (1208, 1208)
    self = kwimage.MultiPolygon.random(10).scale(shape)

    ti = ub.Timerit(3, bestof=1, verbose=2, unit='us')
    for timer in ti.reset('draw_on'):
        with timer:
            mask = np.zeros(shape, dtype=np.uint8)
            mask = self.draw_on(mask)

    for timer in ti.reset('custom'):
        with timer:
            mask = np.zeros(shape, dtype=np.uint8)
            for p in self.data:
                if p is not None:
                    p.fill(mask, value=255)

    for timer in ti.reset('to_mask'):
        with timer:
            self.to_mask(shape)

    kwplot.imshow(mask)
示例#3
0
fpath = ub.grabdata('https://i.redd.it/ywip9sbwysy71.jpg')
data = kwimage.imread(fpath)

subdata = data[242:-22, 22:300]

img = subdata

inty = integrate.cumtrapz(img, axis=0)
intx = integrate.cumtrapz(img, axis=1)

dery = np.gradient(img, axis=0)
derx = np.gradient(img, axis=1)

der_canvas = kwarray.normalize(kwimage.stack_images([dery, derx], axis=0))
int_canvas = kwarray.normalize(kwimage.stack_images([inty, intx], axis=0))
der_canvas = kwimage.ensure_uint255(der_canvas)
int_canvas = kwimage.ensure_uint255(int_canvas)

der_canvas = kwimage.draw_header_text(der_canvas, 'derivative', color='white')
int_canvas = kwimage.draw_header_text(int_canvas,
                                      'antiderivative',
                                      color='white')

canvas = kwimage.stack_images([der_canvas, int_canvas], axis=1)

# kwimage.imwrite('ftfy.jpg', canvas)

kwplot.autompl()
kwplot.imshow(canvas)
示例#4
0
def _devcheck_load_sub_image():
    import kwimage
    import numpy as np

    sampler = grab_camvid_sampler()

    cid_to_cidx = sampler.catgraph.id_to_idx
    classes = sampler.catgraph

    # Try loading a subregion of an image
    sample = sampler.load_positive(2)
    imdata = sample['im']
    annots = sample['annots']
    aids = annots['aids']
    cids = annots['cids']
    boxes = annots['rel_boxes']
    class_idxs = np.array([cid_to_cidx[cid] for cid in cids])
    segmentations = annots['rel_ssegs']

    raw_dets = kwimage.Detections(
        aids=aids,
        boxes=boxes,
        class_idxs=class_idxs,
        segmentations=segmentations,
        classes=classes,
        datakeys=['aids'],
    )

    # Clip boxes to the image boundary
    input_dims = imdata.shape[0:2]
    raw_dets.data['boxes'] = raw_dets.boxes.clip(0, 0, input_dims[1],
                                                 input_dims[0])

    keep = []
    for i, s in enumerate(raw_dets.data['segmentations']):
        # TODO: clip polygons
        m = s.to_mask(input_dims)
        if m.area > 0:
            keep.append(i)
    dets = raw_dets.take(keep)

    heatmap = dets.rasterize(bg_size=(1, 1), input_dims=input_dims)

    if 1:
        print('dets = {!r}'.format(dets))
        print('dets.data = {!r}'.format(dets.data))
        print('dets.meta = {!r}'.format(dets.meta))

    if ub.argflag('--show'):
        import kwplot

        kwplot.autompl()
        heatmap.draw()

        draw_boxes = 1

        kwplot.figure(doclf=True)
        with ub.Timer('dets.draw_on'):
            canvas = imdata.copy()
            # TODO: add logic to color by class
            canvas = dets.draw_on(canvas, boxes=draw_boxes, color='random')
            kwplot.imshow(canvas, pnum=(1, 2, 1), title='dets.draw_on')

        with ub.Timer('dets.draw'):
            kwplot.imshow(imdata,
                          pnum=(1, 2, 2),
                          docla=True,
                          title='dets.draw')
            dets.draw(boxes=draw_boxes, color='random')
示例#5
0
def convert_camvid_raw_to_coco(camvid_raw_info):
    """
    Converts the raw camvid format to an MSCOCO based format, ( which lets use
    use kwcoco's COCO backend).

    Example:
        >>> # xdoctest: +REQUIRES(--download)
        >>> camvid_raw_info = grab_raw_camvid()
        >>> # test with a reduced set of data
        >>> del camvid_raw_info['img_paths'][2:]
        >>> del camvid_raw_info['mask_paths'][2:]
        >>> dset = convert_camvid_raw_to_coco(camvid_raw_info)
        >>> # xdoctest: +REQUIRES(--show)
        >>> import kwplot
        >>> plt = kwplot.autoplt()
        >>> kwplot.figure(fnum=1, pnum=(1, 2, 1))
        >>> dset.show_image(gid=1)
        >>> kwplot.figure(fnum=1, pnum=(1, 2, 2))
        >>> dset.show_image(gid=2)
    """
    import re
    import kwimage
    import kwcoco
    print('Converting CamVid to MS-COCO format')

    dset_root, img_paths, label_path, mask_paths = ub.take(
        camvid_raw_info,
        'dset_root, img_paths, label_path, mask_paths'.split(', '))

    img_infos = {
        'img_fname': img_paths,
        'mask_fname': mask_paths,
    }
    keys = list(img_infos.keys())
    next_vals = list(zip(*img_infos.values()))
    image_items = [{k: v for k, v in zip(keys, vals)} for vals in next_vals]

    dataset = {
        'img_root': dset_root,
        'images': [],
        'categories': [],
        'annotations': [],
    }

    lines = ub.readfrom(label_path).split('\n')
    lines = [line for line in lines if line]
    for line in lines:
        color_text, name = re.split('\t+', line)
        r, g, b = map(int, color_text.split(' '))
        color = (r, g, b)

        # Parse the special camvid format
        cid = (r << 16) + (g << 8) + (b << 0)
        cat = {
            'id': cid,
            'name': name,
            'color': color,
        }
        dataset['categories'].append(cat)

    for gid, img_item in enumerate(image_items, start=1):
        img = {
            'id': gid,
            'file_name': img_item['img_fname'],
            # nonstandard image field
            'segmentation': img_item['mask_fname'],
        }
        dataset['images'].append(img)

    dset = kwcoco.CocoDataset(dataset)
    dset.rename_categories({'Void': 'background'})

    assert dset.name_to_cat['background']['id'] == 0
    dset.name_to_cat['background'].setdefault('alias', []).append('Void')

    if False:
        _define_camvid_class_hierarcy(dset)

    if 1:
        # TODO: Binarize CCs (and efficiently encode if possible)
        import numpy as np

        bad_info = []
        once = False

        # Add images
        dset.remove_annotations(list(dset.index.anns.keys()))
        for gid, img in ub.ProgIter(dset.imgs.items(),
                                    desc='parse label masks'):
            mask_fpath = join(dset_root, img['segmentation'])

            rgb_mask = kwimage.imread(mask_fpath, space='rgb')
            r, g, b = rgb_mask.T.astype(np.int64)
            cid_mask = np.ascontiguousarray(rgb_to_cid(r, g, b).T)

            cids = set(np.unique(cid_mask)) - {0}

            for cid in cids:
                if cid not in dset.cats:
                    if gid == 618:
                        # Handle a known issue with image 618
                        c_mask = (cid == cid_mask).astype(np.uint8)
                        total_bad = c_mask.sum()
                        if total_bad < 32:
                            if not once:
                                print(
                                    'gid 618 has a few known bad pixels, ignoring them'
                                )
                                once = True
                            continue
                        else:
                            raise Exception('more bad pixels than expected')
                    else:
                        raise Exception(
                            'UNKNOWN cid = {!r} in gid={!r}'.format(cid, gid))

                    # bad_rgb = cid_to_rgb(cid)
                    # print('bad_rgb = {!r}'.format(bad_rgb))
                    # print('WARNING UNKNOWN cid = {!r} in gid={!r}'.format(cid, gid))
                    # bad_info.append({
                    #     'gid': gid,
                    #     'cid': cid,
                    # })
                else:
                    ann = {
                        'category_id': cid,
                        'image_id': gid
                        # 'segmentation': mask.to_coco()
                    }
                    assert cid in dset.cats
                    c_mask = (cid == cid_mask).astype(np.uint8)
                    mask = kwimage.Mask(c_mask, 'c_mask')

                    box = kwimage.Boxes([mask.get_xywh()], 'xywh')
                    # box = mask.to_boxes()

                    ann['bbox'] = ub.peek(box.to_coco())
                    ann['segmentation'] = mask.to_coco()
                    dset.add_annotation(**ann)

        if 0:
            bad_cids = [i['cid'] for i in bad_info]
            print(sorted([c['color'] for c in dataset['categories']]))
            print(sorted(set([cid_to_rgb(i['cid']) for i in bad_info])))

            gid = 618
            img = dset.imgs[gid]
            mask_fpath = join(dset_root, img['segmentation'])
            rgb_mask = kwimage.imread(mask_fpath, space='rgb')
            r, g, b = rgb_mask.T.astype(np.int64)
            cid_mask = np.ascontiguousarray(rgb_to_cid(r, g, b).T)
            cid_hist = ub.dict_hist(cid_mask.ravel())

            bad_cid_hist = {}
            for cid in bad_cids:
                bad_cid_hist[cid] = cid_hist.pop(cid)

            import kwplot
            kwplot.autompl()
            kwplot.imshow(rgb_mask)

    if 0:
        import kwplot
        plt = kwplot.autoplt()
        plt.clf()
        dset.show_image(1)

        import xdev
        gid_list = list(dset.imgs)
        for gid in xdev.InteractiveIter(gid_list):
            dset.show_image(gid)
            xdev.InteractiveIter.draw()

    dset._build_index()
    dset._build_hashid()
    return dset
示例#6
0
def demo_flip_orientations():
    import ubelt as ub
    from kwcoco.demo.toypatterns import Rasters
    img = Rasters.eff()[0]

    import kwplot
    kwplot.autompl()
    kwplot.imshow(img)

    flips = [
        [],
        [0],
        [1],
        [0, 1],
    ]
    import numpy as np

    toshow = []

    for axis in flips:
        img_ = img
        img_ = np.flip(img_, axis=axis)
        for k in [0, 1, 2, 3]:
            img_ = np.rot90(img_, k=k)
            row = {'img': img_, 'label': f'rot(flip({axis}), k={k})'}
            row['params'] = [f'axis={axis}, k={k}']
            toshow.append(row)

    # for k in [0, 1, 2, 3]:
    #     img_ = img
    #     img_ = np.rot90(img_, k=k)
    #     for axis in flips:
    #         img_ = np.flip(img_, axis=axis)
    #         row = {'img': img_, 'label': f'flip(rot(k={k}), {axis})'}
    #         row['params'] = [f'k={k}, axis={axis}']
    #         toshow.append(row)

    for row in toshow:
        row['hash'] = ub.hash_data(row['img'])

    pnum_ = kwplot.PlotNums(nSubplots=len(toshow))
    groups = ub.group_items(toshow, lambda x: x['hash'])
    # Only 8 possibiliteis
    for k, group in groups.items():
        print('\n\nk = {!r}'.format(k))
        for g in group:
            print(g['params'])
            row = g
            kwplot.imshow(row['img'], pnum=pnum_(), fnum=1, title=row['label'])

    unique_fliprots = [
        {
            'k': 0,
            'axis': []
        },
        {
            'k': 1,
            'axis': []
        },
        {
            'k': 2,
            'axis': []
        },
        {
            'k': 3,
            'axis': []
        },
        {
            'k': 0,
            'axis': [0]
        },
        {
            'k': 1,
            'axis': [0]
        },
        {
            'k': 2,
            'axis': [0]
        },
        {
            'k': 3,
            'axis': [0]
        },
    ]
    s = []
    for params in unique_fliprots:
        k = params['k']
        axis = params['axis']
        img_ = np.rot90(np.flip(img, axis=axis), k=k)
        s.append(ub.hash_data(img_))

    assert len(set(s)) == len(s)
示例#7
0
    imdata = np.asarray(pil_img)
    return imdata


# This circuit creates the "Bell State"
# which maximally entangles two input qubits.
num_qubits = 2
bell_circuit = qutip.QubitCircuit(num_qubits,
                                  input_states=["e1", "e2", "c1", "c2"],
                                  num_cbits=2)
bell_circuit.add_gate("SNOT", targets=0)  # snot is Hadamard
bell_circuit.add_gate("CNOT", controls=[0], targets=[1])
bell_circuit.add_measurement("M0", targets=[0], classical_store=0)
bell_circuit.add_measurement("M1", targets=[1], classical_store=1)

kwplot.imshow(draw_circuit(bell_circuit))

# qutip.qubit_states()

# Create a system of two electrons
e1 = qutip.basis(dimensions=2, n=0)
e2 = qutip.basis(dimensions=2, n=1)
# This state represents two electrons
input_state = qutip.tensor(e1, e2)

# We can measure, these. It wont matter because we are going to make the
# bell State
initial_measurement = qutip.Measurement("start", targets=[0])
collapsed1, probs1 = initial_measurement.measurement_comp_basis(e1)
collapsed2, probs2 = initial_measurement.measurement_comp_basis(e2)
collapsed3, probs3 = initial_measurement.measurement_comp_basis(input_state)
示例#8
0
import kwplot
import numpy as np
import kwimage
kwplot.autompl()

f = 8
blank_key = np.zeros((64 * f, 54 * f, 3))
blank_key[:, :, :] = np.array(kwimage.Color('darkgray').as255())[None, None, :]
blank_key[0:f * 2, :] = (3, 3, 3)
blank_key[-f * 2:, :] = (3, 3, 3)
blank_key[:, 0:f * 2] = (3, 3, 3)
blank_key[:, -f * 2:] = (3, 3, 3)

key = kwimage.draw_text_on_image(blank_key.copy(), text='!\n1', halign='center', valign='center', color='white')

kwplot.imshow(key)

tab_symbol = '->'


left_rows = []

alt_text0 = [None, None, None, None, None, None, None, None]
row_text0 = ['esc', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'caps']
left_rows += [(alt_text0, row_text0)]

alt_text1 = [None, '~', '!', '@', '#', '$', '%', None]
row_text1 = ['tab', '`', '1', '2', '3', '4', '5', 'win']
left_rows += [(alt_text1, row_text1)]

alt_text2 = ['|', '?',  None, None, None, None, None, None]
示例#9
0
def check_fill_poly_properties():
    """
    Notes:
        It seems as if cv2.fillPoly will draw multiple polygons, but it will
        toggle between drawing holes and filling depending on if the next
        polygon is inside of a previous one.

        skimage.draw.polygon is very slow

        PIL is very slow for floats, but ints aren't too bad. cv2 is better.

    """
    kwplot.autompl()

    shape = (1208, 1208)
    self = kwimage.Polygon.random(n=10, n_holes=1, convex=False).scale(1208)

    cv_contours = self._to_cv_countours()

    value = 1

    mask = np.zeros((128, 128), dtype=np.uint8)
    value = 1
    line_type = cv2.LINE_8

    mask = np.zeros((128, 128), dtype=np.uint8)
    # Modification happens inplace
    cv2.fillPoly(mask, cv_contours, value, line_type, shift=0)

    kwplot.autompl()
    kwplot.imshow(mask)

    extra = cv_contours[1] + 40
    cv_contours3 = cv_contours + [extra, extra + 2]
    mask = np.zeros((128, 128), dtype=np.uint8)
    cv2.fillPoly(mask, cv_contours3, value, line_type, shift=0)

    kwplot.imshow(mask)

    geom = shapely.geometry.Polygon(
        shell=self.data['exterior'].data,
        holes=[c.data for c in self.data['interiors']])

    xs, ys = self.data['exterior'].data.T
    rr, cc = skimage.draw.polygon(xs, ys)

    mask = np.zeros(shape, dtype=np.uint8)

    ti = ub.Timerit(10, bestof=3, verbose=2, unit='us')
    if False:
        # Not general enough
        for timer in ti.reset('fillConvexPoly'):
            mask[:, :] = 0
            with timer:
                cv_contours = self._to_cv_countours()
                cv2.fillConvexPoly(mask, cv_contours[0], value)

    for timer in ti.reset('fillPoly'):
        mask[:, :] = 0
        with timer:
            cv_contours = self._to_cv_countours()
            cv2.fillPoly(mask, cv_contours[0:1], value)

    for timer in ti.reset('skimage.draw.polygon'):
        mask = np.zeros(shape, dtype=np.uint8)
        with timer:
            xs, ys = self.data['exterior'].data.T
            rr, cc = skimage.draw.polygon(xs, ys)

    from PIL import Image, ImageDraw
    for timer in ti.reset('PIL'):
        height, width = shape
        pil_img = Image.new('L', (width, height), 0)
        with timer:
            draw_obj = ImageDraw.Draw(pil_img)
            pil_poly = self.data['exterior'].data.astype(
                np.int).ravel().tolist()
            pil_poly = pil_poly + pil_poly[0:2]
            draw_obj.polygon(pil_poly, outline=0, fill=255)
            mask = np.array(pil_img)
示例#10
0
    def main(cls, cmdline=True, **kw):
        """
        TODO:
            - [ ] Visualize auxiliary data

        Example:
            >>> # xdoctest: +SKIP
            >>> kw = {'src': 'special:shapes8'}
            >>> cmdline = False
            >>> cls = CocoShowCLI
            >>> cls.main(cmdline, **kw)
        """
        import kwcoco
        import kwimage
        import kwplot

        config = cls.CLIConfig(kw, cmdline=cmdline)
        print('config = {}'.format(ub.repr2(dict(config), nl=1)))

        if config['src'] is None:
            raise Exception('must specify source: {}'.format(config['src']))

        dset = kwcoco.CocoDataset.coerce(config['src'])
        print('dset.fpath = {!r}'.format(dset.fpath))

        plt = kwplot.autoplt()

        gid = config['gid']
        aid = config['aid']

        out_fpath = config['dst']

        if gid is None and aid is None:
            gid = ub.peek(dset.imgs)

        if config['mode'] == 'matplotlib':
            show_kw = {
                'show_annots': config['show_annots'],
                'channels': config['channels'],
            }
            if config['show_annots'] == 'both':
                show_kw.pop('show_annots')
                show_kw['title'] = ''
                ax = dset.show_image(gid=gid,
                                     aid=aid,
                                     pnum=(1, 2, 1),
                                     show_annots=False,
                                     **show_kw)
                ax = dset.show_image(gid=gid,
                                     aid=aid,
                                     pnum=(1, 2, 2),
                                     show_annots=True,
                                     **show_kw)
            else:
                ax = dset.show_image(gid=gid, aid=aid, **show_kw)
            if out_fpath is None:

                if 1:
                    try:
                        import xdev
                    except Exception:
                        pass
                    else:
                        gids = [gid] + list(set(dset.imgs.keys()) - {gid})
                        for gid in xdev.InteractiveIter(gids):
                            ax = dset.show_image(gid=gid, aid=aid, **show_kw)
                            xdev.InteractiveIter.draw()
                            plt.show(block=False)
                plt.show()
            else:
                ax.figure.savefig(out_fpath)
        elif config['mode'] == 'opencv':
            canvas = dset.draw_image(gid, channels=config['channels'])
            if out_fpath is None:
                kwplot.imshow(canvas)
                plt.show()
            else:
                kwimage.imwrite(out_fpath, canvas)

        else:
            raise KeyError(config['mode'])
示例#11
0
def plot_convolutional_features(conv,
                                limit=144,
                                colorspace='rgb',
                                fnum=None,
                                nCols=None,
                                voxels=False,
                                alpha=.2,
                                labels=False,
                                normaxis=None,
                                _hack_2drows=False):
    """Plots the convolutional layers to a matplotlib pyplot.

    The convolutional filters (kernels) are stored into a grid and saved to disk
    as a Maplotlib figure.  The convolutional filters, if it has one channel,
    will be stored as an intensity imgage.  If a colorspace is specified and
    there are three input channels, the convolutional filters will be
    represented as an RGB image.

    In the event that 2 or 4+ filters are
    displayed, the different channels will be flattened and showed as distinct
    outputs in the grid.

    TODO:
        - [ ] refactor to use make_conv_images

    Args:
        conv (torch.nn.ConvNd): torch convolutional layer with weights to draw
        limit (int, optional): the limit on the number of filters drawn in the
            figure, achieved by simply dropping any filters past the limit
            starting at the first filter.  Detaults to 144.

        colorspace (str): the colorspace seen by the convolutional filter
            (if applicable), so we can convert to rgb for display.

        voxels (bool): if True, and we have a 3d conv, show the voxels
        alpha (float): only applicable if voxels=True
        stride (list): only applicable if voxels=True

    Returns:
        matplotlib.figure.Figure: fig - a Matplotlib figure

    References:
        https://matplotlib.org/devdocs/gallery/mplot3d/voxels.html

    Example:
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> conv = torch.nn.Conv2d(3, 9, (5, 7))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=None, limit=2)

    Example:
        >>> # xdoctest: +REQUIRES(--comprehensive)
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> import torchvision
        >>> # 2d uncolored gray-images
        >>> conv = torch.nn.Conv3d(1, 2, (3, 4, 5))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=1, limit=2)

        >>> # 2d colored rgb-images
        >>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=1, limit=2)

        >>> # 2d uncolored rgb-images
        >>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=1, limit=2)

        >>> # 3d gray voxels
        >>> conv = torch.nn.Conv3d(1, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=1, voxels=True,
        >>>                             limit=2)

        >>> # 3d color voxels
        >>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=1,
        >>>                             voxels=True, alpha=1, limit=3)

        >>> # hack the nice resnet weights into 3d-space
        >>> # xdoctest: +REQUIRES(--network)
        >>> import torchvision
        >>> model = torchvision.models.resnet50(pretrained=True)
        >>> conv = torch.nn.Conv3d(3, 1, (7, 7, 7))
        >>> weights_tohack = model.conv1.weight[0:7].data.numpy()
        >>> # normalize each weight for nice colors, then place in the conv3d
        >>> for w in weights_tohack:
        ...     w[:] = (w - w.min()) / (w.max() - w.min())
        >>> weights_hacked = weights_tohack.transpose(1, 0, 2, 3)[None, :]
        >>> conv.weight.data[:] = torch.FloatTensor(weights_hacked)

        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=1, voxels=True, alpha=.6)

        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=2, voxels=False, alpha=.9)

    Example:
        >>> # xdoctest: +REQUIRES(--network)
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> import torchvision
        >>> model = torchvision.models.resnet50(pretrained=True)
        >>> conv = model.conv1
        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=None)

    """
    import kwplot
    kwplot.autompl()
    import matplotlib.pyplot as plt

    # get relavent data out of pytorch module
    weights = conv.weight.data.cpu().numpy()
    in_channels = conv.in_channels
    # out_channels = conv.out_channels
    kernel_size = conv.kernel_size
    conv_dim = len(kernel_size)

    # TODO: use make_conv_images in the 2d case here

    if voxels:
        # use up to 3 spatial dimensions
        spatial_axes = list(kernel_size[-3:])
    else:
        # use only 2 spatial dimensions
        spatial_axes = list(kernel_size[-2:])
    color_axes = []

    output_axis = 0

    # If there are 3 input channels, we can visualize features in a colorspace
    if colorspace is not None and in_channels == 3:
        # Move colorable channels to the end (handle 1, 2 and 3d convolution)
        axes = [0] + list(range(2, 2 + conv_dim)) + [1]
        weights = weights.transpose(*axes)
        color_axes = [in_channels]
        output_axis = 0
    else:
        pass

    # Normalize layer weights between 0 and 1
    if normaxis is None:
        minval = weights.min()
        maxval = weights.max()
    else:
        # if normaxis=0 norm over output channels
        minval = weights.min(axis=output_axis, keepdims=True)
        maxval = weights.max(axis=output_axis, keepdims=True)

    weights_norm = (weights - minval) / (maxval - minval)

    if _hack_2drows:
        # To agree with jason's visualization for a paper figure
        if not voxels:
            weights_norm = weights_norm.transpose(1, 0, 2, 3)

    # flatten everything but the spatial and requested color dims
    weights_flat = weights_norm.reshape(-1, *(spatial_axes + color_axes))

    num_plots = min(weights_flat.shape[0], limit)
    dim = int(np.ceil(np.sqrt(num_plots)))

    if voxels:
        from mpl_toolkits.mplot3d import Axes3D  # NOQA
        filled = np.ones(spatial_axes, dtype=np.bool)
        # np.ones(spatial_axes)
        # d, h, w = np.indices(spatial_axes)

    fnum = kwplot.ensure_fnum(fnum)
    fig = kwplot.figure(fnum=fnum)
    fig.clf()
    if nCols is None:
        nCols = dim
    pnum_ = kwplot.PlotNums(nCols=nCols, nSubplots=num_plots)

    def plot_kernel3d(i):
        img = weights_flat[i]

        # fig = kwplot.figure(fnum=fnum, pnum=pnum_[i])
        ax = fig.add_subplot(*pnum_[i], projection='3d')
        # ax = fig.gca(projection='3d')

        alpha_ = (filled * alpha)[..., None]
        colors = img

        if not color_axes:
            import kwimage
            # transform grays into colors
            grays = kwimage.atleast_nd(img, 4)
            colors = np.concatenate([grays, grays, grays], axis=3)

        if colorspace and color_axes:
            import kwimage
            # convert into RGB
            for d in range(len(colors)):
                colors[d] = kwimage.convert_colorspace(colors[d],
                                                       src_space=colorspace,
                                                       dst_space='rgb')
        facecolors = np.concatenate([colors, alpha_], axis=3)

        # shuffle dims so height is upwards and depth move away from us.
        dim_labels = ['d', 'h', 'w']
        axes = [2, 0, 1]

        dim_labels = list(ub.take(dim_labels, axes))
        facecolors = facecolors.transpose(*(axes + [3]))
        filled_ = filled.transpose(*axes)
        spatial_axes_ = list(ub.take(spatial_axes, axes))

        # ax.voxels(filled_, facecolors=facecolors, edgecolors=facecolors)
        if False:
            ax.voxels(filled_, facecolors=facecolors, edgecolors='k')
        else:
            # hack to show "occluded" voxels
            # stride = [1, 3, 1]
            stride = [2, 2, 2]
            slices = tuple(slice(None, None, s) for s in stride)
            spatial_axes2 = list(np.array(spatial_axes_) * stride)
            filled2 = np.zeros(spatial_axes2, dtype=np.bool)
            facecolors2 = np.empty(spatial_axes2 + [4], dtype=np.float32)
            filled2[slices] = filled_
            facecolors2[slices] = facecolors
            edgecolors2 = [0, 0, 0, alpha]
            # 'k'
            # edgecolors2 = facecolors2

            # Shrink the gaps, which let you see occluded voxels
            x, y, z = np.indices(np.array(filled2.shape) +
                                 1).astype(float) // 2
            x[0::2, :, :] += 0.05
            y[:, 0::2, :] += 0.05
            z[:, :, 0::2] += 0.05
            x[1::2, :, :] += 0.95
            y[:, 1::2, :] += 0.95
            z[:, :, 1::2] += 0.95

            ax.voxels(x,
                      y,
                      z,
                      filled2,
                      facecolors=facecolors2,
                      edgecolors=edgecolors2)

        for xyz, dlbl in zip(['x', 'y', 'z'], dim_labels):
            getattr(ax, 'set_' + xyz + 'label')(dlbl)

        for xyz in ['x', 'y', 'z']:
            getattr(ax, 'set_' + xyz + 'ticks')([])

        ax.set_aspect('equal')
        if not labels or i < num_plots - 1:
            # show axis only on the last plot
            ax.grid(False)
            plt.axis('off')

    for i in ub.ProgIter(range(num_plots),
                         desc='plot conv layer',
                         enabled=False):
        if voxels:
            plot_kernel3d(i)
        else:
            img = weights_flat[i]
            kwplot.imshow(img,
                          fnum=fnum,
                          pnum=pnum_[i],
                          interpolation='nearest',
                          colorspace=colorspace)
    return fig
示例#12
0
def warp_image_test(image, transform, dsize=None):
    """

    from kwimage.transform import Affine
    import kwimage
    image = kwimage.grab_test_image('checkerboard', dsize=(2048, 2048)).astype(np.float32)
    image = kwimage.grab_test_image('astro', dsize=(2048, 2048))
    transform = Affine.random() @ Affine.scale(0.01)

    """
    from kwimage.transform import Affine
    import kwimage
    import numpy as np
    import ubelt as ub

    # Choose a random affine transform that probably has a small scale
    # transform = Affine.random() @ Affine.scale((0.3, 2))
    # transform = Affine.scale((0.1, 1.2))
    # transform = Affine.scale(0.05)
    transform = Affine.random() @ Affine.scale(0.01)
    # transform = Affine.random()

    image = kwimage.grab_test_image('astro')
    image = kwimage.grab_test_image('checkerboard')

    image = kwimage.ensure_float01(image)

    from kwimage import im_cv2
    import kwarray
    import cv2
    transform = Affine.coerce(transform)

    if 1 or dsize is None:
        h, w = image.shape[0:2]

        boxes = kwimage.Boxes(np.array([[0, 0, w, h]]), 'xywh')
        poly = boxes.to_polygons()[0]
        warped_poly = poly.warp(transform.matrix)
        warped_box = warped_poly.to_boxes().to_ltrb().quantize()
        dsize = tuple(map(int, warped_box.data[0, 2:4]))

    import timerit
    ti = timerit.Timerit(10, bestof=3, verbose=2)

    def _full_gauss_kernel(k0, sigma0, scale):
        num_downscales = np.log2(1 / scale)
        if num_downscales < 0:
            return 1, 0

        # Define b0 = kernel size for one downsample operation
        b0 = 5
        # Define sigma0 = sigma for one downsample operation
        sigma0 = 1

        # The kernel size and sigma doubles for each 2x downsample
        k = int(np.ceil(b0 * (2 ** (num_downscales - 1))))
        sigma = sigma0 * (2 ** (num_downscales - 1))

        if k % 2 == 0:
            k += 1
        return k, sigma

    def pyrDownK(a, k=1):
        assert k >= 0
        for _ in range(k):
            a = cv2.pyrDown(a)
        return a

    for timer in ti.reset('naive'):
        with timer:
            interpolation = 'nearest'
            flags = im_cv2._coerce_interpolation(interpolation)
            final_v5 = cv2.warpAffine(image, transform.matrix[0:2], dsize=dsize, flags=flags)

    # --------------------
    # METHOD 1
    #
    for timer in ti.reset('resize+warp'):
        with timer:
            params = transform.decompose()

            sx, sy = params['scale']
            noscale_params = ub.dict_diff(params, {'scale'})
            noscale_warp = Affine.affine(**noscale_params)

            h, w = image.shape[0:2]
            resize_dsize = (int(np.ceil(sx * w)), int(np.ceil(sy * h)))

            downsampled = cv2.resize(image, dsize=resize_dsize, fx=sx, fy=sy,
                                     interpolation=cv2.INTER_AREA)

            interpolation = 'linear'
            flags = im_cv2._coerce_interpolation(interpolation)
            final_v1 = cv2.warpAffine(downsampled, noscale_warp.matrix[0:2], dsize=dsize, flags=flags)

    # --------------------
    # METHOD 2
    for timer in ti.reset('fullblur+warp'):
        with timer:
            k_x, sigma_x = _full_gauss_kernel(k0=5, sigma0=1, scale=sx)
            k_y, sigma_y = _full_gauss_kernel(k0=5, sigma0=1, scale=sy)
            image_ = image.copy()
            image_ = cv2.GaussianBlur(image_, (k_x, k_y), sigma_x, sigma_y)
            image_ = kwarray.atleast_nd(image_, 3)
            # image_ = image_.clip(0, 1)

            interpolation = 'linear'
            flags = im_cv2._coerce_interpolation(interpolation)
            final_v2 = cv2.warpAffine(image_, transform.matrix[0:2], dsize=dsize, flags=flags)

    # --------------------
    # METHOD 3

    for timer in ti.reset('pyrDown+blur+warp'):
        with timer:
            temp = image.copy()
            params = transform.decompose()
            sx, sy = params['scale']

            biggest_scale = max(sx, sy)
            # The -2 allows the gaussian to be a little bigger. This
            # seems to help with border effects at only a small runtime cost
            num_downscales = max(int(np.log2(1 / biggest_scale)) - 2, 0)
            pyr_scale = 1 / (2 ** num_downscales)

            # Does the gaussian downsampling
            temp = pyrDownK(image, num_downscales)

            rest_sx = sx / pyr_scale
            rest_sy = sy / pyr_scale

            partial_scale = Affine.scale((rest_sx, rest_sy))
            rest_warp = noscale_warp @ partial_scale

            k_x, sigma_x = _full_gauss_kernel(k0=5, sigma0=1, scale=rest_sx)
            k_y, sigma_y = _full_gauss_kernel(k0=5, sigma0=1, scale=rest_sy)
            temp = cv2.GaussianBlur(temp, (k_x, k_y), sigma_x, sigma_y)
            temp = kwarray.atleast_nd(temp, 3)

            interpolation = 'cubic'
            flags = im_cv2._coerce_interpolation(interpolation)
            final_v3 = cv2.warpAffine(temp, rest_warp.matrix[0:2], dsize=dsize,
                                      flags=flags)

    # --------------------
    # METHOD 4 - dont do the final blur

    for timer in ti.reset('pyrDown+warp'):
        with timer:
            temp = image.copy()
            params = transform.decompose()
            sx, sy = params['scale']

            biggest_scale = max(sx, sy)
            num_downscales = max(int(np.log2(1 / biggest_scale)), 0)
            pyr_scale = 1 / (2 ** num_downscales)

            # Does the gaussian downsampling
            temp = pyrDownK(image, num_downscales)

            rest_sx = sx / pyr_scale
            rest_sy = sy / pyr_scale

            partial_scale = Affine.scale((rest_sx, rest_sy))
            rest_warp = noscale_warp @ partial_scale

            interpolation = 'linear'
            flags = im_cv2._coerce_interpolation(interpolation)
            final_v4 = cv2.warpAffine(temp, rest_warp.matrix[0:2], dsize=dsize, flags=flags)

    if 1:

        def get_title(key):
            from ubelt.timerit import _choose_unit
            value = ti.measures['mean'][key]
            suffix, mag = _choose_unit(value)
            unit_val = value / mag

            return key + ' ' + ub.repr2(unit_val, precision=2) + ' ' + suffix

        final_v2 = final_v2.clip(0, 1)
        final_v1 = final_v1.clip(0, 1)
        final_v3 = final_v3.clip(0, 1)
        final_v4 = final_v4.clip(0, 1)
        final_v5 = final_v5.clip(0, 1)
        import kwplot
        kwplot.autompl()
        kwplot.imshow(final_v5, pnum=(1, 5, 1), title=get_title('naive'))
        kwplot.imshow(final_v2, pnum=(1, 5, 2), title=get_title('fullblur+warp'))
        kwplot.imshow(final_v1, pnum=(1, 5, 3), title=get_title('resize+warp'))
        kwplot.imshow(final_v3, pnum=(1, 5, 4), title=get_title('pyrDown+blur+warp'))
        kwplot.imshow(final_v4, pnum=(1, 5, 5), title=get_title('pyrDown+warp'))