Spaces:
Runtime error
Runtime error
| from PIL import Image, ImageOps | |
| import scipy.ndimage as ndimage | |
| import cv2 | |
| import random | |
| import numpy as np | |
| from scipy.ndimage.filters import maximum_filter | |
| from scipy import signal | |
| cv2.ocl.setUseOpenCL(False) | |
| def get_edge(data, blur=False): | |
| if blur: | |
| data = cv2.GaussianBlur(data, (3, 3), 1.) | |
| sobel = np.array([[1,0,-1],[2,0,-2],[1,0,-1]]).astype(np.float32) | |
| ch_edges = [] | |
| for k in range(data.shape[2]): | |
| edgex = signal.convolve2d(data[:,:,k], sobel, boundary='symm', mode='same') | |
| edgey = signal.convolve2d(data[:,:,k], sobel.T, boundary='symm', mode='same') | |
| ch_edges.append(np.sqrt(edgex**2 + edgey**2)) | |
| return sum(ch_edges) | |
| def get_max(score, bbox): | |
| u = max(0, bbox[0]) | |
| d = min(score.shape[0], bbox[1]) | |
| l = max(0, bbox[2]) | |
| r = min(score.shape[1], bbox[3]) | |
| return score[u:d,l:r].max() | |
| def nms(score, ks): | |
| assert ks % 2 == 1 | |
| ret_score = score.copy() | |
| maxpool = maximum_filter(score, footprint=np.ones((ks, ks))) | |
| ret_score[score < maxpool] = 0. | |
| return ret_score | |
| def image_flow_crop(img1, img2, flow, crop_size, phase): | |
| assert len(crop_size) == 2 | |
| pad_h = max(crop_size[0] - img1.height, 0) | |
| pad_w = max(crop_size[1] - img1.width, 0) | |
| pad_h_half = int(pad_h / 2) | |
| pad_w_half = int(pad_w / 2) | |
| if pad_h > 0 or pad_w > 0: | |
| flow_expand = np.zeros((img1.height + pad_h, img1.width + pad_w, 2), dtype=np.float32) | |
| flow_expand[pad_h_half:pad_h_half+img1.height, pad_w_half:pad_w_half+img1.width, :] = flow | |
| flow = flow_expand | |
| border = (pad_w_half, pad_h_half, pad_w - pad_w_half, pad_h - pad_h_half) | |
| img1 = ImageOps.expand(img1, border=border, fill=(0,0,0)) | |
| img2 = ImageOps.expand(img2, border=border, fill=(0,0,0)) | |
| if phase == 'train': | |
| hoff = int(np.random.rand() * (img1.height - crop_size[0])) | |
| woff = int(np.random.rand() * (img1.width - crop_size[1])) | |
| else: | |
| hoff = (img1.height - crop_size[0]) // 2 | |
| woff = (img1.width - crop_size[1]) // 2 | |
| img1 = img1.crop((woff, hoff, woff+crop_size[1], hoff+crop_size[0])) | |
| img2 = img2.crop((woff, hoff, woff+crop_size[1], hoff+crop_size[0])) | |
| flow = flow[hoff:hoff+crop_size[0], woff:woff+crop_size[1], :] | |
| offset = (hoff, woff) | |
| return img1, img2, flow, offset | |
| def image_crop(img, crop_size): | |
| pad_h = max(crop_size[0] - img.height, 0) | |
| pad_w = max(crop_size[1] - img.width, 0) | |
| pad_h_half = int(pad_h / 2) | |
| pad_w_half = int(pad_w / 2) | |
| if pad_h > 0 or pad_w > 0: | |
| border = (pad_w_half, pad_h_half, pad_w - pad_w_half, pad_h - pad_h_half) | |
| img = ImageOps.expand(img, border=border, fill=(0,0,0)) | |
| hoff = (img.height - crop_size[0]) // 2 | |
| woff = (img.width - crop_size[1]) // 2 | |
| return img.crop((woff, hoff, woff+crop_size[1], hoff+crop_size[0])), (pad_w_half, pad_h_half) | |
| def image_flow_resize(img1, img2, flow, short_size=None, long_size=None): | |
| assert (short_size is None) ^ (long_size is None) | |
| w, h = img1.width, img1.height | |
| if short_size is not None: | |
| if w < h: | |
| neww = short_size | |
| newh = int(short_size / float(w) * h) | |
| else: | |
| neww = int(short_size / float(h) * w) | |
| newh = short_size | |
| else: | |
| if w < h: | |
| neww = int(long_size / float(h) * w) | |
| newh = long_size | |
| else: | |
| neww = long_size | |
| newh = int(long_size / float(w) * h) | |
| img1 = img1.resize((neww, newh), Image.BICUBIC) | |
| img2 = img2.resize((neww, newh), Image.BICUBIC) | |
| ratio = float(newh) / h | |
| flow = cv2.resize(flow.copy(), (neww, newh), interpolation=cv2.INTER_LINEAR) * ratio | |
| return img1, img2, flow, ratio | |
| def image_resize(img, short_size=None, long_size=None): | |
| assert (short_size is None) ^ (long_size is None) | |
| w, h = img.width, img.height | |
| if short_size is not None: | |
| if w < h: | |
| neww = short_size | |
| newh = int(short_size / float(w) * h) | |
| else: | |
| neww = int(short_size / float(h) * w) | |
| newh = short_size | |
| else: | |
| if w < h: | |
| neww = int(long_size / float(h) * w) | |
| newh = long_size | |
| else: | |
| neww = long_size | |
| newh = int(long_size / float(w) * h) | |
| img = img.resize((neww, newh), Image.BICUBIC) | |
| return img, [w, h] | |
| def image_pose_crop(img, posemap, crop_size, scale): | |
| assert len(crop_size) == 2 | |
| assert crop_size[0] <= img.height | |
| assert crop_size[1] <= img.width | |
| hoff = (img.height - crop_size[0]) // 2 | |
| woff = (img.width - crop_size[1]) // 2 | |
| img = img.crop((woff, hoff, woff+crop_size[1], hoff+crop_size[0])) | |
| posemap = posemap[hoff//scale:hoff//scale+crop_size[0]//scale, woff//scale:woff//scale+crop_size[1]//scale,:] | |
| return img, posemap | |
| def neighbor_elim(ph, pw, d): | |
| valid = np.ones((len(ph))).astype(np.int) | |
| h_dist = np.fabs(np.tile(ph[:,np.newaxis], [1,len(ph)]) - np.tile(ph.T[np.newaxis,:], [len(ph),1])) | |
| w_dist = np.fabs(np.tile(pw[:,np.newaxis], [1,len(pw)]) - np.tile(pw.T[np.newaxis,:], [len(pw),1])) | |
| idx1, idx2 = np.where((h_dist < d) & (w_dist < d)) | |
| for i,j in zip(idx1, idx2): | |
| if valid[i] and valid[j] and i != j: | |
| if np.random.rand() > 0.5: | |
| valid[i] = 0 | |
| else: | |
| valid[j] = 0 | |
| valid_idx = np.where(valid==1) | |
| return ph[valid_idx], pw[valid_idx] | |
| def remove_border(mask): | |
| mask[0,:] = 0 | |
| mask[:,0] = 0 | |
| mask[mask.shape[0]-1,:] = 0 | |
| mask[:,mask.shape[1]-1] = 0 | |
| def flow_sampler(flow, strategy=['grid'], bg_ratio=1./6400, nms_ks=15, max_num_guide=-1, guidepoint=None): | |
| assert bg_ratio >= 0 and bg_ratio <= 1, "sampling ratio must be in (0, 1]" | |
| for s in strategy: | |
| assert s in ['grid', 'uniform', 'gradnms', 'watershed', 'single', 'full', 'specified'], "No such strategy: {}".format(s) | |
| h = flow.shape[0] | |
| w = flow.shape[1] | |
| ds = max(1, max(h, w) // 400) # reduce computation | |
| if 'full' in strategy: | |
| sparse = flow.copy() | |
| mask = np.ones(flow.shape, dtype=np.int) | |
| return sparse, mask | |
| pts_h = [] | |
| pts_w = [] | |
| if 'grid' in strategy: | |
| stride = int(np.sqrt(1./bg_ratio)) | |
| mesh_start_h = int((h - h // stride * stride) / 2) | |
| mesh_start_w = int((w - w // stride * stride) / 2) | |
| mesh = np.meshgrid(np.arange(mesh_start_h, h, stride), np.arange(mesh_start_w, w, stride)) | |
| pts_h.append(mesh[0].flat) | |
| pts_w.append(mesh[1].flat) | |
| if 'uniform' in strategy: | |
| pts_h.append(np.random.randint(0, h, int(bg_ratio * h * w))) | |
| pts_w.append(np.random.randint(0, w, int(bg_ratio * h * w))) | |
| if "gradnms" in strategy: | |
| ks = w // ds // 20 | |
| edge = get_edge(flow[::ds,::ds,:]) | |
| kernel = np.ones((ks, ks), dtype=np.float32) / (ks * ks) | |
| subkernel = np.ones((ks//2, ks//2), dtype=np.float32) / (ks//2 * ks//2) | |
| score = signal.convolve2d(edge, kernel, boundary='symm', mode='same') | |
| subscore = signal.convolve2d(edge, subkernel, boundary='symm', mode='same') | |
| score = score / score.max() - subscore / subscore.max() | |
| nms_res = nms(score, nms_ks) | |
| pth, ptw = np.where(nms_res > 0.1) | |
| pts_h.append(pth * ds) | |
| pts_w.append(ptw * ds) | |
| if "watershed" in strategy: | |
| edge = get_edge(flow[::ds,::ds,:]) | |
| edge /= max(edge.max(), 0.01) | |
| edge = (edge > 0.1).astype(np.float32) | |
| watershed = ndimage.distance_transform_edt(1-edge) | |
| nms_res = nms(watershed, nms_ks) | |
| remove_border(nms_res) | |
| pth, ptw = np.where(nms_res > 0) | |
| pth, ptw = neighbor_elim(pth, ptw, (nms_ks-1)/2) | |
| pts_h.append(pth * ds) | |
| pts_w.append(ptw * ds) | |
| if "single" in strategy: | |
| pth, ptw = np.where((flow[:,:,0] != 0) | (flow[:,:,1] != 0)) | |
| randidx = np.random.randint(len(pth)) | |
| pts_h.append(pth[randidx:randidx+1]) | |
| pts_w.append(ptw[randidx:randidx+1]) | |
| if 'specified' in strategy: | |
| assert guidepoint is not None, "if using \"specified\", switch \"with_info\" on." | |
| pts_h.append(guidepoint[:,1]) | |
| pts_w.append(guidepoint[:,0]) | |
| pts_h = np.concatenate(pts_h) | |
| pts_w = np.concatenate(pts_w) | |
| if max_num_guide == -1: | |
| max_num_guide = np.inf | |
| randsel = np.random.permutation(len(pts_h))[:len(pts_h)] | |
| selidx = randsel[np.arange(min(max_num_guide, len(randsel)))] | |
| pts_h = pts_h[selidx] | |
| pts_w = pts_w[selidx] | |
| sparse = np.zeros(flow.shape, dtype=flow.dtype) | |
| mask = np.zeros(flow.shape, dtype=np.int) | |
| sparse[:, :, 0][(pts_h, pts_w)] = flow[:, :, 0][(pts_h, pts_w)] | |
| sparse[:, :, 1][(pts_h, pts_w)] = flow[:, :, 1][(pts_h, pts_w)] | |
| mask[:,:,0][(pts_h, pts_w)] = 1 | |
| mask[:,:,1][(pts_h, pts_w)] = 1 | |
| return sparse, mask | |
| def image_flow_aug(img1, img2, flow, flip_horizon=True): | |
| if flip_horizon: | |
| if random.random() < 0.5: | |
| img1 = img1.transpose(Image.FLIP_LEFT_RIGHT) | |
| img2 = img2.transpose(Image.FLIP_LEFT_RIGHT) | |
| flow = flow[:,::-1,:].copy() | |
| flow[:,:,0] = -flow[:,:,0] | |
| return img1, img2, flow | |
| def flow_aug(flow, reverse=True, scale=True, rotate=True): | |
| if reverse: | |
| if random.random() < 0.5: | |
| flow = -flow | |
| if scale: | |
| rand_scale = random.uniform(0.5, 2.0) | |
| flow = flow * rand_scale | |
| if rotate and random.random() < 0.5: | |
| lengh = np.sqrt(np.square(flow[:,:,0]) + np.square(flow[:,:,1])) | |
| alpha = np.arctan(flow[:,:,1] / flow[:,:,0]) | |
| theta = random.uniform(0, np.pi*2) | |
| flow[:,:,0] = lengh * np.cos(alpha + theta) | |
| flow[:,:,1] = lengh * np.sin(alpha + theta) | |
| return flow | |
| def draw_gaussian(img, pt, sigma, type='Gaussian'): | |
| # Check that any part of the gaussian is in-bounds | |
| ul = [int(pt[0] - 3 * sigma), int(pt[1] - 3 * sigma)] | |
| br = [int(pt[0] + 3 * sigma + 1), int(pt[1] + 3 * sigma + 1)] | |
| if (ul[0] >= img.shape[1] or ul[1] >= img.shape[0] or | |
| br[0] < 0 or br[1] < 0): | |
| # If not, just return the image as is | |
| return img | |
| # Generate gaussian | |
| size = 6 * sigma + 1 | |
| x = np.arange(0, size, 1, float) | |
| y = x[:, np.newaxis] | |
| x0 = y0 = size // 2 | |
| # The gaussian is not normalized, we want the center value to equal 1 | |
| if type == 'Gaussian': | |
| g = np.exp(- ((x - x0) ** 2 + (y - y0) ** 2) / (2 * sigma ** 2)) | |
| elif type == 'Cauchy': | |
| g = sigma / (((x - x0) ** 2 + (y - y0) ** 2 + sigma ** 2) ** 1.5) | |
| # Usable gaussian range | |
| g_x = max(0, -ul[0]), min(br[0], img.shape[1]) - ul[0] | |
| g_y = max(0, -ul[1]), min(br[1], img.shape[0]) - ul[1] | |
| # Image range | |
| img_x = max(0, ul[0]), min(br[0], img.shape[1]) | |
| img_y = max(0, ul[1]), min(br[1], img.shape[0]) | |
| img[img_y[0]:img_y[1], img_x[0]:img_x[1]] = g[g_y[0]:g_y[1], g_x[0]:g_x[1]] | |
| return img | |