def demo_overlay(): """How to overlay images and highlight regions.""" # Overlay rgb = imutils.imread('../data/flamingo.jpg', mode='L') # Generate some data to overlay im_height, im_width = rgb.shape[0], rgb.shape[1] peak_pos = (im_width * 0.75, im_height * 0.15) xv, yv = np.meshgrid(np.arange(0, im_width), np.arange(0, im_height)) overlay = np.exp( -(np.power(xv - peak_pos[0], 2) + np.power(yv - peak_pos[1], 2)) / (3e4)) overlay_vis = imvis.overlay(imvis.pseudocolor(overlay), rgb, 0.7) # Highlight regions rgb = imutils.imread('../data/flamingo.jpg', mode='RGB') rgb_mask = np.zeros((rgb.shape[0], rgb.shape[1]), dtype=np.uint8) rgb_mask[160:334, 120:290] = 1 highlight = imvis.highlight(rgb, rgb_mask) # highlight another region, this time in blue rgb_mask[:] = 0 rgb_mask[200:374, 250:420] = 1 highlight = imvis.highlight(highlight, rgb_mask, color=(0, 0, 255)) # Combine all "colored" images: collage = imvis.make_collage([overlay_vis, highlight], padding=5, bg_color=(255, 255, 255)) imvis.imshow(collage, title="Overlay & Highlights", wait_ms=-1)
def demo_primitives(): """How to draw basic shapes, text boxes, etc.""" # * rotated rect around dot, maybe img = imutils.imread('../data/ninja.jpg', mode='RGB') # Load grayscale as 3-channel image # Draw rounded box(es) vis_img = imvis.draw_rounded_rects(img, [(9, 23, 149, 106)], corner_percentage=0.2, fill_opacity=0.75, line_width=0, color=(0, 200, 200), non_overlapping=True) # Draw filled & dashed rect # vis_img = imvis.draw_rects(vis_img, [(178, 164, 43, 29)], fill_opacity=0.4, line_width=2, dash_length=10, color=(220, 0, 255)) # Draw rotated rectangle vis_img = imvis.draw_rotated_rects(vis_img, [(60, 220, 70, 45, -55)], fill_opacity=0.5, line_width=2, dash_length=15, color=(0, 200, 0)) # Draw lines - a line is a list or tuple: ((start-point), (end-point), is_dashed, color) lines = [ [(7, 184), (329, 211), True, (255, 0, 255)], # Dashed [(42, 147), (337, 168), False, (255, 0, 255)] ] # Solid vis_img = imvis.draw_lines(vis_img, lines, line_width=3, default_color=(200, 255, 0), dash_length=15) # Draw arrows - same format as lines (see above) arrows = [[(314, 20), (175, 38), False, (0, 255, 255)], ((314 + 20, 20 + 30), (175 + 20, 38 + 30), True, (255, 0, 255))] #[(320, 33), (316, 87), True, (0, 255, 255)]] vis_img = imvis.draw_arrows(vis_img, arrows, line_width=2, default_color=(0, 200, 255), dash_length=15, arrow_head_factor=0.1) # Draw text box vis_img = imvis.draw_text_box(vis_img, 'Angry', (283, 68), text_anchor='west', bg_color=(255, 0, 255), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.8) imvis.imshow(vis_img, title='Drawing Primitives', wait_ms=10)
def demo_pseudocolor(): """Pseudocoloring.""" peaks = imutils.imread('../data/peaks.png', mode='L') # For visualization purposes only, reduce input to a few # distinct categories/labels: data = ((peaks / 25) - 5).astype(np.int16) names = ['Bone', 'Magma', 'Viridis'] images = list() for name in names: pc = imvis.pseudocolor( data, limits=None, # Compute min/max from data color_map=colormaps.by_name(name, return_rgb=True)) images.append(pc) # Display as a single collage padding = 10 # Add alpha channel to render the collage nicely for the repo's README images[0] = np.dstack( (images[0], 255 * np.ones(images[0].shape[:2], dtype=np.uint8))) collage = imvis.make_collage(images, padding=padding, fixed_size_per_image=(200, 200), bg_color=(0, 0, 0, 0), num_images_per_row=len(images)) # Add labels height, width = collage.shape[:2] mask_width = (width - (len(names) - 1) * padding) / len(names) for i in range(len(names)): pos = (i * (mask_width + padding) + mask_width / 2, height - 10) collage = imvis.draw_text_box(collage, names[i], pos, text_anchor='south', bg_color=(0, 0, 0), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.8) imvis.imshow(collage, title='Pseudocoloring', wait_ms=-1) imutils.imsave('../../doc/example-pseudocolor.png', collage)
def _process_next_frameset(self, capture, frameset): # assert len(frameset) == 1 # Currently, we assume there's only one mobotix camera connected! if frameset[0] is None: self._streamer.stop() return if self._args.verbose: # Measure time between received framesets if self._mean_ms_between_framesets is None: ms_between_framesets = 0 else: ms_between_framesets = pyutils.ttoc('[frameset received]') self._mean_ms_between_framesets = ms_between_framesets if self._mean_ms_between_framesets is None else 0.9 * self._mean_ms_between_framesets + 0.1 * ms_between_framesets if ms_between_framesets > 0: print( 'Frameset received after {:.2f} ms, avg. framerate {:.1f}'. format(ms_between_framesets, 1000.0 / self._mean_ms_between_framesets)) pyutils.tic('[frameset received]') vis_frames = list() vis_labels = list() for idx, frame in enumerate(frameset): frame_lbl = capture.frame_label(idx) vis_frame = imvis.pseudocolor(frame, [0, 5000], color_map=colormaps.colormap_turbo_rgb)\ if capture.is_depth(idx) or capture.is_infrared(idx) else frame vis_frames.append(vis_frame) vis_labels.append(frame_lbl) # Overlay labels vis_frames = [ imvis.draw_text_box(vis_frames[idx], vis_labels[idx], (vis_frames[idx].shape[1] // 2, 40), text_anchor='north', bg_color=(220, 0, 0), font_color=(0, 0, 0)) for idx in range(len(vis_frames)) ] # Forward to storage processes self._store(capture, frameset) # Display the live stream collage = imvis.make_collage(vis_frames, num_images_per_row=2, padding=0, fixed_size_per_image=(640, 480)) k = imvis.imshow(collage, "Live view", wait_ms=10) if k == ord('q') or k == 27: self._streamer.stop()
def show_off_boxes3d(): # 3D bounding box animations (to show clipping, visibility tests, etc.) box3da = ([(-3, 5, 2.5), (-1.5, 5, 2.5), (-1.5, 3, 2.5), np.array((-3, 3, 2.5)), (-3, 5, 0), (-1.5, 5, 0), (-1.5, 3, 0), (-3, 3, 0)], (255, 0, 0), "A box") # Must be a tuple!!! box3db = ([(-2, -2, -0.5), (-2, 2, -0.5), (0.1, 2, -0.5), (0.1, -2, -0.5), (-2, -2, -1.5), (-2, 2, -1.5), (0.1, 2, -1.5), (0.1, -2, -1.5)], (0, 255, 0), "A better box") # Must be a tuple!!! box3dc = ([[-0.5, -0.5, 1], [-0.5, 0.5, 1], [0.5, 0.5, 1], [0.5, -0.5, 1], [-0.5, -0.5, 0], [-0.5, 0.5, 0], np.array([0.5, 0.5, 0]), np.array([0.5, -0.5, 0])], (0, 255, 255), "Tilted occluder") box3dc = shift_bbox3d(rotate_bbox3d_center(box3dc, 45, 0, 10), 0, 0.5, 0) # Dummy camera parameters: R = np.array([[1.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]], dtype=np.float64) C = np.array([0, -1, 1], dtype=np.float64).reshape((3, 1)) t = -np.dot(R, C) K = np.array([[300, 0, 512], [0, 300, 384], [0, 0, 1]], dtype=np.float64) # Show off (1) for angle in range(0, 90, 2): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d( vis_img, [box3da, rotate_bbox3d(box3db, 0, 0, angle), box3dc], K, R, t, line_width=3, text_anchor='center', non_overlapping=True) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow( vis_img, title="3d bbox (non-overlapping)", wait_ms=100) & 0xFF if k == 27: return # Show off (2) for angle in range(0, 360, 2): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d( vis_img, [rotate_bbox3d_center(box3da, angle, 0, 0)], K, R, t, line_width=3, dash_length=-1, text_anchor='southeast') vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=10) & 0xFF if k == 27: return # Show off (3) for angle in range(0, 360, 2): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d( vis_img, [rotate_bbox3d_center(box3da, 0, angle, 0)], K, R, t, line_width=3) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=10) & 0xFF if k == 27: return # Show off (4) for angle in range(0, 360, 2): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d( vis_img, [rotate_bbox3d_center(box3da, 0, 0, angle)], K, R, t, line_width=3) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=10) & 0xFF if k == 27: return # Show off (5) for shift in range(0, -48, -1): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d(vis_img, [ shift_bbox3d(rotate_bbox3d(box3da, 0, 0, 10), 1.9, shift / 10.0, 0) ], K, R, t, line_width=3) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=50) & 0xFF if k == 27: return # Show off (6) box = rotate_bbox3d_center(box3da, 90, 0, 0) for shift in range(0, -54, -1): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d( vis_img, [shift_bbox3d(box, 1.5, shift / 10.0, 0)], K, R, t, line_width=3) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=50) & 0xFF if k == 27: return # Show off (7) box = rotate_bbox3d_center(box3da, 40, 0, 20) for shift in range(0, -60, -1): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d( vis_img, [shift_bbox3d(box, 1.5, shift / 10.0, 0)], K, R, t, line_width=3) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=50) & 0xFF if k == 27: return # Show off (8) for shift in range(0, -63, -1): vis_img = np.zeros((768, 1024, 3), dtype=np.uint8) vis_img = imvis.draw_bboxes3d(vis_img, [ shift_bbox3d(rotate_bbox3d_center(box3db, 10, 10, -20), 1, 4 + shift / 10.0, 1.5) ], K, R, t, line_width=3) vis_img = imvis.draw_text_box(vis_img, 'Press ESC to cancel', (512, 5), text_anchor='north') k = imvis.imshow(vis_img, title="3d bbox", wait_ms=50) & 0xFF if k == 27: return
mask_width = (width - padding) / 2 for i in range(len(names)): pos = ((i % 2) * (mask_width + padding) + mask_width / 2, (i // 2) * (225 + padding) + (225 - 10)) collage = imvis.draw_text_box(collage, names[i], pos, text_anchor='south', bg_color=(0, 0, 0), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.8) imvis.imshow(collage, title='Basic Drawing', wait_ms=-1) imutils.imsave('../../doc/example-imvis.png', collage) # ############################################################################ # Drawing basic shapes/primitives demo_primitives() # ############################################################################ # Pseudocolorization demo_pseudocolor() # ############################################################################ # Overlay images and highlight regions demo_overlay() # ############################################################################
center = (im_width / 2.0, im_height / 2.0) rect = (im_width * 3 / 4, im_height / 2, 50, 80) vis_img = imvis.draw_rects(rgb, [rect], fill_opacity=0.4, line_width=2, dash_length=10, color=(220, 0, 255)) rotrect = imutils.rotate_rect(rect, center, np.deg2rad(5)) vis_img = imvis.draw_rotated_rects(vis_img, [rotrect], fill_opacity=0.4, line_width=2, dash_length=10, color=(220, 0, 0)) imvis.imshow(vis_img, title="rotated rect", wait_ms=200) #TODO make testable ## Find the convex hull of this polyline # First, scale it to the target image size target_sz = (1024, 768) xmin, xmax = np.min(x), np.max(x) ymin, ymax = np.min(y), np.max(y) padding = 20 scale_x = (target_sz[0] - 2 * padding) / (xmax - xmin) scale_y = (target_sz[1] - 2 * padding) / (ymax - ymin) # Subsample the polyline to get some points for convex hull computation polygon = [((p[0] - xmin) * scale_x + padding, target_sz[1] - ((p[1] - ymin) * scale_y + padding)) for p in [polyline[sub] for sub in range(0, len(polyline), 5)]]
def demo_align(): cfg_base_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'data-best') cfg_file = os.path.join(cfg_base_path, 'k4a-manual-alignment.cfg') streamer = best.MulticamStepper(cfg_file, True, cfg_file_rel_path_base_dir=cfg_base_path, verbose=True) capture = streamer.start() _, frameset = streamer.next_frameset() K_color = capture.intrinsics(0) K_depth = capture.intrinsics(1) Rt_stereo = capture.stereo_transformation(1) D_color = capture.distortion_coefficients(0) D_depth = capture.distortion_coefficients(1) alignment = None num_frames_processed = 1 while streamer.is_available(): capture, frameset = streamer.next_frameset() if frameset is None: print('Invalid frameset received, terminating now!') break color, depth, infrared = frameset if alignment is None: alignment = best.RgbdAlignment(K_color, K_depth, Rt_stereo[0], Rt_stereo[1], img_resolution(color), img_resolution(depth), D_color, D_depth) # pyutils.tic('cpp-align') # aligned_depth_cpp = alignment.align_d2c(depth) # pyutils.toc('cpp-align') pyutils.tic('cpp-align-di') aligned_depth_cpp, aligned_ir_cpp = alignment.align_di2c( depth, infrared) pyutils.toc('cpp-align-di') vis_frames = [color, vis_depth(depth), vis_infrared(infrared)] vis_labels = ['RGB', 'Depth (original)', 'IR (original)'] ## The cpp version takes care of properly interpolating depth values during alignment # takes about 3-5ms per 640x480 depth # Additionally aligning the intensity image adds another 0.8-1ms to the cpp processing time ## The python version is a naive reprojection + binning (without depth ordering, filtering, interpolation, etc.) # takes about 20-30 ms (~4-5 times slower than cpp) # pyutils.tic('py-align') # aligned_depth_py = align_depth_to_color(depth, K_color, K_depth, Rt_stereo, color.shape[1], color.shape[0]) # pyutils.toc('py-align') aligned_depth = aligned_depth_cpp vis_aligned_depth = vis_depth(aligned_depth) vis_frames.append(vis_aligned_depth) vis_labels.append('Aligned Depth') aligned_ir = aligned_ir_cpp vis_aligned_ir = vis_infrared(aligned_ir) # vis_frames.append(vis_aligned_ir) # vis_labels.append('Aligned IR') # color_resized = cv2.resize(color, (aligned_depth.shape[1], aligned_depth.shape[0])) # vis_frames.append(color_resized) # vis_labels.append('color resized') # vis_frames.append(imvis.overlay(vis_aligned_depth, color_resized, 0.7))#, aligned_depth > 0)) vis_frames.append(imvis.overlay(vis_aligned_depth, color, 0.7)) vis_labels.append('RGB+D') vis_frames.append(imvis.overlay(vis_aligned_ir, color, 0.7)) vis_labels.append('RGB+IR') # Visualization (rescale, overlay a label, show a single collage) bg_color = (180, 180, 180) vis_frames = [ imutils.aspect_aware_resize(f, (640, 480), padding_value=bg_color)[0] for f in vis_frames ] vis_frames = overlay_labels(vis_frames, vis_labels) img_per_row = len(vis_frames) // 2 img_per_row = img_per_row if len( vis_frames) % 2 == 0 else img_per_row + 1 collage = imvis.make_collage(vis_frames, bg_color=bg_color, num_images_per_row=img_per_row) k = imvis.imshow(collage, title='Stream', wait_ms=20) if k == ord('q') or k == 27: break num_frames_processed += 1
def _cb_next_frameset(self, capture, frameset): if any([f is None for f in frameset]): mp.get_logger().warning('[Demo] Skipping invalid frameset') return # Colorize depth/infrared images for visualization def _col_rgb(f): return f #imutils.transform(f, 'histeq') def _col_depth(f): # return imutils.transform(f, 'depth2surfnorm', 'surfnorm2rgb') return imvis.pseudocolor(f, limits=[0, self._args.max_depth], color_map=colormaps.colormap_turbo_rgb) def _col_ir(f): #TODO # Normalize/stretch, etc. using: self._args.max_ir if f.dtype == np.uint8: return f return imvis.pseudocolor(f, limits=None, color_map=colormaps.colormap_turbo_rgb) vis_frames = [ _col_depth(frameset[idx]) if capture.is_depth(idx) else (_col_ir(frameset[idx]) if capture.is_infrared(idx) else _col_rgb(frameset[idx])) for idx in range(len(frameset)) ] # Resize vis_frames = [ imutils.fuzzy_resize(f, self._args.scale) for f in vis_frames ] # Overlay frame labels if self._args.label_overlay: vis_frames = [ imvis.draw_text_box(vis_frames[idx], capture.frame_label(idx) + (' [Undist. & Rect.]' if capture.is_rectified(idx) else ''), (vis_frames[idx].shape[1] // 2, 10), 'north', bg_color=(0, 0, 0), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.5) for idx in range(len(vis_frames)) ] # Show collage collage = imvis.make_collage( vis_frames, num_images_per_row=self._args.images_per_row) k = imvis.imshow(collage, title='Live Stream', wait_ms=10) # Handle user input (if any) if k == 27 or k == ord('q'): self._streamer.stop() elif k == ord('s') or k == 85 or k == 86 or k == 10: # 85, 86, 10: PgUp, PgDown, Enter if self._storage is not None: for idx in range(len(frameset)): self._storage[capture.frame_label( idx)].put_storage_request(frameset[idx]) mp.get_logger().info('[Demo] Current frameset has been saved.')
(530, img.shape[0]-10), text_anchor='south', bg_color=(0, 0, 0), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.8) if __name__ == "__main__": # RGBA, transparent image vis_img = np.zeros((256, 600, 4)) vis_img = demo_intersect(vis_img) vis_img = demo_tangents(vis_img) vis_img = demo_convhull(vis_img) imvis.imshow(vis_img, title='Geometry Utilities', wait_ms=-1) imutils.imsave('../../doc/example-geometry.png', vis_img) # # #TODO remove this # # print(math2d.circle_from_three_points((0,0), (0,0), (10, 20))) # # # Plane from 3 points # # plane = cmath.plane_from_three_points((10,234,0), (13,-23,-16), (234.2,37,999)) # # print(plane) # # # Collinear - should be all 0, and a warning issued # # plane = cmath.plane_from_three_points((-7,3,0), (3,3,10), (5,3,12)) # # print(plane) # # # Compute distances: # # plane = cmath.plane_from_three_points((-1,-2,2), (-1,2,2), (1,0,1)) # # print(plane)
def demo(pseudocolor=True, inspect=False): imgs = [imutils.imread('../data/ninja-01.jpg'), imutils.imread('../data/ninja-02.jpg')] bgmodels = list() bgmodel = bgm.BackgroundModel() bgmodel.approximate_median_bgm( adaptation_step=5, fg_report_threshold=50, median_on_grayscale=True) bgmodels.append(bgmodel) bgmodel = bgm.BackgroundModel() bgmodel.block_mean_bgm( block_size=(16, 16), block_overlap=0.5, update_rate=0.01, fg_report_threshold=50, channel='grayscale') bgmodels.append(bgmodel) bgmodel = bgm.BackgroundModel() bgmodel.gaussian_mixture_bgm( history=500, detect_shadows=True, var_thresh=100, comp_thresh=0.05) bgmodels.append(bgmodel) bgmodel = bgm.BackgroundModel() bgmodel.normalized_rgb_bgm( report_as_binary=False, # binary_reporting_threshold=20, update_rate=0.1, alpha=0.1, beta=1.0) bgmodels.append(bgmodel) print(""" ! Note that the reported initialization time for the first BGM includes library initialization - maybe OpenCV (haven't tracked that down yet). """) fg_masks = list() for bgmodel in bgmodels: pyutils.tic('init') bgmodel.init(imgs[0]) t_init = pyutils.ttoc('init') pyutils.tic('apply') mask = bgmodel.report_changes(imgs[1]) t_apply = pyutils.ttoc('apply') if pseudocolor: fg_masks.append(imvis.pseudocolor(mask, limits=None, color_map=colormaps.colormap_viridis_rgb)) else: fg_masks.append(mask) print('init/apply: {:17s} {:7.2f} ms, {:7.2f} ms'.format(bgmodel.name(), t_init, t_apply)) if inspect: import iminspect iminspect.show(mask) padding = 10 # Add alpha channel to render the README visualization nicely for web display fg_masks[0] = np.dstack((fg_masks[0], 255 * np.ones(fg_masks[0].shape[:2], dtype=np.uint8))) collage = imvis.make_collage(fg_masks, padding=padding, fixed_size_per_image=(200, 266), bg_color=(0, 0, 0, 0), num_images_per_row=2) input_seq = cv2.resize(imutils.imread('../data/ninja-seq.png'), (200, 266)) collage = imvis.make_collage([input_seq, collage], padding=padding, bg_color=(0, 0, 0, 0)) # Overlay names height, width = collage.shape[:2] collage = imvis.draw_text_box(collage, 'Input', (input_seq.shape[1]/2, height/3+20), text_anchor='center', bg_color=(255, 255, 255), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.8) names = [bg.name() for bg in bgmodels] mask_width = (width-input_seq.shape[1] - padding) / 2 for i in range(len(names)): pos = (input_seq.shape[1] + padding + (i % 2) * (mask_width + padding) + mask_width/2, (i // 2) * (266 + padding) + 266 - 10) collage = imvis.draw_text_box(collage, names[i], pos, text_anchor='south', bg_color=(255, 255, 255), font_color=(-1, -1, -1), font_scale=1.0, font_thickness=1, padding=5, fill_opacity=0.8) imvis.imshow(collage, title="Background Subtraction", wait_ms=-1) imutils.imsave('../../doc/example-bgm.png', collage)