def overlap(topics, emotions, icons, colors, size, background=(255, 255, 255), icon_ratio=0.1, size_flux=0.25, rand_alpha=True, passes=10, mask_all=True, border_shape=False, border_color=None, inc_floor=.5, inc_ceiling=.75, text=True, **kwargs): """ Overlap visualization. :param topics: Topics to use (list). :param emotions: Emotions to use (list). :param icons: Shape icons (dict). :param colors: Emotion colors (dict). :param background: Background color in RGB (tuple). :param border_shape: Whether to apply icon shape as border (bool). :param border_color: Border color in RGB (tuple). :param text: Include text labels below visualization (bool). :param icon_ratio: Ratio of small shape sizes to overall image size (float). :param size_flux: Standard deviation by which small shapes vary in size (float). :param rand_alpha: Randomly adjust opacity of each shape placed (float). :param passes: Number of overlapping passes (int). :param mask_all: Opacity mask for individual small shapes (bool). :param inc_floor: Minimum step size in placing new shape (float). :param inc_ceiling: Maximum step size in placing new shape (float). :param kwargs: Additional arguments (dict). :return: Visualization (array). """ if len(topics) == 0 or len(emotions) == 0: return None elif topics[0] is None: border_shape = False elif not set(topics) <= set(icons.keys()): return 'Error: Topics outside of presets.' elif not set(emotions) <= set(colors.keys()): return 'Error: Emotions outside of presets.' start_size = ( 500, 500 ) # Start here because smaller values run into issues with sub-shape masking base_size = int(min(start_size) * icon_ratio) if topics[0] is None: icons_resized = np.ones((base_size, base_size)) * 255 border_points = np.concatenate( (np.column_stack( (np.zeros(base_size), np.array(np.arange(0, base_size)))), np.column_stack((np.ones(base_size) * (base_size - 1), np.array(np.arange(0, base_size)))), np.column_stack( (np.array(np.arange(0, base_size)), np.zeros(base_size))), np.column_stack( (np.array(np.arange(0, base_size)), np.ones(base_size) * (base_size - 1))))).astype(int) icons_resized[border_points[:, 0], border_points[:, 1]] = 0 icons_resized = [icons_resized] else: icons_resized = [ cv2.resize(icons[topic], (base_size, base_size)) for topic in topics ] colors_list = [colors[emotion] for emotion in emotions] color_icons = [ fill_color(icon, color['rgb'], border_color) for icon, color in product(icons_resized, colors_list) ] canvas = np.zeros((start_size[0], start_size[1], 3)) canvas[..., :] = background for p in range(passes): complete = False start = [ random.randint(0, base_size // 4), random.randint(0, base_size // 4) ] while not complete: icon, icon_size = random.choice(color_icons), max( 1, int(base_size * np.random.normal(1, size_flux))) icon_resized = cv2.resize(icon, (icon_size, icon_size), interpolation=cv2.INTER_NEAREST) adj_y = min(int(start[0] * np.random.normal(1, .025)), start_size[0] - icon_size) mask = bg_mask(icon_resized, colors_list, border_color) if mask_all else None increment = random.randint(int(inc_floor * icon_size), int(icon_size * inc_ceiling)) alpha = random.random() if rand_alpha else 0 if start[1] + icon_size < canvas.shape[1]: canvas = fill_canvas(canvas, background, mask, start_size, icon_resized, start, adj_y, icon_size, alpha) start[1] += increment elif start[0] + icon_size < canvas.shape[0]: start[0] += increment start[1] = increment canvas = fill_canvas(canvas, background, mask, start_size, icon_resized, start, adj_y, icon_size, alpha) else: complete = True if border_shape: canvas = apply_shape(canvas, icons, topics, start_size, border_color, background) canvas = cv2.resize(canvas, size) if text: canvas = add_labels(canvas, topics, emotions, colors) return canvas
def string(topics, emotions, icons, colors, size, background=(255, 255, 255), n_lines=150, line_width_string=5, border_shape=True, border_color=None, text=True, offset_sd=0.2, **kwargs): """ String doll visualization. :param topics: Topics to use (list). :param emotions: Emotions to use (list). :param icons: Shape icons (dict). :param colors: Emotion colors (dict). :param background: Background color in RGB (tuple). :param border_shape: Whether to apply icon shape as border (bool). :param border_color: Border color in RGB (tuple). :param text: Include text labels below visualization (bool). :param n_lines: Number of lines drawn (int). :param line_width_string: Width of lines (int). :param offset_sd: Standard deviation of offset for arc (float). :param kwargs: Additional arguments (dict). :return: Visualization (array). """ if len(topics) == 0 or len(emotions) == 0: return None elif topics[0] is None: border_shape = False elif not set(topics) <= set(icons.keys()): return 'Error: Topics outside of presets.' elif not set(emotions) <= set(colors.keys()): return 'Error: Emotions outside of presets.' colors_list = [colors[emotion] for emotion in emotions] canvas = np.zeros((size[0], size[1], 3)) canvas[..., :] = background # Get coordinates of shape boundaries to start and end curves if border_shape: # Load a boolean mask indicating outline region bool_mask = shape_bool_mask(icons, topics, size, border_color)[..., 0] canvas[bool_mask] = (245, 245, 245) border = cv2.resize(icons[topics[0]], size) / 255 border_points = np.argwhere(~border.astype(bool)).tolist() else: border_points = np.concatenate( (np.column_stack( (np.zeros(size[0]), np.array(np.arange(0, size[1])))), np.column_stack((np.ones(size[0]) * (size[0] - 1), np.array(np.arange(0, size[1])))), np.column_stack( (np.array(np.arange(0, size[0])), np.zeros(size[1]))), np.column_stack((np.array(np.arange(0, size[0])), np.ones(size[1]) * (size[1] - 1))))) border_points = border_points.tolist() # For n number of curves, select arbitrary start and end point on boundary, then one random midpoints for line in range(n_lines): start, end = random.sample(border_points, 1)[0], random.sample(border_points, 1)[0] offset = np.random.normal(scale=offset_sd) mid1 = np.array([start[0] / 2 + end[0] / 2, start[1] / 2 + end[1] / 2 ]) * (1 + offset) points = [start, mid1, end] nPoints = len(points) xPoints = np.array([p[1] for p in points]) yPoints = np.array([p[0] for p in points]) t = np.linspace(0.0, 1.0, 50) polynomial_array = np.array([ comb(nPoints - 1, i) * (t**(nPoints - 1 - i)) * (1 - t)**i for i in range(0, nPoints) ]) xvals = np.dot(xPoints, polynomial_array)[:, None] yvals = np.dot(yPoints, polynomial_array)[:, None] curve_points = np.concatenate((xvals, yvals), axis=1).astype(np.int32)[None, ...] color = np.random.choice(colors_list)['rgb'] cv2.polylines(canvas, curve_points, False, [color[2], color[1], color[0]], line_width_string, lineType=cv2.LINE_AA) cv2.polylines( canvas, curve_points, False, [int(color[2] * 1.5), int(color[1] * 1.5), int(color[0] * 1.5)], 1, lineType=cv2.LINE_AA) if border_shape: canvas = apply_shape(canvas, icons, topics, size, border_color, background) if text: canvas = add_labels(canvas, topics, emotions, colors) return canvas
def tiles(topics, emotions, icons, colors, size, background=(255, 255, 255), border_shape=True, border_color=None, text=True, line_width_tile=1, step_size=10, dir_prob=0.5, **kwargs): """ Tile visualization. :param topics: Topics to use (list). :param emotions: Emotions to use (list). :param icons: Shape icons (dict). :param colors: Emotion colors (dict). :param background: Background color in RGB (tuple). :param border_shape: Whether to apply icon shape as border (bool). :param border_color: Border color in RGB (tuple). :param text: Include text labels below visualization (bool). :param line_width_tile: Line width (int). :param step_size: Step size separating lines (int). :param dir_prob: Probability of choosing first direction (float). :param kwargs: Additional arguments (dict). :return: Visualization (array). """ if len(topics) == 0 or len(emotions) == 0: return None elif topics[0] is None: border_shape = False elif not set(topics) <= set(icons.keys()): return 'Error: Topics outside of presets.' elif not set(emotions) <= set(colors.keys()): return 'Error: Emotions outside of presets.' colors_list = [colors[emotion] for emotion in emotions] # Draw lines canvas = np.ones((size[0], size[1], 3)) for i in range(0, size[0], step_size): for j in range(0, size[1], step_size): if random.uniform(0, 1) > dir_prob: cv2.line(canvas, (j, i), (j + step_size, i + step_size), (0, 0, 0), line_width_tile) else: cv2.line(canvas, (j, i + step_size), (j + step_size, i), (0, 0, 0), line_width_tile) canvas = np.uint8(canvas[..., 0]) # Find connected components connections = measure.regionprops(measure.label(canvas, connectivity=1)) # Canvas for output canvas = np.zeros((size[0], size[1], 3)) canvas[..., :] = background for component in connections: fill = random.choice(colors_list)['rgb'] canvas[component.coords[:, 0], component.coords[:, 1]] = [fill[2], fill[1], fill[0]] del connections gc.collect() if border_shape: canvas = apply_shape(canvas, icons, topics, size, border_color, background) if text: canvas = add_labels(canvas, topics, emotions, colors) return canvas
def circle(topics, emotions, icons, colors, size, background=(255, 255, 255), min_rad_factor=.01, max_rad_factor=.09, n_circles=100, max_attempts=100, border_shape=True, border_color=None, border_width=1, text=True, **kwargs): """ Circle packing visualization. :param topics: Topics to use (list). :param emotions: Emotions to use (list). :param icons: Shape icons (dict). :param colors: Emotion colors (dict). :param size: Size of output (tuple). :param background: Background color in RGB (tuple). :param border_shape: Whether to apply icon shape as border (bool). :param border_color: Border color in RGB (tuple). :param text: Include text labels below visualization (bool). :param min_rad_factor: Minimum ratio of circle radius to image size (float). :param max_rad_factor: Maximum ratio of circle radius to image size (float). :param n_circles: Number of circles (int). :param max_attempts: Maximum number of attempts to place each circle (int). :param border_width: Circle border width (int). :param kwargs: Additional arguments (dict). :return: Visualization (array). """ if len(topics) == 0 or len(emotions) == 0: return None elif topics[0] is None: border_shape = False elif not set(topics) <= set(icons.keys()): return 'Error: Topics outside of presets.' elif not set(emotions) <= set(colors.keys()): return 'Error: Emotions outside of presets.' colors_list = [colors[emotion] for emotion in emotions] canvas = np.zeros((size[0], size[1], 3)) canvas[..., :] = background if topics[0] is None: bool_mask = np.ones((size[0], size[1])).astype(bool) min_row, max_row = 0, size[0] - 1 min_col, max_col = 0, size[1] - 1 else: # Load a boolean mask indicating whether each coordinate is within desired outline shape bool_mask = shape_bool_mask(icons, topics, size, border_color)[..., 0] interior_coords = np.argwhere(bool_mask) min_row, max_row = np.min(interior_coords[:, 0]), np.max( interior_coords[:, 0]) min_col, max_col = np.min(interior_coords[:, 1]), np.max( interior_coords[:, 1]) canvas[bool_mask] = (245, 245, 245) # Choose a set of random radii and sort by largest first min_rad, max_rad = min_rad_factor * size[0], max_rad_factor * size[0] circles_to_place = (min_rad + (max_rad - min_rad) * np.random.random(n_circles) * np.random.random(n_circles)).astype('int') circles_to_place[::-1].sort() # For each circle, X number of attempts to place it without going outside boundary or overlapping another circle can_place = bool_mask fail_count = 0 all_rows, all_cols = np.arange(size[0]), np.arange(size[1]) for r in circles_to_place: if fail_count < n_circles / 10: placed, try_idx = False, 0 row_try = np.random.uniform(min_row, max_row, max_attempts) col_try = np.random.uniform(min_col, max_col, max_attempts) try_coords = np.concatenate((row_try[:, None], col_try[:, None]), 1).astype('int') while not placed and try_idx < max_attempts: try_center = try_coords[try_idx] # Get coordinates of circle with given center and radius spacing_mask = (all_cols[None, :] - try_center[1]) ** 2 + \ (all_rows[:, None] - try_center[0]) ** 2 < (r+border_width) ** 2 circle_mask = (all_cols[None, :] - try_center[1]) ** 2 + \ (all_rows[:, None] - try_center[0]) ** 2 < r ** 2 inner_mask = (all_cols[None, :] - try_center[1]) ** 2 + \ (all_rows[:, None] - try_center[0]) ** 2 < (r-border_width) ** 2 no_conflicts = np.all( np.logical_and(can_place, spacing_mask)[spacing_mask]) if no_conflicts: color = np.random.choice(colors_list)['rgb'] canvas[circle_mask] = [50, 50, 50] canvas[inner_mask] = [color[2], color[1], color[0]] can_place = np.logical_and(can_place, ~spacing_mask) placed = True fail_count = 0 else: try_idx += 1 fail_count += 1 if border_shape: canvas = apply_shape(canvas, icons, topics, size, border_color, background) if text: canvas = add_labels(canvas, topics, emotions, colors) return canvas
def ae(topics, emotions, icons, colors, size, in_size=16, background=(255, 255, 255), border_shape=False, border_color=None, text=True, intensity_sd=.2, **kwargs): """ Autoencoder visualization. :param topics: Topics to use (list). :param emotions: Emotions to use (list). :param icons: Shape icons (dict). :param colors: Emotion colors (dict). :param size: Size of output (tuple). :param in_size: Size of input, assuming square shape (int). :param background: Background color in RGB (tuple). :param border_shape: Whether to apply icon shape as border (bool). :param border_color: Border color in RGB (tuple). :param text: Include text labels below visualization (bool). :param intensity_sd: Standard deviation for random color intensity adjustment (float). :param kwargs: Additional arguments (dict). :return: Visualization (array). """ if len(topics) == 0 or len(emotions) == 0: return None elif topics[0] is None: border_shape = False elif not set(topics) <= set(icons.keys()): return 'Error: Topics outside of presets.' elif not set(emotions) <= set(colors.keys()): return 'Error: Emotions outside of presets.' colors_list = [colors[emotion]['rgb'] for emotion in emotions] canvas = np.ones((in_size, in_size, 3)) coords = np.reshape( np.indices((in_size, in_size)).transpose((1, 2, 0)), (in_size * in_size, 2)) np.random.shuffle(coords) coords_split = np.array_split(coords, len(colors_list)) for idx, c in enumerate(colors_list): canvas[coords_split[idx][:, 0], coords_split[idx][:, 1]] = c[::-1] canvas[coords_split[idx][:, 0], coords_split[idx][:, 1]] *= np.random.normal( loc=1, scale=intensity_sd, size=(canvas[coords_split[idx][:, 0], coords_split[idx][:, 1]].shape)) img_proc = np.asarray(canvas, dtype='float32')[None, ...] img_proc = (img_proc / 127.5 - 1.0).astype(np.float32) with session.as_default(): with session.graph.as_default(): img_out = dec_model.predict(enc_model.predict(img_proc, batch_size=1), batch_size=1) img_out = (img_out[0, ..., :3] * 127.5 + 127.5).astype(np.uint8) if border_shape: img_out = apply_shape(img_out, icons, topics, size, border_color, background) if text: img_out = add_labels(img_out, topics, emotions, colors) return img_out
def carpet(topics, emotions, icons, colors, size, background=(255, 255, 255), border_shape=True, border_color=None, text=True, tile_ratio=.1, line_width=1, rotations=4, rot_degree=45, num_lines=3, **kwargs): """ Carpet visualization. :param topics: Topics to use (list). :param emotions: Emotions to use (list). :param icons: Shape icons (dict). :param colors: Emotion colors (dict). :param size: Size of output (tuple). :param background: Background color in RGB (tuple). :param border_shape: Whether to apply icon shape as border (bool). :param border_color: Border color in RGB (tuple). :param text: Include text labels below visualization (bool). :param tile_ratio: Ratio of tile sizes to overall image size (float). :param line_width: Width of lines drawn (int). :param rotations: Number of rotations for lines (int). :param rot_degree: Degree of rotations for lines (int). :param num_lines: Number of lines (int). :param kwargs: Additional arguments (dict). :return: Visualization (array). """ if len(topics) == 0 or len(emotions) == 0: return None elif topics[0] is None: border_shape = False elif not set(topics) <= set(icons.keys()): return 'Error: Topics outside of presets.' elif not set(emotions) <= set(colors.keys()): return 'Error: Emotions outside of presets.' colors_list = [colors[emotion] for emotion in emotions] canvas = np.zeros((size[0], size[1], 3)) canvas[..., :] = background tile_size = int(size[0]*tile_ratio) num_tiles = (int(size[0]/tile_size), int(size[1]/tile_size)) line_array = np.linspace(0, tile_size, num_lines)[:, None] for i in range(num_tiles[0]): for j in range(num_tiles[1]): x_start = j*tile_size y_start = i*tile_size all_start = np.int32(line_array + [x_start, y_start]) angle = random.choice(range(0, rotations*rot_degree, rot_degree)) for line in range(num_lines): if angle == 0: start = (all_start[0, 0], all_start[line, 1]) end = (all_start[num_lines-1, 0], all_start[line, 1]) elif angle == rot_degree: if line < num_lines - 1: start = (all_start[0, 0], all_start[num_lines-1-line, 1]) end = (all_start[line+1, 0], all_start[num_lines-1, 1]) elif 0 < line < num_lines - 1: start2 = (all_start[line, 0], all_start[0, 1]) end2 = (all_start[num_lines-1, 0], all_start[num_lines-line, 1]) cv2.line(canvas, start2, end2, (0, 0, 0), line_width) elif angle == rot_degree*2: start = (all_start[line, 0], all_start[0, 1]) end = (all_start[line, 0], all_start[num_lines-1, 1]) elif angle == rot_degree*3: if line < num_lines - 1: start = (all_start[0, 0], all_start[line+1, 1]) end = (all_start[line+1, 0], all_start[0, 1]) elif 0 < line < num_lines - 1: start2 = (all_start[line, 0], all_start[num_lines-1, 1]) end2 = (all_start[num_lines-1, 0], all_start[line, 1]) cv2.line(canvas, start2, end2, (0, 0, 0), line_width) cv2.line(canvas, start, end, (0, 0, 0), line_width) canvas = np.uint8(canvas[..., 0]) # Find connected components connections = measure.regionprops(measure.label(canvas, connectivity=1)) # Canvas for output canvas = np.zeros((size[0], size[1], 3)) canvas[..., :] = background for component in connections: fill = random.choice(colors_list)['rgb'] canvas[component.coords[:, 0], component.coords[:, 1]] = [fill[2], fill[1], fill[0]] del connections gc.collect() if border_shape: canvas = apply_shape(canvas, icons, topics, size, border_color, background) if text: canvas = add_labels(canvas, topics, emotions, colors) return canvas