def __getitem__(self, index): import kwimage # Load sample image and category sample = self.sampler.load_positive(index, with_annots=False) image = kwimage.atleast_3channels(sample['im'])[:, :, 0:3] target = sample['tr'] image = kwimage.ensure_uint255(image) if self.augmenter is not None: det = self.augmenter.to_deterministic() image = det.augment_image(image) # Resize to input dimensinos if self.input_dims is not None: dsize = tuple(self.input_dims[::-1]) image = kwimage.imresize(image, dsize=dsize, letterbox=True) class_id_to_idx = self.sampler.classes.id_to_idx cid = target['category_id'] cidx = class_id_to_idx[cid] im_chw = image.transpose(2, 0, 1) / 255.0 inputs = { 'rgb': torch.FloatTensor(im_chw), } labels = { 'class_idxs': cidx, } batch = { 'inputs': inputs, 'labels': labels, } return batch
def _draw_batch(harn, batch, decoded, limit=32): """ Example: >>> from ggr_matching import * >>> harn = setup_harn().initialize() >>> batch = harn._demo_batch(0, tag='vali') >>> outputs, loss = harn.run_batch(batch) >>> decoded = harn._decode(outputs) >>> stacked = harn._draw_batch(batch, decoded, limit=42) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> kwplot.imshow(stacked, colorspace='rgb', doclf=True) >>> kwplot.show_if_requested() """ tostack = [] fontkw = {'fontScale': 1.0, 'thickness': 2} n = min(limit, len(decoded['triple_imgs'][0])) dsize = (300, 300) for i in range(n): ims = [g[i].transpose(1, 2, 0) for g in decoded['triple_imgs']] ims = [cv2.resize(g, dsize) for g in ims] ims = [kwimage.atleast_3channels(g) for g in ims] triple_nxs = [n[i] for n in decoded['triple_nxs']] text = 'distAP={:.3g} -- distAN={:.3g} -- {}'.format( decoded['distAP'][i], decoded['distAN'][i], str(triple_nxs), ) color = ('dodgerblue' if decoded['distAP'][i] < decoded['distAN'][i] else 'orangered') img = kwimage.stack_images(ims, overlap=-2, axis=1, bg_value=(10 / 255, 40 / 255, 30 / 255)) img = (img * 255).astype(np.uint8) img = kwimage.draw_text_on_image(img, text, org=(2, img.shape[0] - 2), color=color, **fontkw) tostack.append(img) stacked = kwimage.stack_images_grid(tostack, overlap=-10, bg_value=(30, 10, 40), axis=1, chunksize=3) return stacked
def draw_on(self, image, color='blue', fill=True, border=False, alpha=1.0, copy=False): """ Rasterizes a polygon on an image. See `draw` for a vectorized matplotlib version. Args: image (ndarray): image to raster polygon on. color (str | tuple): data coercable to a color fill (bool, default=True): draw the center mass of the polygon border (bool, default=False): draw the border of the polygon alpha (float, default=1.0): polygon transparency (setting alpha < 1 makes this function much slower). copy (bool, default=False): if False only copies if necessary Example: >>> # xdoc: +REQUIRES(module:kwplot) >>> from kwimage.structs.polygon import * # NOQA >>> self = Polygon.random(n_holes=1).scale(128) >>> image = np.zeros((128, 128), dtype=np.float32) >>> image = self.draw_on(image) >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> kwplot.imshow(image, fnum=1) Example: >>> import kwimage >>> color = 'blue' >>> self = kwimage.Polygon.random(n_holes=1).scale(128) >>> image = np.zeros((128, 128), dtype=np.float32) >>> # Test drawong on all channel + dtype combinations >>> im3 = np.random.rand(128, 128, 3) >>> im_chans = { >>> 'im3': im3, >>> 'im1': kwimage.convert_colorspace(im3, 'rgb', 'gray'), >>> 'im4': kwimage.convert_colorspace(im3, 'rgb', 'rgba'), >>> } >>> inputs = {} >>> for k, im in im_chans.items(): >>> inputs[k + '_01'] = (kwimage.ensure_float01(im.copy()), {'alpha': None}) >>> inputs[k + '_255'] = (kwimage.ensure_uint255(im.copy()), {'alpha': None}) >>> inputs[k + '_01_a'] = (kwimage.ensure_float01(im.copy()), {'alpha': 0.5}) >>> inputs[k + '_255_a'] = (kwimage.ensure_uint255(im.copy()), {'alpha': 0.5}) >>> outputs = {} >>> for k, v in inputs.items(): >>> im, kw = v >>> outputs[k] = self.draw_on(im, color=color, **kw) >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.figure(fnum=2, doclf=True) >>> kwplot.autompl() >>> pnum_ = kwplot.PlotNums(nCols=2, nRows=len(inputs)) >>> for k in inputs.keys(): >>> kwplot.imshow(inputs[k][0], fnum=2, pnum=pnum_(), title=k) >>> kwplot.imshow(outputs[k], fnum=2, pnum=pnum_(), title=k) >>> kwplot.show_if_requested() """ import kwimage # return shape of contours to openCV contours dtype_fixer = _generic._consistent_dtype_fixer(image) # print('--- A') # print('image.dtype = {!r}'.format(image.dtype)) # print('image.max() = {!r}'.format(image.max())) # line_type = cv2.LINE_AA line_type = cv2.LINE_8 cv_contours = self._to_cv_countours() if alpha is None or alpha == 1.0: # image = kwimage.ensure_uint255(image) image = kwimage.atleast_3channels(image, copy=copy) rgba = kwimage.Color(color)._forimage(image) else: image = kwimage.ensure_float01(image) image = kwimage.ensure_alpha_channel(image) rgba = kwimage.Color(color, alpha=alpha)._forimage(image) # print('--- B') # print('image.dtype = {!r}'.format(image.dtype)) # print('image.max() = {!r}'.format(image.max())) # print('rgba = {!r}'.format(rgba)) if fill: if alpha is None or alpha == 1.0: # Modification happens inplace image = cv2.fillPoly(image, cv_contours, rgba, line_type, shift=0) else: orig = image.copy() mask = np.zeros_like(orig) mask = cv2.fillPoly(mask, cv_contours, rgba, line_type, shift=0) # TODO: could use add weighted image = kwimage.overlay_alpha_images(mask, orig) rgba = kwimage.Color(rgba)._forimage(image) # print('--- C') # print('image.dtype = {!r}'.format(image.dtype)) # print('image.max() = {!r}'.format(image.max())) # print('rgba = {!r}'.format(rgba)) if border or True: thickness = 4 contour_idx = -1 image = cv2.drawContours(image, cv_contours, contour_idx, rgba, thickness, line_type) # image = kwimage.ensure_float01(image)[..., 0:3] # print('--- D') # print('image.dtype = {!r}'.format(image.dtype)) # print('image.max() = {!r}'.format(image.max())) image = dtype_fixer(image, copy=False) return image
def draw_clf_on_image(im, classes, tcx=None, probs=None, pcx=None, border=1): """ Draws classification label on an image. Works best with image chips sized between 200x200 and 500x500 Args: im (ndarray): the image classes (Sequence | CategoryTree): list of class names tcx (int, default=None): true class index if known probs (ndarray): predicted class probs for each class pcx (int, default=None): predicted class index. (if None but probs is specified uses argmax of probs) Example: >>> # xdoctest: +REQUIRES(module:torch) >>> import torch >>> import kwarray >>> import kwimage >>> rng = kwarray.ensure_rng(0) >>> im = (rng.rand(300, 300) * 255).astype(np.uint8) >>> classes = ['cls_a', 'cls_b', 'cls_c'] >>> tcx = 1 >>> probs = rng.rand(len(classes)) >>> probs[tcx] = 0 >>> probs = torch.FloatTensor(probs).softmax(dim=0).numpy() >>> im1_ = kwimage.draw_clf_on_image(im, classes, tcx, probs) >>> probs[tcx] = .9 >>> probs = torch.FloatTensor(probs).softmax(dim=0).numpy() >>> im2_ = kwimage.draw_clf_on_image(im, classes, tcx, probs) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> kwplot.imshow(im1_, colorspace='rgb', pnum=(1, 2, 1), fnum=1, doclf=True) >>> kwplot.imshow(im2_, colorspace='rgb', pnum=(1, 2, 2), fnum=1) >>> kwplot.show_if_requested() """ import kwimage im_ = kwimage.atleast_3channels(im) w, h = im.shape[0:2][::-1] if pcx is None and probs is not None: import kwarray probs = kwarray.ArrayAPI.numpy(probs) pcx = probs.argmax() if probs is not None: pred_score = None if pcx is None else probs[pcx] true_score = None if tcx is None else probs[tcx] org1 = np.array((2, h - 5)) org2 = np.array((2, 5)) true_label = None if tcx is not None: true_name = classes[tcx] if pcx == tcx: true_label = 't:{tcx}:{true_name}'.format(**locals()) elif probs is None: true_label = 't:{tcx}:\n{true_name}'.format(**locals()) else: true_label = 't:{tcx}@{true_score:.2f}:\n{true_name}'.format( **locals()) pred_label = None if pcx is not None: pred_name = classes[pcx] if probs is None: pred_label = 'p:{pcx}:\n{pred_name}'.format(**locals()) else: pred_label = 'p:{pcx}@{pred_score:.2f}:\n{pred_name}'.format( **locals()) fontkw = {'fontScale': 1.0, 'thickness': 2} color = 'dodgerblue' if pcx == tcx else 'orangered' # im_ = draw_text_on_image(im_, pred_label, org=org1 - 2, # color='white', valign='bottom', **fontkw) # im_ = draw_text_on_image(im_, true_label, org=org2 - 2, # color='white', valign='top', **fontkw) if pred_label is not None: im_ = draw_text_on_image(im_, pred_label, org=org1, color=color, border=border, valign='bottom', **fontkw) if true_label is not None: im_ = draw_text_on_image(im_, true_label, org=org2, color='lawngreen', valign='top', border=border, **fontkw) return im_
def draw_on(self, image, color='white', radius=None, copy=False): """ CommandLine: xdoctest -m ~/code/kwimage/kwimage/structs/points.py Points.draw_on --show Example: >>> # xdoc: +REQUIRES(module:kwplot) >>> from kwimage.structs.points import * # NOQA >>> s = 128 >>> image = np.zeros((s, s)) >>> self = Points.random(10).scale(s) >>> image = self.draw_on(image) >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.figure(fnum=1, doclf=True) >>> kwplot.autompl() >>> kwplot.imshow(image) >>> self.draw(radius=3, alpha=.5) >>> kwplot.show_if_requested() Example: >>> # xdoc: +REQUIRES(module:kwplot) >>> from kwimage.structs.points import * # NOQA >>> s = 128 >>> image = np.zeros((s, s)) >>> self = Points.random(10).scale(s) >>> image = self.draw_on(image, radius=3, color='distinct') >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.figure(fnum=1, doclf=True) >>> kwplot.autompl() >>> kwplot.imshow(image) >>> self.draw(radius=3, alpha=.5, color='classes') >>> kwplot.show_if_requested() Example: >>> import kwimage >>> s = 32 >>> self = kwimage.Points.random(10).scale(s) >>> color = 'blue' >>> # Test drawong on all channel + dtype combinations >>> im3 = np.zeros((s, s, 3), dtype=np.float32) >>> im_chans = { >>> 'im3': im3, >>> 'im1': kwimage.convert_colorspace(im3, 'rgb', 'gray'), >>> 'im4': kwimage.convert_colorspace(im3, 'rgb', 'rgba'), >>> } >>> inputs = {} >>> for k, im in im_chans.items(): >>> inputs[k + '_01'] = (kwimage.ensure_float01(im.copy()), {'radius': None}) >>> inputs[k + '_255'] = (kwimage.ensure_uint255(im.copy()), {'radius': None}) >>> outputs = {} >>> for k, v in inputs.items(): >>> im, kw = v >>> outputs[k] = self.draw_on(im, color=color, **kw) >>> # xdoc: +REQUIRES(--show) >>> import kwplot >>> kwplot.figure(fnum=2, doclf=True) >>> kwplot.autompl() >>> pnum_ = kwplot.PlotNums(nCols=2, nRows=len(inputs)) >>> for k in inputs.keys(): >>> kwplot.imshow(inputs[k][0], fnum=2, pnum=pnum_(), title=k) >>> kwplot.imshow(outputs[k], fnum=2, pnum=pnum_(), title=k) >>> kwplot.show_if_requested() """ import kwimage dtype_fixer = _generic._consistent_dtype_fixer(image) if radius is None: if color == 'distinct': raise NotImplementedError image = kwimage.atleast_3channels(image) image = kwimage.ensure_float01(image, copy=copy) # value = kwimage.Color(color).as01() value = kwimage.Color(color)._forimage(image) image = self.data['xy'].fill( image, value, coord_axes=[1, 0], interp='bilinear') else: import cv2 image = kwimage.atleast_3channels(image, copy=copy) # note: ellipse has a different return type (UMat) and does not # work inplace if the input is not contiguous. image = np.ascontiguousarray(image) xy_pts = self.data['xy'].data.reshape(-1, 2) if color == 'distinct': colors = kwimage.Color.distinct(len(xy_pts)) elif color == 'classes': # TODO: read colors from categories if they exist class_idxs = self.data['class_idxs'] _keys, _vals = kwarray.group_indices(class_idxs) cls_colors = kwimage.Color.distinct(len(self.meta['classes'])) colors = list(ub.take(cls_colors, class_idxs)) colors = [kwimage.Color(c)._forimage(image) for c in colors] # if image.dtype.kind == 'f': # colors = [kwimage.Color(c).as01() for c in colors] # else: # colors = [kwimage.Color(c).as255() for c in colors] else: value = kwimage.Color(color)._forimage(image) colors = [value] * len(xy_pts) # image = kwimage.ensure_float01(image) for xy, color_ in zip(xy_pts, colors): # center = tuple(map(int, xy.tolist())) center = tuple(xy.tolist()) axes = (radius / 2, radius / 2) center = tuple(map(int, center)) axes = tuple(map(int, axes)) # print('center = {!r}'.format(center)) # print('axes = {!r}'.format(axes)) cv2.ellipse(image, center, axes, angle=0.0, startAngle=0.0, endAngle=360.0, color=color_, thickness=-1) image = dtype_fixer(image, copy=False) return image