def make_orimask(radians, mag=None, alpha=1.0): """ Makes a colormap in HSV space where the orientation changes color and mag changes the saturation/value. Args: radians (ndarray): orientation in radians mag (ndarray): magnitude (must be normalized between 0 and 1) alpha (float | ndarray): if False or None, then the image is returned without alpha if a float, then mag is scaled by this and used as the alpha channel if an ndarray, then this is explicilty set as the alpha channel Returns: ndarray[float32]: an rgb / rgba image in 01 space SeeAlso: kwimage.overlay_alpha_images Example: >>> # xdoc: +REQUIRES(module:matplotlib) >>> x, y = np.meshgrid(np.arange(64), np.arange(64)) >>> dx, dy = x - 32, y - 32 >>> radians = np.arctan2(dx, dy) >>> mag = np.sqrt(dx ** 2 + dy ** 2) >>> orimask = make_orimask(radians, mag) >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.imshow(orimask, fnum=1, doclf=True, colorspace='rgb') >>> kwplot.show_if_requested() """ import matplotlib as mpl import matplotlib.cm # NOQA TAU = np.pi * 2 # Map radians to 0 to 1 ori01 = (radians % TAU) / TAU cmap_ = mpl.cm.get_cmap('hsv') color_rgb = cmap_(ori01)[..., 0:3].astype(np.float32) if mag is not None: import kwimage if mag.max() > 1: mag = mag / mag.max() color_hsv = kwimage.convert_colorspace(color_rgb, 'rgb', 'hsv') color_hsv[..., 1:3] = mag[..., None] color_rgb = kwimage.convert_colorspace(color_hsv, 'hsv', 'rgb') else: mag = 1 orimask = np.array(color_rgb, dtype=np.float32) if isinstance(alpha, np.ndarray): # Alpha specified as explicit numpy array orimask = kwimage.ensure_alpha_channel(orimask) orimask[:, :, 3] = alpha elif alpha is not False and alpha is not None: orimask = kwimage.ensure_alpha_channel(orimask) orimask[:, :, 3] = mag * alpha return orimask
def _draw_batch(harn, batch, decoded, limit=32): """ Example: >>> # xdoctest: +REQUIRES(--download) >>> harn = setup_harn().initialize() >>> # >>> batch = harn._demo_batch(0, tag='test') >>> outputs, loss = harn.run_batch(batch) >>> bx = harn.bxs[harn.current_tag] >>> decoded = harn._decode(outputs, batch['label']) >>> fpath = harn._draw_batch(bx, batch, decoded, limit=42) >>> print('fpath = {!r}'.format(fpath)) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> kwplot.imshow(fpath, colorspace='rgb', doclf=True) >>> kwplot.show_if_requested() """ import kwimage import kwplot inputs = batch['input'] inputs = inputs[0:limit] input_shape = inputs.shape dims = [160] * (len(input_shape) - 2) min_, max_ = inputs.min(), inputs.max() inputs = (inputs - min_) / (max_ - min_) inputs = torch.nn.functional.interpolate(inputs, size=dims) inputs = (inputs * 255).byte() inputs = inputs.data.cpu().numpy() dset = harn.datasets[harn.current_tag] true_cxs = batch['label'].data.cpu().numpy() pred_cxs = decoded['pred_cxs'].data.cpu().numpy() class_probs = decoded['class_probs'].data.cpu().numpy() todraw = [] for im, pcx, tcx, probs in zip(inputs, pred_cxs, true_cxs, class_probs): im_ = im.transpose(1, 2, 0) im_ = kwimage.convert_colorspace(im_, 'gray', 'rgb') im_ = np.ascontiguousarray(im_) im_ = kwplot.draw_clf_on_image(im_, dset.classes, tcx, probs) todraw.append(im_) stacked = kwimage.stack_images_grid(todraw, overlap=-10, bg_value=(10, 40, 30), chunksize=8) return stacked
def make_heatmask(probs, cmap='plasma', with_alpha=1.0, space='rgb', dsize=None): """ Colorizes a single-channel intensity mask (with an alpha channel) Args: probs (ndarray): 2D probability map with values between 0 and 1 cmap (str): mpl colormap with_alpha (float): between 0 and 1, uses probs as the alpha multipled by this number. space (str): output colorspace dsize (tuple): if not None, then output is resized to W,H=dsize SeeAlso: kwimage.overlay_alpha_images Example: >>> # xdoc: +REQUIRES(module:matplotlib) >>> probs = np.tile(np.linspace(0, 1, 10), (10, 1)) >>> heatmask = make_heatmask(probs, with_alpha=0.8, dsize=(100, 100)) >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.imshow(heatmask, fnum=1, doclf=True, colorspace='rgb') >>> kwplot.show_if_requested() """ import kwimage import matplotlib as mpl import matplotlib.cm # NOQA assert len(probs.shape) == 2 cmap_ = mpl.cm.get_cmap(cmap) probs = kwimage.ensure_float01(probs) heatmask = cmap_(probs).astype(np.float32) heatmask = kwimage.convert_colorspace(heatmask, 'rgba', space, implicit=True) if with_alpha is not False and with_alpha is not None: heatmask[:, :, 3] = (probs * with_alpha) # assign probs to alpha channel if dsize is not None: import cv2 heatmask = cv2.resize(heatmask, tuple(dsize), interpolation=cv2.INTER_NEAREST) return heatmask
def ensure_grayscale(img, colorspace_hint='BGR'): """ Example: >>> # xdoctest: +REQUIRES(module:kwimage) >>> import numpy as np >>> ensure_grayscale(np.array([[[0, 0, 1]]], dtype=np.float32)) array([[0.299]], dtype=float32) """ import kwimage img = kwimage.ensure_float01(img, copy=False) c = get_num_channels(img) if c == 1: return img else: return kwimage.convert_colorspace(img, src_space=colorspace_hint, dst_space='gray')
def imshow(img, fnum=None, pnum=None, xlabel=None, title=None, figtitle=None, ax=None, norm=None, cmap=None, data_colorbar=False, colorspace='rgb', interpolation='nearest', alpha=None, **kwargs): r""" Args: img (ndarray): image data. Height, Width, and Channel dimensions can either be in standard (H, W, C) format or in (C, H, W) format. If C in [3, 4], we assume data is in the rgb / rgba colorspace by default. colorspace (str): if the data is 3-4 channels, this indicates the colorspace 1 channel data is assumed grayscale. 4 channels assumes alpha. interpolation (str): either nearest (default), bicubic, bilinear norm (bool): if True, normalizes the image intensities to fit in a colormap. cmap (Colormap): color map used if data is not starndard image data data_colorbar (bool): if True, displays a color scale indicating how colors map to image intensities. fnum (int): figure number pnum (tuple): plot number xlabel (str): sets the label for the x axis title (str): set axes title (if ax is not given) figtitle (None): set figure title (if ax is not given) ax (Axes): axes to draw on (alternative to fnum and pnum) **kwargs: docla, doclf, projection Returns: tuple: (fig, ax) Ignore: >>> import kwplot >>> kwplot.autompl() >>> import kwimage >>> img = kwimage.grab_test_image('carl') >>> (fig, ax) = imshow(img) >>> result = ('(fig, ax) = %s' % (str((fig, ax)),)) >>> print(result) >>> kwplot.show_if_requested() """ import matplotlib as mpl import matplotlib.pyplot as plt if ax is not None: fig = ax.figure nospecial = True else: fig = figure(fnum=fnum, pnum=pnum, title=title, figtitle=figtitle, **kwargs) ax = fig.gca() nospecial = False if isinstance(img, six.string_types): # Allow for path to image to be specified img_fpath = img import kwimage img = kwimage.imread(img_fpath) valid_interpolation_choices = ['nearest', 'bicubic', 'bilinear'] if interpolation not in valid_interpolation_choices: raise KeyError( 'Invalid interpolation choice {}. Can be {}'.format( interpolation, valid_interpolation_choices)) plt_imshow_kwargs = { 'interpolation': interpolation, } if alpha is not None: plt_imshow_kwargs['alpha'] = alpha if norm is not None: if norm is True: norm = 'linear' if isinstance(norm, six.string_types): norm_choices = { 'linear': mpl.colors.Normalize, 'log': mpl.colors.LogNorm, } try: norm = norm_choices[norm]() except KeyError: raise KeyError('norm={} not in valid choices: {}'.format( norm, list(norm_choices) )) if not isinstance(norm, mpl.colors.Normalize): raise TypeError('norm={} must be an instance of {} or in {}'.format( norm, mpl.colors.Normalize, list(norm_choices))) plt_imshow_kwargs['norm'] = norm else: if cmap is None and not nospecial: plt_imshow_kwargs['vmin'] = 0 plt_imshow_kwargs['vmax'] = 255 # Handle tensor chw format in most cases try: if 'torch' in img.__module__: img = img.cpu().data.numpy() except Exception: pass if img.ndim == 3: if img.shape[0] == 3 or img.shape[0] == 1: if img.shape[2] > 4: # probably in chw format img = img.transpose(1, 2, 0) try: if len(img.shape) == 3 and (img.shape[2] == 3 or img.shape[2] == 4): # img is in a color format dst_space = 'rgb' import kwimage imgRGB = kwimage.convert_colorspace(img, src_space=colorspace, dst_space=dst_space, implicit=True) if not norm: if imgRGB.dtype.kind == 'f': maxval = imgRGB.max() if maxval > 1.01 and maxval < 256: imgRGB = np.array(imgRGB, dtype=np.uint8) cs = ax.imshow(imgRGB, **plt_imshow_kwargs) elif len(img.shape) == 2 or (len(img.shape) == 3 and img.shape[2] == 1): # img is in grayscale if len(img.shape) == 3: imgGRAY = img.reshape(img.shape[0:2]) else: imgGRAY = img if cmap is None: cmap = plt.get_cmap('gray') if isinstance(cmap, six.string_types): cmap = plt.get_cmap(cmap) # for some reason gray floats aren't working right if not norm: if imgGRAY.max() <= 1.01 and imgGRAY.min() >= -1E-9: imgGRAY = (imgGRAY * 255).astype(np.uint8) cs = ax.imshow(imgGRAY, cmap=cmap, **plt_imshow_kwargs) else: raise AssertionError( 'Unknown image format. ' 'img.dtype={!r}, img.shape={!r}'.format( img.dtype, img.shape) ) except TypeError as te: print('[imshow] imshow ERROR %r' % (te,)) raise except Exception as ex: print('!!! WARNING !!!') print('[imshow] type(img) = %r' % type(img)) if not isinstance(img, np.ndarray): print('!!! ERRROR !!!') pass print('[imshow] img.dtype = %r' % (img.dtype,)) print('[imshow] type(img) = %r' % (type(img),)) print('[imshow] img.shape = %r' % (img.shape,)) print('[imshow] imshow ERROR %r' % ex) raise ax.set_xticks([]) ax.set_yticks([]) if data_colorbar: # Use the axes to supply the colorbar info # Does this mean we can depricate `colorbar`? cbar = fig.colorbar(cs) if isinstance(norm, mpl.colors.LogNorm): # References: # https://github.com/matplotlib/matplotlib/issues/8307 cbar.ax.yaxis.set_major_locator(mpl.ticker.LogLocator()) # <- Why? See refs cbar.set_ticks(cbar.ax.yaxis.get_major_locator().tick_values( img.min(), img.max())) # scores = np.unique(img.flatten()) # if cmap is None: # cmap = 'hot' # colors = scores_to_color(scores, cmap) # colorbar(scores, colors) if xlabel is not None: ax.set_xlabel(xlabel) if figtitle is not None: set_figtitle(figtitle) return fig, ax
def make_legend_img(label_to_color, dpi=96, shape=(200, 200), mode='line', transparent=False): """ Makes an image of a categorical legend Args: label_to_color (Dict[str, Color]): mapping from string label to the color. CommandLine: xdoctest -m kwplot.mpl_make make_legend_img --show Example: >>> # xdoctest: +REQUIRES(module:kwplot) >>> import kwplot >>> import kwimage >>> label_to_color = { >>> 'blue': kwimage.Color('blue').as01(), >>> 'red': kwimage.Color('red').as01(), >>> 'green': 'green', >>> 'yellow': 'yellow', >>> 'orangered': 'orangered', >>> } >>> img = make_legend_img(label_to_color, transparent=True) >>> # xdoctest: +REQUIRES(--show) >>> kwplot.autompl() >>> kwplot.imshow(img) >>> kwplot.show_if_requested() """ import kwplot import kwimage plt = kwplot.autoplt() def append_phantom_legend_label(label, color, type_='line', alpha=1.0, ax=None): if ax is None: ax = plt.gca() _phantom_legend_list = getattr(ax, '_phantom_legend_list', None) if _phantom_legend_list is None: _phantom_legend_list = [] setattr(ax, '_phantom_legend_list', _phantom_legend_list) if type_ == 'line': phantom_actor = plt.Line2D((0, 0), (1, 1), color=color, label=label, alpha=alpha) else: phantom_actor = plt.Circle((0, 0), 1, fc=color, label=label, alpha=alpha) _phantom_legend_list.append(phantom_actor) fig = plt.figure(dpi=dpi) w, h = shape[1] / dpi, shape[0] / dpi fig.set_size_inches(w, h) # ax = fig.add_subplot('111') ax = fig.add_subplot(1, 1, 1) for label, color in label_to_color.items(): color = kwimage.Color(color).as01() append_phantom_legend_label(label, color, type_=mode, ax=ax) _phantom_legend_list = getattr(ax, '_phantom_legend_list', None) if _phantom_legend_list is None: _phantom_legend_list = [] setattr(ax, '_phantom_legend_list', _phantom_legend_list) ax.legend(handles=_phantom_legend_list) ax.grid(False) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) plt.axis('off') legend_img = render_figure_to_image(fig, dpi=dpi, transparent=transparent) legend_img = kwimage.convert_colorspace(legend_img, src_space='bgr', dst_space='rgb') legend_img = crop_border_by_color(legend_img) plt.close(fig) return legend_img
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')