def __init__(self, filter_size=None, warning=True, debug=True): ''' generate a class of filter ''' if debug: isimsize(filter_size), 'the filter size is not correct' self.debug = debug self.warning = warning self.weights = None
def imagecoor2cartesian_center(image_shape, debug=True): ''' given an image shape, return 2 functions which change the original image coordinate to centered cartesian coordinate system basically the origin is in the center of the image for example: if the image shape is (480, 640) and the top left point is (0, 0), after passing throught forward_map function, it returns (-320, 240) for the bottom right point (639, 479), it returns (319, -239) ''' if debug: isimsize(image_shape), 'input image shape is not correct' width, height = image_shape[1], image_shape[0] def forward_map(pts, debug=True): if debug: assert is2dpts(pts), 'input 2d point is not correct' assert pts[0] >= 0 and pts[0] < width and isinteger( pts[0] ), 'x coordinate is out of range %d should in [%d, %d)' % ( pts[0], 0, width) assert pts[1] >= 0 and pts[1] < height and isinteger( pts[1] ), 'y coordinate is out of range %d shoud in [%d, %d)' % ( pts[1], 0, height) car_pts = imagecoor2cartesian(pts, debug=debug) car_pts = np.array(car_pts) car_pts[ 0] += -width / 2 # shift x axis half length of width to the right car_pts[1] += height / 2 # shigt y axis hald length of height downside return (car_pts[0], car_pts[1]) def backward_map(pts, debug=True): if debug: assert is2dpts(pts), 'input 2d point is not correct' assert is2dpts(pts), 'input 2d point is not correct' assert pts[0] >= -width / 2 and pts[0] < width / 2 and isinteger( pts[0] ), 'x coordinate is out of range %d should in [%d, %d)' % ( pts[0], -width / 2, width / 2) assert pts[1] > -height / 2 and pts[1] <= height / 2 and isinteger( pts[1] ), 'y coordinate is out of range %d shoud in (%d, %d]' % ( pts[1], -height / 2, height / 2) pts = np.array(pts) pts[0] += width / 2 pts[1] += -height / 2 img_pts = cartesian2imagecoor(pts, debug=debug) return img_pts return forward_map, backward_map
def image_concatenate(input_image, target_size=[1600, 2560], grid_size=None, edge_factor=0.99, warning=True, debug=True): ''' concatenate a list of images automatically parameters: input_image: NHWC numpy image, uint8 or float32 target_size: a tuple or list or numpy array with 2 elements, for [H, W] grid_size: a tuple or list or numpy array with 2 elements, for [num_rows, num_cols] edge_factor: the margin between images after concatenation, bigger, the edge is smaller, [0, 1] outputs: image_merged: CHW uint8 numpy image with size of target_size ''' np_image, _ = safe_batch_image(input_image, warning=warning, debug=debug) if debug: assert isimsize(target_size), 'the input image size is not correct' if grid_size is not None: assert isimsize(grid_size), 'the input grid size is not correct' assert isscalar(edge_factor) and edge_factor <= 1 and edge_factor >= 0, 'the edge factor is not correct' num_images = np_image.shape[0] if grid_size is None: num_rows = int(np.sqrt(num_images)) num_cols = int(np.ceil(num_images * 1.0 / num_rows)) else: num_rows, num_cols = np.ceil(grid_size[0]), np.ceil(grid_size[1]) window_height, window_width = target_size[0], target_size[1] grid_height = int(window_height / num_rows) grid_width = int(window_width / num_cols) im_height = int(grid_height * edge_factor) im_width = int(grid_width * edge_factor) im_channel = np_image.shape[-1] # concatenate image_merged = np.zeros((window_height, window_width, im_channel), dtype='uint8') for image_index in range(num_images): image_tmp = np_image[image_index, :, :, :] image_tmp = image_resize(image_tmp, target_size=(im_height, im_width), warning=warning, debug=debug) rows_index = int(np.ceil((image_index + 1.0) / num_cols)) # 1-indexed cols_index = int(image_index + 1 - (rows_index - 1) * num_cols) # 1-indexed rows_start = int((rows_index - 1) * grid_height) # 0-indexed rows_end = int(rows_start + im_height) # 0-indexed cols_start = int((cols_index - 1) * grid_width) # 0-indexed cols_end = int(cols_start + im_width) # 0-indexed image_merged[rows_start:rows_end, cols_start:cols_end, :] = image_tmp return image_merged
def nparray_resize(input_nparray, resize_factor=None, target_size=None, interp='bicubic', warning=True, debug=True): ''' resize the numpy array given a resize factor (e.g., 0.25), or given a target size (height, width) e.g., the numpy array has 600 x 800: 1. given a resize factor of 0.25 -> results in an image with 150 x 200 2. given a target size of (300, 400) -> results in an image with 300 x 400 note that: resize_factor and target_size cannot exist at the same time parameters: input_nparray: a numpy array resize_factor: a scalar target_size: a list of tuple or numpy array with 2 elements, representing height and width interp: interpolation methods: bicubic or bilinear outputs: resized_nparray: a numpy array ''' np_array = safe_npdata(input_nparray, warning=warning, debug=debug) if debug: assert interp in ['bicubic', 'bilinear' ], 'the interpolation method is not correct' assert (resize_factor is not None and target_size is None) or ( resize_factor is None and target_size is not None), 'resize_factor and target_size cannot co-exist' if target_size is not None: if debug: assert isimsize( target_size), 'the input target size is not correct' target_width, target_height = int(round(target_size[1])), int( round(target_size[0])) elif resize_factor is not None: if debug: assert isscalar(resize_factor), 'the resize factor is not a scalar' height, width = np_array.shape[:2] target_width, target_height = int(round(resize_factor * width)), int( round(resize_factor * height)) else: assert False, 'the target_size and resize_factor do not exist' if interp == 'bicubic': resized_nparray = cv2.resize(np_array, (target_width, target_height), interpolation=cv2.INTER_CUBIC) elif interp == 'bilinear': resized_nparray = cv2.resize(np_array, (target_width, target_height), interpolation=cv2.INTER_LINEAR) else: assert False, 'interpolation is wrong' return resized_nparray
def generate_gaussian_heatmap(input_pts, image_size, std, warning=True, debug=True): ''' generate a heatmap based on the input points array, create a 2-D gaussian with given std around each points provided the mask is generated by the occlusion from the point array: only occlusion with -1 will be masked out 0 -> invisible points without location 1 -> visible points with location -1 -> visible points without location, masked parameters: input_pts: a list of 3 elements, a listoflist of 3 elements: e.g., [[1,2], [5,6], [0, 1]], a numpy array with shape or (3, N) or (3, ) image_size: a tuple or list of numpy array with 2 elements, representing (height, width) std: the standard deviation used for gaussian distribution outputs: masked_heatmap: numpy float32 multichannel numpy array, (height, width, num_pts + 1) mask_valid: numpy float32 multichannel numpy array, (1, 1, num_pts + 1) mask_visible: numpy float32 multichannel numpy array, (1, 1, num_pts + 1) ''' pts_array = safe_2dptsarray_occlusion(input_pts, warning=warning, debug=debug) if debug: assert isscalar(std), 'the standard deviation should be a scalar' assert isimsize(image_size), 'the image size is not correct' height, width = image_size[0], image_size[1] num_pts, threshold = pts_array.shape[1], 0.01 heatmap = np.fromfunction( lambda y, x, pts_id : ((x - pts_array[0, pts_id])**2 \ + (y - pts_array[1, pts_id])**2) \ / -2.0 / std / std, (height, width, num_pts), dtype=int) heatmap = np.exp(heatmap) valid = np.logical_or( pts_array[2, :] == 0, pts_array[2, :] == 1) # mask out invalid points with -1 in the third visible = pts_array[2, :] == 1 # mask out invalid and occuluded points mask_valid = np.ones((1, 1, num_pts + 1), dtype='float32') mask_valid[0, 0, :num_pts] = valid # never mask out the background channel mask_visible = np.ones((1, 1, num_pts + 1), dtype='float32') mask_visible[ 0, 0, :num_pts] = visible # never mask out the background channel # mask out the invalid channel heatmap[heatmap < threshold] = 0 # ceiling and flooring heatmap[heatmap > 1] = 1 masked_heatmap = heatmap * mask_valid[:, :, : num_pts] # (height, width, num_pts) background_label = 1 - np.amax( masked_heatmap, axis=2) # (height, width), maximize along the channel axis background_label[background_label < 0] = 0 # (height, width, 1) masked_heatmap = np.concatenate( (masked_heatmap, np.expand_dims(background_label, axis=2)), axis=2).astype('float32') return masked_heatmap, mask_valid, mask_visible
def image_resize(input_image, resize_factor=None, target_size=None, interp='bicubic', warning=True, debug=True): ''' resize the image given a resize factor (e.g., 0.25), or given a target size (height, width) e.g., the input image has 600 x 800: 1. given a resize factor of 0.25 -> results in an image with 150 x 200 2. given a target size of (300, 400) -> results in an image with 300 x 400 note that: resize_factor and target_size cannot exist at the same time parameters: input_image: an pil or numpy image resize_factor: a scalar target_size: a list of tuple or numpy array with 2 elements, representing height and width interp: interpolation methods: bicubic or bilinear outputs: resized_image: a numpy uint8 image ''' np_image, _ = safe_image(input_image, warning=warning, debug=debug) if isfloatimage(np_image): np_image = (np_image * 255.).astype('uint8') if debug: assert interp in ['bicubic', 'bilinear' ], 'the interpolation method is not correct' assert (resize_factor is not None and target_size is None) or ( resize_factor is None and target_size is not None), 'resize_factor and target_size cannot co-exist' if target_size is not None: if debug: assert isimsize( target_size), 'the input target size is not correct' target_width, target_height = int(round(target_size[1])), int( round(target_size[0])) if target_width == np_image.shape[ 1] and target_height == np_image.shape[0]: return np_image elif resize_factor is not None: if debug: assert isscalar( resize_factor ) and resize_factor > 0, 'the resize factor is not a scalar' if resize_factor == 1: return np_image # no resizing height, width = np_image.shape[:2] target_width, target_height = int(round(resize_factor * width)), int( round(resize_factor * height)) else: assert False, 'the target_size and resize_factor do not exist' if interp == 'bicubic': resized_image = cv2.resize(np_image, (target_width, target_height), interpolation=cv2.INTER_CUBIC) elif interp == 'bilinear': resized_image = cv2.resize(np_image, (target_width, target_height), interpolation=cv2.INTER_LINEAR) else: assert False, 'interpolation is wrong' return resized_image