def __init__(self, shape, scale=1): """ Initalize a Warper with a reference shape with coordinates in the numpy array 'shape' """ xy = shape.copy() * scale self.scale = scale xy = self.shape_to_xy(xy) xy = xy - np.min(xy,axis=0) dt = scipy.spatial.Delaunay(xy) # Define a grid cols = int(np.ceil(np.max(xy[:,0]))) rows = int(np.ceil(np.max(xy[:,1]))) xx, yy = np.meshgrid(range(cols),range(rows)) xy_grid = np.vstack((xx.flatten(),yy.flatten())).T # Define a mask mask = Path(xy).contains_points(xy_grid) self.mask = mask.reshape(xx.shape) xy_grid = xy_grid[mask==True,:] # Remove pts not inside mask # Calculate barycentric coordinates for all points inside mask simplex_ids = dt.find_simplex(xy_grid) bary_coords = points_to_bary(dt,simplex_ids,xy_grid) self.tri = dt.simplices self.warp_template = np.hstack((simplex_ids[:,np.newaxis],bary_coords))
def to_grid(self): """ draw layout into a numpy array with indexes for https://stackoverflow.com/questions/3654289/scipy-create-2d-polygon-mask returns: ----- np.array(self._size).ntype(int) """ self._img_dict = {} nx, ny = self._size X = np.zeros((ny, nx)) mul = 256 // (self.__len__() - 1) # xmn, ymn, xmx, ymx = self._problem.footprint.bounds scale = self.get_scale_for_size(nx, ny) x, y = np.meshgrid(np.arange(nx), np.arange(ny)) x, y = x.flatten(), y.flatten() points = np.vstack((x, y)).T for i, room in enumerate(self.geoms): # generate color and add to dictionary icol = (i + 1) * mul self._img_dict = {room.name: icol} # create a patch on meshgrid vert = (np.array(list(room.exterior.coords)) * scale).astype(int) grid = Path(vert).contains_points(points, radius=0) grid = grid.reshape((ny, nx)) X[grid] += icol return np.flipud(X)
def write_mat(geoms, footprint, nx, ny): """ tensor of size [num_rooms, size omega.x, omega.y] """ scale = get_scale_for_size(footprint, nx, ny) x, y = np.meshgrid(np.arange(nx), np.arange(ny)) x, y = x.flatten(), y.flatten() points = np.vstack((x, y)).T X = np.zeros((len(geoms), nx, ny)) for i, room in enumerate(geoms): vert = (np.array(list(room.exterior.coords)) * scale).astype(int) grid = Path(vert).contains_points(points, radius=0) grid = grid.reshape((ny, nx)) X[i][grid] = 1. return np.flipud(X).copy()
def onLassoSelect(self, poly_verts): ny, nx = self.im.shape x, y = np.meshgrid(np.arange(nx), np.arange(ny)) x, y = x.flatten(), y.flatten() points = np.vstack((x, y)).T mask = Path(poly_verts).contains_points(points) mask = mask.reshape((ny, nx)) im = np.asarray(mpimg.imread(self.fns[self.i]), float) im[np.logical_not(mask)] = np.nan self.setimage(im)
def drawmap(plots, boundary=None): fig = plt.figure() ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) plt.title("科研楼出发省内X小时到达圈(高德)") bmap = Basemap(llcrnrlon=113, llcrnrlat=24, urcrnrlon=119, urcrnrlat=30.5, projection='mill', resolution='l', area_thresh=10000, ax=ax1) bmap.readshapefile('gadm36_CHN_1', 'states', drawbounds=False) bmap.drawcountries() for info, shp in zip(bmap.states_info, bmap.states): if info['NAME_1'] in ['Jiangxi']: boundary = shp if info['NAME_1'] in [ 'Fujian', 'Hunan', 'Hubei', 'Guangdong', 'Anhui', 'Zhejiang' ]: ax1.add_patch(Polygon(shp, facecolor='w', edgecolor='b', lw=0.2)) x, y = bmap(plots['经度'].values, plots['纬度'].values) mask = Path(boundary, closed=True).contains_points( pd.concat([pd.DataFrame(x), pd.DataFrame(y)], axis=1)) X, Y = np.meshgrid(m, n) X, Y = bmap(X, Y) Z = (plots['驾车耗时'].values / 1800).astype(np.int64).reshape(X.T.shape).T mask = mask.reshape(X.T.shape).T Z = Z * mask maxcount = max(Z.flatten()) mincount = min(Z.flatten()) cs = bmap.contourf(X, Y, Z, [*range(mincount, maxcount + 1)], cmap=plt.cm.jet) cbar = bmap.colorbar(cs) ticks = [str(i / 2.0) + "小时" for i in range(mincount, maxcount + 1)] cbar.set_ticklabels(ticks) cbar.set_ticks([*range(mincount, maxcount + 1)]) fig.savefig('target.jpg', format='jpg', dpi=300, transparent=True, bbox_inches='tight', pad_inches=0)
def polys_to_mask(mask_dict, coords, shape, radius=None, invert=False): """ Converts a mask definition in terms of the underlying polygon to a True/False mask array using the coordinates and shape of the target data. This process "specializes" a mask to a particular shape, whereas masks given by polygon definitions are general to any data with appropriate dimensions, because waypoints are given in unitful values rather than index values. :param mask_dict: :param coords: :param shape: :param radius: :param invert: :return: """ dims = mask_dict['dims'] polys = mask_dict['polys'] polys = [[[np.searchsorted(coords[dims[i]], coord) for i, coord in enumerate(p)] for p in poly] for poly in polys] mask_grids = np.meshgrid(*[np.arange(s) for s in shape]) mask_grids = tuple(k.flatten() for k in mask_grids) points = np.vstack(mask_grids).T mask = None for poly in polys: grid = Path(poly).contains_points(points, radius=radius or 0) grid = grid.reshape(list(shape)[::-1]).T if mask is None: mask = grid else: mask = np.logical_or(mask, grid) if invert: mask = np.logical_not(mask) return mask
def fill_polygon_for_raster(perimeter, rows=900, cols=2160, flip=True, closing={ 'close': False, 'struct': np.ones((4, 4)) }): '''Given the indices of the perimeter, returns the filled polygon (inclusive) Arguments: `perimeter`: points on perimeter (inorder preferable) `rows`: #rows `cols`: #columns `flip`: bool, flip final result `closing`: dict, required keys `'close'` (bool) & `'struct'` (2d iterable), perform binary closing on result ''' xs_2d, ys_2d = np.meshgrid(np.arange(rows), np.arange(cols)) xs_2d, ys_2d = xs_2d.flatten(), ys_2d.flatten() geo_points = np.vstack((xs_2d, ys_2d)).T grid = Path(perimeter).contains_points(geo_points) # np.flip(axis=0) to get [0,0] as top left point of raster grid = grid.reshape(cols, rows).T grid[([x for x, _ in perimeter], [y for _, y in perimeter])] = True if closing['close']: grid = binary_closing(grid, structure=closing['struct']) if flip: grid = np.flip(grid, 0) return grid
def setmask(self, im): """ input an image (for now an HDU) and set self.mask to an array the size of the image with the phot region =1 and expanded background annulus =2 for now we also create a mask the size of the image, so I recommend to extract a subimage and call this method with that input this method well trim the polyon to fit in the image """ imshape = im.shape mask = pl.zeros(imshape) if self.type == "circle": x, y, r = self.imcoords(im) x0 = int(x) y0 = int(y) dx = x - x0 dy = y - y0 # grr pixel centers again - is this right? # dx=dx-0.5; dy=dy-0.5 bg0_r = self.imcoords(im, reg="bg0")[2] #-0.2 # fudge bg1_r = self.imcoords(im, reg="bg1")[2] #+0.2 # fudge bg1_r0 = int(pl.ceil(bg1_r)) r2 = r**2 bg0_r2 = bg0_r**2 bg1_r2 = bg1_r**2 for i in pl.array(range(2 * bg1_r0 + 1)) - bg1_r0: for j in pl.array(range(2 * bg1_r0 + 1)) - bg1_r0: if y0 + j >= 0 and x0 + i >= 0 and y0 + j < ( imshape[0] - 1) and x0 + i < (imshape[1] - 1): d2 = (1. * i - dx)**2 + (1. * j - dy)**2 # d2 = (i-x)**2 + (j-y)**2 -> (i-x0-(x-x0))**2 + ... if d2 <= r2: mask[y0 + j, x0 + i] = 1 # remember indices inverted if d2 >= bg0_r2 and d2 <= bg1_r2: mask[y0 + j, x0 + i] = 2 # remember indices inverted # if x0+i==6: # print i,j,x0+i,y0+j,dx,dy,d2,bg0_r2,bg1_r2 elif self.type == "polygon": # turn annulus back into mask, will trim at edges of image from matplotlib.path import Path from matplotlib import __version__ as mpver v = mpver.split('.') if v[0] < 1: raise Exception( "need matplotlib >=1.3.1, or tell remy to add fallback nxutils option for Path.contains_points" ) elif v[1] < 3: raise Exception( "need matplotlib >=1.3.1, or tell remy to add fallback nxutils option for Path.contains_points" ) elif v[2] < 1: raise Exception( "need matplotlib >=1.3.1, or tell remy to add fallback nxutils option for Path.contains_points" ) # Create vertex coordinates for each grid cell x, y = pl.meshgrid(pl.arange(imshape[1]), pl.arange(imshape[0])) x, y = x.flatten(), y.flatten() points = pl.vstack((x, y)).T mask1 = Path(self.imcoords(im, reg="bg1")).contains_points(points) mask1 = mask1.reshape((imshape[0], imshape[1])) mask0 = Path(self.imcoords(im, reg="bg0")).contains_points(points) #,radius=1) mask0 = mask0.reshape((imshape[0], imshape[1])) mask = Path(self.imcoords(im, reg="ap")).contains_points(points) mask = mask.reshape((imshape[0], imshape[1])) mask = mask + (1 * mask1 - 1 * mask0) * 2 else: raise Exception("unknown region type %s" % self.type) self.mask = mask return mask