6 years, 11 months ago 2) I'm not using euclidean distance anywhere - the p=np.inf in query_ball_point means to use the infinity (a.k.a. I think your listcomp probably fails because in edge_idx will return a boolean array rather than a scalar, and arrays are "truthy". 6 years, 11 months ago 1) To get the non-border neighbours you could take the bitwise difference between the mask after eroding it once vs twice, e.g. #Sum elements in vstack array update6 years, 11 months ago Actually I have another issue concerning that task (see my update in the question). 6 years, 11 months ago Great! See my update for another suggestion that might help to speed things up, although if performance is really important to you then the fastest method is always going to be implementing your own filter in C/Cython etc. Nonzero_idx = np.vstack(np.where(candidate_neighbours)).Tġ0 6 years, 11 months ago Related Topics python numpy scipy Comments 6 years, 11 months ago Thank's for the detailed answer! I have never used a k-D tree before and I think it is also suitable for some other stuff I am working on. #Sum elements in vstack array plus# the edge pixels/voxels plus their immediate non-zero neighboursĮrode2 = ndimage.binary_erosion(erode, struct) The performance could be further improved by reducing the number of points that are considered as candidate neighbours of the edge pixels/voxels: #. I'm sure this isn't the most efficient way to do it, but it will still be significantly faster than using generic_filter. Result = ndimage.generic_filter(B, borderCheck, footprint=np.ones((3, 3, 3))) Test against your version: def borderCheck(values): Struct = ndimage.generate_binary_structure(3, 3) This approach will also generalize to the 3D case: B = np.random.randint(1, 5, size=(100, 100, 100)).astype(np.double) Some visualisation: fig, ax = plt.subplots(1, 3, figsize=(10, 4), sharex=True, sharey=True)Īx.set_title('Original', fontsize='x-large')Īx.set_title('Edges', fontsize='x-large')Īx.set_title('Averaged', fontsize='x-large') # use these to replace the values of the edge pixels New_vals = np.hstack(np.mean(nonzero_vals) for n in neighbours) # take the average value for each set of neighbours Neighbours = tree.query_ball_point(edge_idx, r=1, p=np.inf) # use it to find the indices of all non-zero values that are at most 1 pixel Nonzero_idx = np.vstack(np.where(mask)).T # the indices of the non-zero locations and their corresponding values One approach to find the nearest non-zero neighbours of each edge pixel would be to use a : from scipy.spatial import cKDTree Struct = ndimage.generate_binary_structure(2, 2)Įrode = ndimage.binary_erosion(mask, struct) #Sum elements in vstack array fullTo find the edge pixels you could perform binary erosion on your mask, then XOR the result with your mask # rank 2 structure with full connectivity I think it's best to start out with the 2D case first, since it can be visualized much more easily: import numpy as npĪ = np.random.randint(1, 5, size=(100, 100)).astype(np.double) Now I can't figure out why non_border_neighbours comes back empty?įurthermore, correct me if I am wrong but doesn't tree.query_ball_point with radius 1 adress only the 6 next neighbours (euclidean distance 1)? Should I set sqrt(3) (3D case) as radius to get the 26-neighbourhood? Non_border_neighbours.append( not in edge_idx]) #Sum elements in vstack array codeFor this, I tried to clean up the neighbours from ali_m's code (2D case): #for each neighbour voxel, check whether it also appears in the border/edges I messed one thing up: I would like to replace all border voxels with the mean of their nonzero AND non-border neighbours. Are there any other suitable (numpy, scipy ) functions that I can use? Is this a proper way to handle this problem? I feel that I am trying to reinvent the wheel here and that there must be a shorter, nicer way to achieve the result. Result = ndimage.generic_filter(array, borderCheck, footprint = np.ones((3,3,3))) Generic filter: from scipy import ndimage Return np.sum(values)/np.count_nonzero(values) #replace border voxels with the mean of nonzero neighbours #check if the footprint center is on a nonzero value So far I tried to use scipy's generic filter in the following way:įunction to apply at each element: def borderCheck(values): Second, I would like to replace all border voxels with the mean of their nonzero neighbours. As an example I will take a sphere of random values: array = np.random.randint(1, 5, size = (100,100,100))įirst, I would like to find the "border voxels" (all nonzero values that have a zero within their 3x3x3 neigbourhood). Suppose I have a 3D numpy array of nonzero values and "background" = 0.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |