Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import torch | |
| def disp_color_func(disp): | |
| """ | |
| Based on color histogram, convert the gray disp into color disp map. | |
| The histogram consists of 7 bins, value of each is e.g. [114.0, 185.0, 114.0, 174.0, 114.0, 185.0, 114.0] | |
| Accumulate each bin, named cbins, and scale it to [0,1], e.g. [0.114, 0.299, 0.413, 0.587, 0.701, 0.886, 1.0] | |
| For each value in disp, we have to find which bin it belongs to | |
| Therefore, we have to compare it with every value in cbins | |
| Finally, we have to get the ratio of it accounts for the bin, and then we can interpolate it with the histogram map | |
| For example, 0.780 belongs to the 5th bin, the ratio is (0.780-0.701)/0.114, | |
| then we can interpolate it into 3 channel with the 5th [0, 1, 0] and 6th [0, 1, 1] channel-map | |
| Inputs: | |
| disp: numpy array, disparity gray map in (Height * Width, 1) layout, value range [0,1] | |
| Outputs: | |
| disp: numpy array, disparity color map in (Height * Width, 3) layout, value range [0,1] | |
| """ | |
| map = np.array([ | |
| [0, 0, 0, 114], | |
| [0, 0, 1, 185], | |
| [1, 0, 0, 114], | |
| [1, 0, 1, 174], | |
| [0, 1, 0, 114], | |
| [0, 1, 1, 185], | |
| [1, 1, 0, 114], | |
| [1, 1, 1, 0] | |
| ]) | |
| # grab the last element of each column and convert into float type, e.g. 114 -> 114.0 | |
| # the final result: [114.0, 185.0, 114.0, 174.0, 114.0, 185.0, 114.0] | |
| bins = map[0:map.shape[0] - 1, map.shape[1] - 1].astype(float) | |
| # reshape the bins from [7] into [7,1] | |
| bins = bins.reshape((bins.shape[0], 1)) | |
| # accumulate element in bins, and get [114.0, 299.0, 413.0, 587.0, 701.0, 886.0, 1000.0] | |
| cbins = np.cumsum(bins) | |
| # divide the last element in cbins, e.g. 1000.0 | |
| bins = bins / cbins[cbins.shape[0] - 1] | |
| # divide the last element of cbins, e.g. 1000.0, and reshape it, final shape [6,1] | |
| cbins = cbins[0:cbins.shape[0] - 1] / cbins[cbins.shape[0] - 1] | |
| cbins = cbins.reshape((cbins.shape[0], 1)) | |
| # transpose disp array, and repeat disp 6 times in axis-0, 1 times in axis-1, final shape=[6, Height*Width] | |
| ind = np.tile(disp.T, (6, 1)) | |
| tmp = np.tile(cbins, (1, disp.size)) | |
| # get the number of disp's elements bigger than each value in cbins, and sum up the 6 numbers | |
| b = (ind > tmp).astype(int) | |
| s = np.sum(b, axis=0) | |
| bins = 1 / bins | |
| # add an element 0 ahead of cbins, [0, cbins] | |
| t = cbins | |
| cbins = np.zeros((cbins.size + 1, 1)) | |
| cbins[1:] = t | |
| # get the ratio and interpolate it | |
| disp = (disp - cbins[s]) * bins[s] | |
| disp = map[s, 0:3] * np.tile(1 - disp, (1, 3)) + map[s + 1, 0:3] * np.tile(disp, (1, 3)) | |
| return disp | |
| def gen_disp_error_colormap(): | |
| """ | |
| format:[[min_error<= this_error<=max_error, RGB], | |
| [min_error<= this_error<=max_error, RGB], | |
| ... | |
| [min_error<= this_error<=max_error, RGB],] | |
| unit: pixel | |
| """ | |
| cols = np.array( | |
| [[0 / 3.0, 0.1875 / 3.0, 49, 54, 149], | |
| [0.1875 / 3.0, 0.375 / 3.0, 69, 117, 180], | |
| [0.375 / 3.0, 0.75 / 3.0, 116, 173, 209], | |
| [0.75 / 3.0, 1.5 / 3.0, 171, 217, 233], | |
| [1.5 / 3.0, 3 / 3.0, 224, 243, 248], | |
| [3 / 3.0, 6 / 3.0, 254, 224, 144], | |
| [6 / 3.0, 12 / 3.0, 253, 174, 97], | |
| [12 / 3.0, 24 / 3.0, 244, 109, 67], | |
| [24 / 3.0, 48 / 3.0, 215, 48, 39], | |
| [48 / 3.0, np.inf, 165, 0, 38]], dtype=np.float32) | |
| cols[:, 2: 5] /= 255. | |
| return cols | |
| error_colormap = gen_disp_error_colormap() | |
| def disp_error_image_func(D_est_tensor, D_gt_tensor, abs_thres=3., rel_thres=0.05, dilate_radius=1): | |
| """ | |
| D_est_tensor: estimated disparity, BHW | |
| D_gt_tensor: ground-truth disparity, BHW | |
| abs_thres: abs(D_est - D_gt) > abs_thres? outliers : zeros | |
| """ | |
| D_gt_np = D_gt_tensor.detach().cpu().numpy() | |
| D_est_np = D_est_tensor.detach().cpu().numpy() | |
| B, H, W = D_gt_np.shape | |
| # valid mask | |
| mask = D_gt_np > 1e-3 | |
| # error in percentage. When error <= 1, the pixel is valid since <= 3px & 5% | |
| error = np.abs(D_gt_np - D_est_np) | |
| error[np.logical_not(mask)] = 0 # remove the invalid pixels | |
| error[mask] = np.minimum(error[mask] / abs_thres, (error[mask] / D_gt_np[mask]) / rel_thres) | |
| # get colormap | |
| cols = error_colormap | |
| # create error image | |
| error_image = np.zeros([B, H, W, 3], dtype=np.float32) | |
| for i in range(cols.shape[0]): | |
| error_image[np.logical_and(error >= cols[i][0], error < cols[i][1])] = cols[i, 2:] # find out the correspondant range, give RGB values | |
| # TODO: imdilate | |
| # error_image = cv2.imdilate(D_err, strel('disk', dilate_radius)); | |
| # remove the color in invalid pixels | |
| error_image[np.logical_not(mask)] = 0. | |
| # show color tag in the top-left cornor of the image | |
| for i in range(cols.shape[0]): | |
| distance = 20 | |
| error_image[:, :10, i * distance:(i + 1) * distance, :] = cols[i, 2:] | |
| return torch.from_numpy(np.ascontiguousarray(error_image.transpose([0, 3, 1, 2]))) | |
| def gen_dep_error_colormap(max_range=2): | |
| """ | |
| format:[[min_error<= this_error<=max_error, RGB], | |
| [min_error<= this_error<=max_error, RGB], | |
| ... | |
| [min_error<= this_error<=max_error, RGB],] | |
| unit: meter | |
| range: (0, max_range) meters | |
| """ | |
| max_range = max_range / 0.9 | |
| cols = np.array( | |
| [[0.0 * max_range, 0.1 * max_range, 49, 54, 149], | |
| [0.1 * max_range, 0.2 * max_range, 69, 117, 180], | |
| [0.2 * max_range, 0.3 * max_range, 116, 173, 209], | |
| [0.3 * max_range, 0.4 * max_range, 171, 217, 233], | |
| [0.4 * max_range, 0.5 * max_range, 224, 243, 248], | |
| [0.5 * max_range, 0.6 * max_range, 254, 224, 144], | |
| [0.6 * max_range, 0.7 * max_range, 253, 174, 97], | |
| [0.7 * max_range, 0.8 * max_range, 244, 109, 67], | |
| [0.8 * max_range, 0.9 * max_range, 215, 48, 39], | |
| [0.9 * max_range, np.inf, 165, 0, 38]], dtype=np.float32) | |
| cols[:, 2: 5] /= 255. | |
| return cols | |
| dep_error_colormap = gen_dep_error_colormap(max_range=2.) | |
| def dep_error_image_func(D_est_tensor, D_gt_tensor): | |
| """ | |
| D_est_tensor: estimated depth, BHW | |
| D_gt_tensor: ground-truth depth, BHW | |
| abs_thres: abs(D_est - D_gt) > abs_thres? outliers : zeros | |
| """ | |
| D_gt_np = D_gt_tensor.detach().cpu().numpy() | |
| D_est_np = D_est_tensor.detach().cpu().numpy() | |
| B, H, W = D_gt_np.shape | |
| # valid mask | |
| mask = D_gt_np > 1e-3 | |
| # error in percentage. When error <= 1, the pixel is valid since <= 3px & 5% | |
| error = np.abs(D_gt_np - D_est_np) | |
| error[np.logical_not(mask)] = 0 # remove the invalid pixels | |
| # get colormap | |
| cols = error_colormap | |
| # create error image | |
| error_image = np.zeros([B, H, W, 3], dtype=np.float32) | |
| for i in range(cols.shape[0]): | |
| error_image[np.logical_and(error >= cols[i][0], error < cols[i][1])] = cols[i, 2:] # find out the correspondant range, give RGB values | |
| # TODO: imdilate | |
| # error_image = cv2.imdilate(D_err, strel('disk', dilate_radius)); | |
| # remove the color in invalid pixels | |
| error_image[np.logical_not(mask)] = 0. | |
| # show color tag in the top-left cornor of the image | |
| for i in range(cols.shape[0]): | |
| distance = 20 | |
| error_image[:, :10, i * distance:(i + 1) * distance, :] = cols[i, 2:] | |
| return torch.from_numpy(np.ascontiguousarray(error_image.transpose([0, 3, 1, 2]))) |