def draw_ellipsoid(shape, radius, center, FWHM, noise=0): sigma = FWHM / 2.35482 cutoff = 2 * FWHM # draw a sphere R = max(radius) zoom_factor = np.array(radius) / R size = int((R + cutoff)*2) c = size // 2 z, y, x = np.meshgrid(*([np.arange(size)] * 3), indexing='ij') h = np.sqrt((z - c)**2+(y - c)**2+(x - c)**2) - R mask = np.abs(h) < cutoff im = np.zeros((size,)*3, dtype=np.float) im[mask] += np.exp((h[mask] / sigma)**2/-2)/(sigma*np.sqrt(2*np.pi)) # zoom so that radii are ok with warnings.catch_warnings(): warnings.simplefilter("ignore") im = zoom(im, zoom_factor) # shift and make correct shape center_diff = center - np.array(center_of_mass(im)) left_padding = np.round(center_diff).astype(np.int) subpx_shift = center_diff - left_padding im = shift(im, subpx_shift) im = crop_pad(im, -left_padding, shape) im[im < 0] = 0 assert_almost_equal(center_of_mass(im), center, decimal=2) if noise > 0: im += np.random.random(shape) * noise * im.max() return (im / im.max() * 255).astype(np.uint8)
def evaluate_bioid(loss, load_batch, n_batches): from scipy.ndimage.measurements import center_of_mass, maximum_position from numpy.linalg import norm L = [] for batch in xrange(n_batches()): load_batch(batch) output = loss.get_sink("output") out = output.evaluate().np target = loss.get_parameter("target") tch = target.data.np out = np.rollaxis(out, 3) for i in xrange(out.shape[0]): o0, o1 = out[i].reshape(2, 30, 30) t0, t1 = tch[i].reshape(2, 30, 30) mo0 = np.array(maximum_position(o0)) mo1 = np.array(maximum_position(o1)) mt0 = np.array(center_of_mass(t0)) mt1 = np.array(center_of_mass(t1)) mask0 = np.zeros_like(o0) mask1 = np.zeros_like(o1) region0 = np.clip((mo0 - 2, mo0 + 3), 0, 30) region1 = np.clip((mo1 - 2, mo1 + 3), 0, 30) mask0[region0[0, 0]:region0[1, 0], region0[0, 1]:region0[1, 1]] = 1 mask1[region1[0, 0]:region1[1, 0], region1[0, 1]:region1[1, 1]] = 1 mo0 = center_of_mass(o0, mask0) mo1 = center_of_mass(o1, mask1) dst = max(norm(mo0 - mt0), norm(mo1 - mt1)) / norm(mt0 - mt1) L.append(dst) L = np.array(L) print "n =", len(L) print "Average normalized distance: ", L.mean() print "Correct: ", np.sum(L < 0.25) / float(len(L))
def center_of_blob(img): if type(img) is list: centers = [] for blob in img: center = np.array([center_of_mass(blob)[i] for i in range(2)]) centers.append(center) return centers else: center = np.array([center_of_mass(img)[i] for i in range(2)]) return center
def process_eso(vol_out): print 'iterpolating eso...' voleso=vol_out==1 voleso=voleso.astype(np.uint8) idxesoini=np.where(voleso>0) id_eso=np.where(vol_out==1) seg_eso=np.zeros_like(vol_out) seg_eso[id_eso]=1 listorgan=np.where(seg_eso>0) zmin=np.min(listorgan[0]) zmax=np.max(listorgan[0]) ini_found=False for idx in xrange(zmin,zmax): eso_slice=seg_eso[idx] centroid=center_of_mass(eso_slice) if not ini_found:#if we have not found the first slice empty if np.isnan(centroid).any():#look for the first emppty slice #print 'is NAN ',idx ini=idx-1 pini=list(center_of_mass(seg_eso[idx-1])) pini.append(idx-1) ini_found=True else:#if we have already found the first empty slice, look for the final one idvox=np.where(eso_slice==1) nvoxels=len(idvox[0]) if not np.isnan(centroid).any() and nvoxels>5:#the slice with data and enough voxels #print 'final nan ',idx fin=idx pfin=list(center_of_mass(seg_eso[fin])) pfin.append(idx) #print 'pini ',pini #print 'pfin ',pfin for z in xrange(ini,fin):#we will fill the empty slices here newcenter=interpolateline(pini,pfin,z) #print 'new center ',newcenter #print 'prev center ',center_of_mass(seg_eso[z-1]) translation=np.int16(np.array(newcenter)-np.array(center_of_mass(seg_eso[z-1]))) #print 'trans ',translation #tx = tf.SimilarityTransform(translation=(0,0))#tuple(translation) if z==ini: slicetmp = shift(seg_eso[z-5],translation)#tf.warp(seg_eso[z-1], tx) else: slicetmp = shift(seg_eso[z-1],translation)#tf.warp(seg_eso[z-1], tx) #print 'unique slice befor trans ',np.unique(seg_eso[z-1]) #print 'unique slice tmp ',np.unique(slicetmp) seg_eso[z]=slicetmp ini_found=False idxeso=np.where(seg_eso>0) volfinal=np.copy(vol_out) volfinal[idxesoini]=0 volfinal[idxeso]=1 return volfinal
def find_phan_centers(self,params): """ Find the center of the phantom for the slices of analysis :return: """ self.slices_of_interest = ptg.find_slices_of_interest(self.images,params) print('haleluja!',self.slices_of_interest) for key in self.slices_of_interest: print ("curr SOI",key) #plt.imshow(self.images[self.slices_of_interest[key],:,:]) #plt.title("%s"%key) #plt.show() SOI = self.images[self.slices_of_interest[key],:,:] SOI = np.where(SOI > np.percentile(SOI,48), 1, 0) # convert slice to binary based on threshold #SOI = morph.binary_fill_holes(SOI) # fill in air pockets to make one solid ROI SOI_labeled, no_roi = meas.label(SOI) # identify the ROIs if no_roi < 1 or no_roi is None: raise ValueError, "Unable to locate the CatPhan" hist,bins = np.histogram(SOI_labeled,bins=no_roi) # hist will give the size of each label SOI = np.where(SOI_labeled == np.argmax(hist), 1, 0) # remove all ROIs except the largest one (the CatPhan) self.slice_centers[key] = meas.center_of_mass(SOI) self.SOI_cleaned[key] = SOI
def measure_barycenter(vignet, pixscale=1.): x,y = center_of_mass(vignet) x -= (vignet.shape[0]-1)/2 x *= pixscale y -= (vignet.shape[1]-1)/2 y *= pixscale return (x,y)
def find_roll(self): """ Determine the roll of the phantom based on the phantom air bubbles on the HU slice. :return: """ SOI = self.SOI_cleaned['HU'] invSOI = ptg.invert(SOI) labels, no_roi = meas.label(invSOI) roi_sizes = [meas.sum(invSOI, labels, index=item) for item in range(1,no_roi+1)] air_bubbles = [idx+1 for idx, item in enumerate(roi_sizes) if item < np.median(roi_sizes)*1.5 and item > np.median(roi_sizes)*(1/1.5)] if len(air_bubbles) != 2: self.phan_roll = 0 #raise RuntimeWarning, "Roll unable to be determined; assuming 0" else: air_bubble_CofM = meas.center_of_mass(invSOI, labels, air_bubbles) y_dist = air_bubble_CofM[0][0] - air_bubble_CofM[1][0] x_dist = air_bubble_CofM[0][1] - air_bubble_CofM[1][1] angle = np.arctan2(y_dist, x_dist) * 180/np.pi if angle < 0: roll = abs(angle) - 90 else: roll = angle - 90 self.phan_roll = roll self._roll_found = True
def fit_ellipse(img, full_output=False): img = np.array(img, dtype=float) center = center_of_mass(img) r = 10. x = np.arange(0., float(img.shape[1]), 1.) y = np.arange(0., float(img.shape[0]), 1.) X,Y = np.meshgrid(x, y) def fminfunc(vals): #center = [vals[0], vals[1]] a,b,angle = vals Z = ellipse(X, Y, center, a, b, angle) err = np.abs(img-Z) errsum = np.sum(err) #print errsum return errsum a = 20 b = 20 angle = np.pi/4 vals = [a,b,angle] tmp = scipy.optimize.fmin( fminfunc, vals, full_output = 1, disp=0) vals = tmp[0] #center = [vals[0], vals[1]] a,b,angle = vals if full_output is False: return center, a, b, angle else: Z = ellipse(X, Y, center, a, b, angle) return center, a, b, angle, Z
def align_image_on_cores_com(img, bg): finder_conf = wds.FinderConfiguration() finder_conf.set("max_scale", 2) finder_conf.set("min_scale", 1) finder_conf.set("interscales", False) group = wds.FeaturesFinder(img, bg, finder_conf).execute()[0] cmp_intensity = lambda x, y: cmp(x.get_intensity(), y.get_intensity()) brightest = group.sorted_list(cmp=cmp_intensity)[-1] cores = wfeatures.FeaturesGroup() # consider only features with total intensity > 10% of brightest one. for feature in group.get_features(): if feature.get_total_intensity() > 0.1 * brightest.get_total_intensity(): cores.add_feature(feature) img_cores = np.zeros_like(group.get_img().data) for core in cores: img_cores += core.get_segment_image() com = measurements.center_of_mass(img_cores) print "COM:", com return com
def get_coord_centroid(filename, region): """ Get centroid coordinates from an image and a region filename: fits file region: ds9 region """ import astropy.io.fits as pyfits import astropy.wcs as pywcs import pyregion from scipy.ndimage.measurements import center_of_mass fits = pyfits.open(filename) header, data = flatten(fits) # extract mask and find center of mass r = pyregion.open(region) mask = r.get_mask(header=header, shape=data.shape) dec_pix, ra_pix = center_of_mass(mask) # convert to ra/dec in angle w = pywcs.WCS(fits[0].header) #w = w.celestial # needs newer astropy ra, dec = w.all_pix2world(ra_pix, dec_pix, 0, 0, 0, ra_dec_order=True) fits.close() return float(ra), float(dec)
def calculateTestedClass(testedimg, classId): #img = Image.open(imgfile); img = testedimg npimg = np.array(img, dtype=np.uint8); filtereddataclasses = npimg #make sure to keep only needed class filtereddataclasses[npimg != classId] = 0 #find all connected components #smooth the image to remove small objects? blurradius = 0.5 #threshold = 0 if useSmoothed == 1: smoothedimg = ndimage.gaussian_filter(filtereddataclasses, blurradius) else: smoothedimg = filtereddataclasses labeled, nr_objects = ndimage.label(smoothedimg > 0) print 'Number of items (classid: ' + str(classId) + ') detected: ' + str(nr_objects) centreobjects = center_of_mass(labeled, labels=labeled, index=range(1, nr_objects+1)) return centreobjects # for each item, the format is y, x
def extract_sagital_slice(self): """Extract the sagital slice where the detection is done. If the segmentation is provided, the 2D sagital slice is choosen accoding to the segmentation. If the segmentation is not provided, the 2D sagital slice is choosen as the mid-sagital slice of the input image. """ if self.fname_seg is not None: img_seg = Image(self.fname_seg) z_mid_slice = img_seg.data[:, int(img_seg.dim[1] / 2), :] if 1 in z_mid_slice: # if SC segmentation available at this slice self.rl_coord = int(center_of_mass(z_mid_slice)[1]) # Right_left coordinate else: self.rl_coord = int(img_seg.dim[2] / 2) del img_seg else: img = Image(self.fname_im) self.rl_coord = int(img.dim[2] / 2) # Right_left coordinate del img sct.run(['sct_crop_image', '-i', self.fname_im, '-start', str(self.rl_coord), '-end', str(self.rl_coord), '-dim', '2', '-o', self.slice2D_im])
def segment_2d(model_fname, contrast_type, input_size, im_in): """Segment data using 2D convolutions.""" seg_model = nn_architecture_seg(height=input_size[0], width=input_size[1], depth=2 if contrast_type != 't2' else 3, features=32, batchnorm=False, dropout=0.0) seg_model.load_weights(model_fname) seg_crop = zeros_like(im_in, dtype=np.uint8) data_norm = im_in.data x_cOm, y_cOm = None, None for zz in range(im_in.dim[2]): pred_seg = seg_model.predict(np.expand_dims(np.expand_dims(data_norm[:, :, zz], -1), 0), batch_size=BATCH_SIZE)[0, :, :, 0] pred_seg_th = (pred_seg > 0.5).astype(int) pred_seg_pp = post_processing_slice_wise(pred_seg_th, x_cOm, y_cOm) seg_crop.data[:, :, zz] = pred_seg_pp if 1 in pred_seg_pp: x_cOm, y_cOm = center_of_mass(pred_seg_pp) x_cOm, y_cOm = np.round(x_cOm), np.round(y_cOm) return seg_crop.data
def crop_image_around_centerline(im_in, ctr_in, crop_size): """Crop the input image around the input centerline file.""" data_ctr = ctr_in.data data_ctr = data_ctr if len(data_ctr.shape) >= 3 else np.expand_dims(data_ctr, 2) data_in = im_in.data.astype(np.float32) im_new = empty_like(im_in) # but in fact we're going to crop it x_lst, y_lst, z_lst = [], [], [] data_im_new = np.zeros((crop_size, crop_size, im_in.dim[2])) for zz in range(im_in.dim[2]): if np.any(np.array(data_ctr[:, :, zz])): x_ctr, y_ctr = center_of_mass(np.array(data_ctr[:, :, zz])) x_start, x_end = _find_crop_start_end(x_ctr, crop_size, im_in.dim[0]) y_start, y_end = _find_crop_start_end(y_ctr, crop_size, im_in.dim[1]) crop_im = np.zeros((crop_size, crop_size)) x_shape, y_shape = data_in[x_start:x_end, y_start:y_end, zz].shape crop_im[:x_shape, :y_shape] = data_in[x_start:x_end, y_start:y_end, zz] data_im_new[:, :, zz] = crop_im x_lst.append(str(x_start)) y_lst.append(str(y_start)) z_lst.append(zz) im_new.data = data_im_new return x_lst, y_lst, z_lst, im_new
def find_sudoku_edges(im, axis=0): """ 寻找对齐后数独图像的的单元边线 """ # threshold and sum rows and columns #阈值化,像素值小于128的阈值处理后为1,大于128的为0 trim = 1*(128 > im) #阈值处理后对行(列)相加求和 s = trim.sum(axis=axis) print s # find center of strongest lines # 寻找连通区域 s_labels, s_nbr = measurements.label((0.5*max(s)) < s) print s_labels print s_nbr #计算各连通域的质心 m = measurements.center_of_mass(s, s_labels, range(1, s_nbr+1)) print m #对质心取整,质心即为粗线条所在位置 x = [int(x[0]) for x in m] print x # if only the strong lines are detected add lines in between # 如果检测到了粗线条,便在粗线条间添加直线 if 4 == len(x): dx = diff(x) x = [x[0], x[0]+dx[0]/3, x[0]+2*dx[0]/3, x[1], x[1]+dx[1]/3, x[1]+2*dx[1]/3, x[2], x[2]+dx[2]/3, x[2]+2*dx[2]/3, x[3]] if 10 == len(x): return x else: raise RuntimeError('Edges not detected.')
def vertical_stddev(image): """Compute the standard deviation in the vertical direction. This is used below to get a rough idea of how large characters and lines are.""" assert amax(image)>amin(image) cy,cx = measurements.center_of_mass(1.0*image) return (sum(((arange(len(image))-cy)[:,newaxis]*image)**2)/sum(image))**.5,cy,cx
def fit_circle(img): center = center_of_mass(img) r = 10 x = np.arange(0, img.shape[0], 1) y = np.arange(0, img.shape[1], 1) X,Y = np.meshgrid(x, y) def circle(x,y, center, r): R = np.sqrt((X-center[1])**2 + (Y-center[0])**2) Z = R<r Z *= 255 return Z def fminfunc(vals): #center = [vals[0], vals[1]] r = vals[0] Z = circle(X, Y, center, r) err = np.abs(img-Z) errsum = np.sum(err) #print errsum return errsum vals = [r] tmp = scipy.optimize.fmin( fminfunc, vals, full_output = 1, disp=0) vals = tmp[0] #center = [vals[0], vals[1]] r = vals[0] Z = circle(X, Y, center, r) return center, r, Z
def locate(characters): #find the "center of mass" of the array for char in characters: image = invert_image(char.image) char.center = center_of_mass(image) return characters
def get_center_of_shape(self, segment): if self.center_of_shape is None: labels = self.get_labels() # ids = self.get_segmentids() ids = np.unique(labels) coss = measurements.center_of_mass(labels, labels, ids) self.center_of_shape = dict(zip(ids, np.array(coss))) return self.center_of_shape.get(segment.get_segmentid(), segment.get_coord(mode="lm"))
def find_center_by_scattering_lobes(image, threshold=15): '''find center of mass of stripe domain lattice scattering lobes in the upper left and lower right quadrant of the image and use these to calculate center of scattering pattern''' limit_x, limit_y = [i // 4 for i in image.shape] quad = median_filter(image[:limit_x, :limit_y], size=6, mode='constant') mean = quad.mean() std = quad.std() lobe1 = np.array(center_of_mass(quad * quad > (mean + threshold * std))) limit_x, limit_y = [i - i // 4 for i in image.shape] quad = median_filter(image[limit_x:, limit_y:], size=6, mode='constant') mean = quad.mean() std = quad.std() lobe2 = np.array(center_of_mass(quad * quad > (mean + threshold * std))) lobe2 += [limit_x, limit_y] center = np.array(lobe1 + (lobe2 - lobe1) / 2, dtype=np.int) return center
def get_contours3d(A, dims, thr=0.9): """Gets contour of spatial components and returns their coordinates Parameters ----------- A: np.ndarray or sparse matrix Matrix of Spatial components (d x K) dims: tuple of ints Spatial dimensions of movie (x, y, z) thr: scalar between 0 and 1 Energy threshold for computing contours (default 0.995) Returns -------- Coor: list of coordinates with center of mass and contour plot coordinates (per layer) for each component """ d, nr = np.shape(A) d1, d2, d3 = dims x, y = np.mgrid[0:d2:1, 0:d3:1] coordinates = [] cm = np.asarray([center_of_mass(a.reshape(dims, order='F')) for a in A.T]) for i in range(nr): pars = dict() indx = np.argsort(A[:, i], axis=None)[::-1] cumEn = np.cumsum(A[:, i].flatten()[indx]**2) cumEn /= cumEn[-1] Bvec = np.zeros(d) Bvec[indx] = cumEn Bmat = np.reshape(Bvec, dims, order='F') pars['coordinates'] = [] for B in Bmat: cs = pl.contour(y, x, B, [thr]) # this fix is necessary for having disjoint figures and borders plotted correctly p = cs.collections[0].get_paths() v = np.atleast_2d([np.nan, np.nan]) for pths in p: vtx = pths.vertices num_close_coords = np.sum(np.isclose(vtx[0, :], vtx[-1, :])) if num_close_coords < 2: if num_close_coords == 0: # case angle newpt = np.round(old_div(vtx[-1, :], [d2, d1])) * [d2, d1] vtx = np.concatenate((vtx, newpt[np.newaxis, :]), axis=0) else: # case one is border vtx = np.concatenate((vtx, vtx[0, np.newaxis]), axis=0) v = np.concatenate((v, vtx, np.atleast_2d([np.nan, np.nan])), axis=0) pars['coordinates'] += [v] pars['CoM'] = np.squeeze(cm[i, :]) pars['neuron_id'] = i + 1 coordinates.append(pars) return coordinates
def get_center_of_mass(self, segment): if self.center_of_mass is None: labels = self.get_labels() img = self.get_img() # ids = self.get_segmentids() ids = np.unique(labels) coms = measurements.center_of_mass(img.data, labels, ids) self.center_of_mass = dict(zip(ids, np.array(coms))) return self.center_of_mass.get(segment.get_segmentid(), segment.get_coord(mode="lm"))
def start_point(area, bkg): ''' Returns a guess of fitting parameters to be used as the starting point of the fitting process.''' center = area.shape[0] // 2 area_bkg = area - bkg A = 1.54 * area_bkg[center, center] x0, y0 = center_of_mass(area_bkg) return [A, x0, y0, np.mean(bkg)]
def find_GEO(self): """ Determine the geometric distortion. Averages 3 slices around HU slice. :return: """ # average 3 slices around the nominal slice GEO_slice = np.mean(self.images[ self.slices_of_interest['HU'] - 1:self.slices_of_interest['HU'] + 1, small_FOV_settings['GEO_box_bounds'][0]:small_FOV_settings['GEO_box_bounds'][2], small_FOV_settings['GEO_box_bounds'][1]:small_FOV_settings['GEO_box_bounds'][3]], 0) #plt.imshow(GEO_slice) # construct black & white image GEO_bw1 = np.where(GEO_slice > np.median(GEO_slice) * 1.3, 1, 0) GEO_bw2 = np.where(GEO_slice < np.median(GEO_slice) * 0.7, 1, 0) GEO_bw = GEO_bw1 + GEO_bw2 plt.imshow(GEO_bw) plt.title("GEO_slice") #plt.show() # find centers of geometric points labels, no_roi = meas.label(GEO_bw) print (no_roi) #if no_roi != 4: # raise ValueError, "Unable to locate the geometric nodes. May need to adjust the geometric ROI slice. " geo_CofM = meas.center_of_mass(GEO_bw, labels, index=[1,2,3,4]) self.geo_CofM = geo_CofM # distance calculations (result is in mm; nominal distance is 50mm (5cm) self.results['v1'] = ptg.dist_2points(geo_CofM[0], geo_CofM[1]) * self.improps['mm/Pixel'] self.results_diffs['v1'] = self.results['v1'] - nominal_GEO self.results['h1'] = ptg.dist_2points(geo_CofM[0], geo_CofM[2]) * self.improps['mm/Pixel'] self.results_diffs['h1'] = self.results['h1'] - nominal_GEO self.results['v2'] = ptg.dist_2points(geo_CofM[3], geo_CofM[1]) * self.improps['mm/Pixel'] self.results_diffs['v2'] = self.results['v2'] - nominal_GEO self.results['h2'] = ptg.dist_2points(geo_CofM[3], geo_CofM[2]) * self.improps['mm/Pixel'] self.results_diffs['h2'] = self.results['h2'] - nominal_GEO res_diffs = np.array((self.results_diffs['v1'], self.results_diffs['h1'], self.results_diffs['v2'], self.results_diffs['h2'])) if all(res_diffs < tolerances['GEO']) and all(res_diffs > -tolerances['GEO']): self.GEO_pass = True else: self.GEO_pass = False pass
def fix_orientation(data): from scipy.ndimage.measurements import center_of_mass # Find the first and last frame with nonzero measurement_data (from z) x, y, z = np.nonzero(data) # For some reason I was loading the file in such a way that it wasn't sorted z = sorted(z) start, end = z[0], z[-1] # Get the COP for those two frames start_x, start_y = center_of_mass(data[:, :, start]) end_x, end_y = center_of_mass(data[:, :, end]) # We've calculated the start and end point of the measurement (if at all) x_distance = end_x - start_x # If this distance is negative, the subject walked right to left #print .The distance between the start and end is: {}".format(x_distance) if x_distance < 0: # So we flip the measurement_data around data = np.rot90(np.rot90(data)) #measurement_data = measurement_data[::-1,::-1,:] #Alternative return data
def gen_feature_mfcc(x): v, asp = x try: if np.isnan(v).any() or np.isinf(v).any(): raise Exception('MFCC contains Nan of Inf') xn, (xmin, xmax), xmean, xvar, xskew, xkurt = stats.describe(v) d = np.diff(v, 1, 0) dmean = np.mean(d, 0) feat = np.reshape((measurements.center_of_mass(v)[0], measurements.center_of_mass(asp)[0], measurements.maximum_position(asp)[0]),(3,)) hist = 1.0*measurements.histogram(asp, 0, 1, 4) / asp.shape[0]/asp.shape[1] x = np.concatenate((xmean,xmin,xmax,xvar,dmean,feat,hist[-1:])) if np.isnan(x).any() or np.isinf(x).any(): raise Exception('Feature vector contains Nan of Inf') except: #print d, dd print xmin.shape raise return x.T
def _eucl_cog(self, nii1, nii2): origdata1 = nii1.get_data().astype(np.bool) cog_t = np.array(center_of_mass(origdata1)).reshape(-1, 1) cog_t = np.vstack((cog_t, np.array([1]))) cog_t_coor = np.dot(nii1.get_affine(), cog_t)[:3, :] origdata2 = nii2.get_data().astype(np.bool) (labeled_data, n_labels) = label(origdata2) cogs = np.ones((4, n_labels)) for i in range(n_labels): cogs[:3, i] = np.array(center_of_mass(origdata2, labeled_data, i + 1)) cogs_coor = np.dot(nii2.get_affine(), cogs)[:3, :] dist_matrix = cdist(cog_t_coor.T, cogs_coor.T) return np.mean(dist_matrix)
def calc_object_pos(movie): # define background, do background subtraction and thresholding background = nim.darken(movie.frames[0].raw, movie.frames[-1].raw) for i, frame in enumerate(movie.frames): print 'processing frames... ', i movie.frames[i].absdiff = nim.absdiff(frame.raw, background) movie.frames[i].diffthresh = nim.threshold(movie.frames[i].absdiff, THRESH_HOLD) ## TODO: right now this assumes the thresholding is perfect...! # find center of fly: center = center_of_mass(movie.frames[i].diffthresh) if 1: if center[0] == np.nan: center = (0,0) limlo_x = center[0]-ROI_RADIUS if limlo_x < 0: limlo_x = 0 limhi_x = center[0]+ROI_RADIUS if limhi_x > movie.height: limhi_x = movie.height limlo_y = center[1]-ROI_RADIUS if limlo_y < 0: limlo_y = 0 limhi_y = center[1]+ROI_RADIUS if limhi_y > movie.width: limhi_y = movie.width # TODO: right now object entering or leaving frame doesnt work perfectly uimg = movie.frames[i].diffthresh[limlo_x:limhi_x, limlo_y:limhi_y] movie.frames[i].uimg = uimg movie.frames[i].uimg_center = center el = nim.fit_ellipse(uimg) center_relative_to_roi,xr,yr,theta_to_xaxis = el tmp = np.array([float(ROI_RADIUS)/2, float(ROI_RADIUS)/2]) obj_pos = np.array(center) + np.array(center_relative_to_roi) - tmp if xr>=yr: angle = theta_to_xaxis else: angle = theta_to_xaxis+np.pi/2. movie.frames[i].obj = Object(obj_pos, angle) print xr,yr return movie
def findCenter(frame, threshold): '''Take a frame, and find the pupil center''' img = frame[...,0] h,w = img.shape # Threshold the image and adapt - if necessary - the threshold (bw, threshold) = adaptThreshold(img, threshold) # Flip b/w, and convert to uint8 im_bw = np.array(~bw, dtype=np.uint8)*255 algorithmNr = 0 if algorithmNr == 0: labelled_array, num_features = spm.label(im_bw) sizes = spm.sum(bw, labelled_array, range(num_features)) center = spm.center_of_mass(bw, labelled_array, np.argmax(sizes)) center = [center[1], center[0]] elif algorithmNr == 1: # Fill the corners # Note that the mask has to be 2 pixels larger than the image! mask = np.zeros( (h+2,w+2), dtype=np.uint8) cv2.floodFill(im_bw, mask, (1,h-1), 255) # After the floodfill operation, the "mask" indicates which areas have # been filled. It therefore has to be re-set for the next filling task. mask = np.zeros( (h+2,w+2), dtype=np.uint8) cv2.floodFill(im_bw, mask, (w-1,h-1), 255) # Fill the holes in the pupil wHoles = im_bw.copy() mask = np.zeros( (h+2,w+2), dtype=np.uint8) cv2.floodFill(wHoles, mask, (1,1), 0) im_bw[wHoles==255] = 0 # Close the image, to remove the eye-brows radius = 25 strEl = np.zeros((2*radius+1, 2*radius+1), dtype=np.uint8) cv2.circle(strEl, (radius,radius), radius, 255, -1) closed = cv2.morphologyEx(im_bw, cv2.MORPH_CLOSE, strEl) # find the edge edgeThresholds = (1000, 1000) edge = cv2.Canny(closed, edgeThresholds[0], edgeThresholds[1], apertureSize=5) # find the center of the edge edge_y, edge_x = np.where(edge==255) center = np.array([np.mean(edge_x), np.mean(edge_y)]) if np.any(np.isnan(center)): center = np.zeros(2) return (center, threshold)
def _eucl_cog(self, nii1, nii2): origdata1 = np.logical_and(nii1.get_data() != 0, np.logical_not(np.isnan(nii1.get_data()))) cog_t = np.array(center_of_mass(origdata1.copy())).reshape(-1, 1) cog_t = np.vstack((cog_t, np.array([1]))) cog_t_coor = np.dot(nii1.affine, cog_t)[:3, :] origdata2 = np.logical_and(nii2.get_data() != 0, np.logical_not(np.isnan(nii2.get_data()))) (labeled_data, n_labels) = label(origdata2) cogs = np.ones((4, n_labels)) for i in range(n_labels): cogs[:3, i] = np.array(center_of_mass(origdata2, labeled_data, i + 1)) cogs_coor = np.dot(nii2.affine, cogs)[:3, :] dist_matrix = cdist(cog_t_coor.T, cogs_coor.T) return np.mean(dist_matrix)
def stack_all(self, mode='median', save=False): """ Stack all PSF stars to produce a PSF image in the original pixel scale. """ output = 'psf_stacked_raw_%s_%s_mag%.2f.fits' % (self.band, mode, 1. / self.factor) if os.path.exists(output): os.remove(output) iraf.imcombine(input='@psflist', output=output, combine=mode, reject='sigclip', lsigma=3.0, hsigma=3.0, mclip='yes', nkeep=3) shape2 = np.array(pyfits.getdata(output).shape) # Now re-sample the image back to the original pixel scale output2 = 'psf_stacked_%s_%s.fits' % (self.band, mode) if os.path.exists(output2): os.remove(output2) # pm = image_moments.moments(pyfits.getdata(output)) # pm.firstorder() pm1 = measurements.center_of_mass(pyfits.getdata(output)) print "Oversampled PSF shape:", shape2 print "Centroid before shift: %.2f, %.2f" % tuple(pm1) print "Shifted PSF image:", output2 # AND REMEMBER TO SWAP X & Y if using IRAF! # iraf.imlintran(input=output, # output=output2, # xrotation=0., yrotation=0., # xin=pm.y1, yin=pm.x1, # xmag=self.factor, ymag=self.factor, # ncols=shape2[0]/self.factor, nlines=shape2[1]/self.factor, # interpolant=self.interpolant) xshift = shape2[0] / 2. - pm1[0] yshift = shape2[1] / 2. - pm1[1] output_data = pyfits.getdata(output) print "xshift, yshift:", xshift, yshift output2_data = interpolation.shift(output_data, [xshift, yshift], order=1, mode='wrap') # check the new psf is centered... pm2 = measurements.center_of_mass(output2_data) print "Shifted center of mass: %.2f, %.2f" % tuple(pm2) # Now zoom the PSF back to the original pixel scale output2_data = interpolation.zoom(output2_data, 1. / self.factor, order=1, mode='wrap') pyfits.append(output2, output2_data, pyfits.getheader(output)) # Now center the PSF # pm2 = image_moments.moments(pyfits.getdata(output2)) # npix = np.min(pyfits.getdata(output2).shape) # print "npix", npix # iraf.imlintran(input=output2, output='temp.fits', # xrotation=0., yrotation=0., # xin=pm2.x1+1, yin=pm2.y1+1, # xmag=1.0, ymag=1.0, # ncols=npix, nlines=npix, # interpolant='linear') # Now normalize the PSF # imgsum = pyfits.getdata(output2).ravel().sum() imgsum = output2_data.sum() imgsum = np.abs(imgsum) iraf.imarith(output2, '/', imgsum, 'temp.fits') os.remove(output2) os.system('mv temp.fits %s' % output2) os.system('rm temp*.fits') if not save: print "Removing %s..." % output os.remove(output)
def addImg(self, img, roi=None): ''' img - background, flat field, ste corrected image roi - [(x1,y1),...,(x4,y4)] - boundaries where points are ''' self.img = imread(img, 'gray') s0, s1 = self.img.shape if roi is None: roi = ((0, 0), (s0, 0), (s0, s1), (0, s1)) k = self.kernel_size hk = k // 2 # mask image img2 = self.img.copy() # .astype(int) mask = np.zeros(self.img.shape) cv2.fillConvexPoly(mask, np.asarray(roi, dtype=np.int32), color=1) mask = mask.astype(bool) im = img2[mask] bg = im.mean() # assume image average with in roi == background mask = ~mask img2[mask] = -1 # find points from local maxima: self.points = np.zeros(shape=(self.max_points, 2), dtype=int) thresh = 0.8 * bg + 0.2 * im.max() _findPoints(img2, thresh, self.min_dist, self.points) self.points = self.points[:np.argmin(self.points, axis=0)[0]] # correct point position, to that every point is over max value: for n, p in enumerate(self.points): sub = self.img[p[1] - hk:p[1] + hk + 1, p[0] - hk:p[0] + hk + 1] i, j = np.unravel_index(np.nanargmax(sub), sub.shape) self.points[n] += [j - hk, i - hk] # remove points that are too close to their neighbour or the border mask = maximum_filter(mask, hk) i = np.ones(self.points.shape[0], dtype=bool) for n, p in enumerate(self.points): if mask[p[1], p[0]]: # too close to border i[n] = False else: # too close to other points for pp in self.points[n + 1:]: if norm(p - pp) < hk + 1: i[n] = False isum = i.sum() ll = len(i) - isum print('found %s points' % isum) if ll: print('removed %s points (too close to border or other points)' % ll) self.points = self.points[i] # self.n_points += len(self.points) # for finding best peak position: # def fn(xy,cx,cy):#par # (x,y) = xy # return 1-(((x-cx)**2 + (y-cy)**2)*(1/8)).flatten() # x,y = np.mgrid[-2:3,-2:3] # x = x.flatten() # y = y.flatten() # for shifting peak: xx, yy = np.mgrid[0:k, 0:k] xx = xx.astype(float) yy = yy.astype(float) self.subs = [] # import pylab as plt # plt.figure(20) # img = self.drawPoints() # plt.imshow(img, interpolation='none') # # plt.figure(21) # # plt.imshow(sub2, interpolation='none') # plt.show() #thresh = 0.8*bg + 0.1*im.max() for i, p in enumerate(self.points): sub = self.img[p[1] - hk:p[1] + hk + 1, p[0] - hk:p[0] + hk + 1].astype(float) sub2 = sub.copy() mean = sub2.mean() mx = sub2.max() sub2[sub2 < 0.5 * (mean + mx)] = 0 # only select peak try: # SHIFT SUB ARRAY to align peak maximum exactly in middle: # only eval a 5x5 array in middle of sub: # peak = sub[hk-3:hk+4,hk-3:hk+4]#.copy() # peak -= peak.min() # peak/=peak.max() # peak = peak.flatten() # fit paraboloid to get shift in x,y: # p, _ = curve_fit(fn, (x,y), peak, (0,0)) c0, c1 = center_of_mass(sub2) # print (p,c0,c1,hk) #coords = np.array([xx+p[0],yy+p[1]]) coords = np.array([xx + (c0 - hk), yy + (c1 - hk)]) #print (c0,c1) #import pylab as plt #plt.imshow(sub2, interpolation='none') # shift array: sub = map_coordinates(sub, coords, mode='nearest').reshape(k, k) # plt.figure(2) #plt.imshow(sub, interpolation='none') # plt.show() #normalize: bg = 0.25 * (sub[0].mean() + sub[-1].mean() + sub[:, 0].mean() + sub[:, -1].mean()) sub -= bg sub /= sub.max() # import pylab as plt # plt.figure(20) # plt.imshow(sub, interpolation='none') # # plt.figure(21) # # plt.imshow(sub2, interpolation='none') # plt.show() self._psf += sub if self.calc_std: self.subs.append(sub) except ValueError: pass #sub.shape == (0,0)
def nema_2008_small_animal_pet_rois(vol, voxsize, lp_voxel = 'max', rod_th = 0.15, phantom = 'standard'): """ generate a label volume indicating the ROIs needed in the analysis of the NEMA small animal PET IQ phantom Parameters ---------- vol : 3D numpy float array containing the image voxsize : 3 element 1D numpy array containing the voxel size lp_voxel: string, optional method of how to compute the pixel used to draw the line profiles in the rods. 'max' means the maximum voxels in the summed 2D image. anything else means use the center of mass. rod_th : float, optional threshold to find the rod in the summed 2D image relative to the mean of the big uniform region phantom : string phantom version ('standard' or 'mini') Returns ------- a 3D integer numpy array encoding the following ROIs: 1 ... ROI of the big uniform region 2 ... first cold insert 3 ... second cold insert 4 ... central line profile in 5mm rod 5 ... central line profile in 4mm rod 6 ... central line profile in 3mm rod 7 ... central line profile in 2mm rod 8 ... central line profile in 1mm rod Note ---- The rod ROIs in the summed 2D image are found by thresholding. If the activity in the small rods is too low, they might be missed. """ roi_vol = np.zeros(vol.shape, dtype = np.uint) # calculate the summed z profile to place the ROIs zprof = vol.sum(0).sum(0) zprof_grad = np.gradient(zprof) zprof_grad[np.abs(zprof_grad) < 0.13*np.abs(zprof_grad).max()] = 0 rising_edges = argrelextrema(zprof_grad, np.greater, order = 10)[0] falling_edges = argrelextrema(zprof_grad, np.less, order = 10)[0] # if we only have 2 falling edges because the volume is cropped, we add the last slices as # falling edge if falling_edges.shape[0] == 2: falling_edges = np.concatenate([falling_edges,[vol.shape[2]]]) # define and analyze the big uniform ROI uni_region_start_slice = rising_edges[1] uni_region_end_slice = falling_edges[1] uni_region_center_slice = 0.5*(uni_region_start_slice + uni_region_end_slice) uni_roi_start_slice = int(np.floor(uni_region_center_slice - 5./voxsize[2])) uni_roi_end_slice = int(np.ceil(uni_region_center_slice + 5./voxsize[2])) uni_com = np.array(center_of_mass(vol[:,:,uni_roi_start_slice:(uni_roi_end_slice+1)])) x0 = (np.arange(vol.shape[0]) - uni_com[0]) * voxsize[0] x1 = (np.arange(vol.shape[1]) - uni_com[1]) * voxsize[1] x2 = (np.arange(vol.shape[2]) - uni_com[2]) * voxsize[2] X0,X1,X2 = np.meshgrid(x0,x1,x2,indexing='ij') RHO = np.sqrt(X0**2 + X1**2) uni_mask = np.zeros(vol.shape, dtype = np.uint) if phantom == 'standard': uni_mask[RHO <= 11.25] = 1 elif phantom == 'mini': uni_mask[RHO <= 6.25] = 1 uni_mask[:,:,:uni_roi_start_slice] = 0 uni_mask[:,:,(uni_roi_end_slice+1):] = 0 uni_inds = np.where(uni_mask == 1) roi_vol[uni_inds] = 1 # define and analyze the two cold ROIs insert_region_start_slice = falling_edges[1] insert_region_end_slice = falling_edges[2] insert_region_center_slice = 0.5*(insert_region_start_slice + insert_region_end_slice) insert_roi_start_slice = int(np.floor(insert_region_center_slice - 3.75/voxsize[2])) insert_roi_end_slice = int(np.ceil(insert_region_center_slice + 3.75/voxsize[2])) # sum the insert slices and subtract them from the max to find the two cold inserts sum_insert_img = vol[:,:,insert_roi_start_slice:(insert_roi_end_slice+1)].mean(2) ref = np.percentile(sum_insert_img,99) if phantom == 'standard': insert_label_img, nlab_insert = label(sum_insert_img <= 0.5*ref) elif phantom == 'mini': # reset pixels outside the phantom, since inserts sometimes leak into background tmp_inds = RHO[:,:,0] > 9 sum_insert_img[tmp_inds] = ref insert_label_img, nlab_insert = label(binary_erosion(sum_insert_img <= 0.5*ref)) # add backgroud low activity ROI to be compliant with standard phantom insert_label_img[tmp_inds] = 3 nlab_insert += 1 insert_labels = np.arange(1,nlab_insert+1) # sort the labels according to volume npix_insert = labeled_comprehension(sum_insert_img, insert_label_img, insert_labels, len, int, 0) insert_sort_inds = npix_insert.argsort()[::-1] insert_labels = insert_labels[insert_sort_inds] npix_insert = npix_insert[insert_sort_inds] for i_insert in [1,2]: tmp = insert_label_img.copy() tmp[insert_label_img != insert_labels[i_insert]] = 0 com_pixel = np.round(np.array(center_of_mass(tmp))) x0 = (np.arange(vol.shape[0]) - com_pixel[0]) * voxsize[0] x1 = (np.arange(vol.shape[1]) - com_pixel[1]) * voxsize[1] x2 = (np.arange(vol.shape[2])) * voxsize[2] X0,X1,X2 = np.meshgrid(x0,x1,x2,indexing='ij') RHO = np.sqrt(X0**2 + X1**2) insert_mask = np.zeros(vol.shape, dtype = np.uint) insert_mask[RHO <= 2] = 1 insert_mask[:,:,:insert_roi_start_slice] = 0 insert_mask[:,:,(insert_roi_end_slice+1):] = 0 insert_inds = np.where(insert_mask == 1) roi_vol[insert_inds] = i_insert + 1 # find the rod z slices rod_start_slice = falling_edges[0] rod_end_slice = rising_edges[1] rod_center = 0.5*(rod_start_slice + rod_end_slice) rod_roi_start_slice = int(np.floor(rod_center - 5./voxsize[2])) rod_roi_end_slice = int(np.ceil(rod_center + 5./voxsize[2])) # sum the rod slices sum_img = vol[:,:,rod_roi_start_slice:(rod_roi_end_slice+1)].mean(2) # label the summed image label_img, nlab = label(sum_img > rod_th*sum_img.max()) labels = np.arange(1,nlab+1) # sort the labels according to volume npix = labeled_comprehension(sum_img, label_img, labels, len, int, 0) sort_inds = npix.argsort()[::-1] labels = labels[sort_inds] npix = npix[sort_inds] # find the center for the line profiles for i, lab in enumerate(labels): rod_sum_img = sum_img.copy() rod_sum_img[label_img != lab] = 0 if lp_voxel == 'max': central_pixel = np.unravel_index(rod_sum_img.argmax(),rod_sum_img.shape) else: central_pixel = np.round(np.array(center_of_mass(rod_sum_img))).astype(np.int) roi_vol[central_pixel[0],central_pixel[1],rod_roi_start_slice:(rod_roi_end_slice+1)] = i + 4 #------------------------------------------------------- # if we only have 4 labels (rods), we find the last (smallest) one based on symmetries if nlab == 4: roi_img = roi_vol[...,rod_roi_start_slice] com = center_of_mass(roi_vol == 1) x0 = (np.arange(sum_img.shape[0]) - com[0]) * voxsize[0] x1 = (np.arange(sum_img.shape[1]) - com[1]) * voxsize[1] X0,X1 = np.meshgrid(x0, x1, indexing = 'ij') RHO = np.sqrt(X0**2 + X1**2) PHI = np.arctan2(X1,X0) rod_phis = np.array([PHI[roi_img == x][0] for x in np.arange(4,nlab+4)]) PHI = ((PHI - rod_phis[3]) % (2*np.pi)) - np.pi rod_phis = ((rod_phis - rod_phis[3]) % (2*np.pi)) - np.pi missing_phi = ((rod_phis[3] - rod_phis[2]) % (2*np.pi)) - np.pi mask = np.logical_and(np.abs(PHI - missing_phi) < 0.25, np.abs(RHO - 6.4) < 2) central_pixel = np.unravel_index(np.argmax(sum_img*mask), sum_img.shape) roi_vol[central_pixel[0],central_pixel[1],rod_roi_start_slice:(rod_roi_end_slice+1)] = 8 nlab += 1 #------------------------------------------------------- return roi_vol
def heatmap(im, model, patch_shape, mean_train, std_train, brain_bool=True): """Compute the heatmap with CNN_1 representing the SC localization.""" data_im = im.data.astype(np.float32) im_out = change_type(im, "uint8") del im data = np.zeros(im_out.data.shape) x_shape, y_shape = data_im.shape[:2] x_shape_block, y_shape_block = np.ceil(x_shape * 1.0 / patch_shape[0]).astype(np.int), np.int( y_shape * 1.0 / patch_shape[1]) x_pad = int(x_shape_block * patch_shape[0] - x_shape) if y_shape > patch_shape[1]: y_crop = y_shape - y_shape_block * patch_shape[1] # slightly crop the input data in the P-A direction so that data_im.shape[1] % patch_shape[1] == 0 data_im = data_im[:, :y_shape - y_crop, :] # coordinates of the blocks to scan during the detection, in the cross-sectional plane coord_lst = [[x_dim * patch_shape[0], y_dim * patch_shape[1], (x_dim + 1) * patch_shape[0], (y_dim + 1) * patch_shape[1]] for y_dim in range(y_shape_block) for x_dim in range(x_shape_block)] else: data_im = np.pad(data_im, ((0, 0), (0, patch_shape[1] - y_shape), (0, 0)), 'constant') coord_lst = [[x_dim * patch_shape[0], 0, (x_dim + 1) * patch_shape[0], patch_shape[1]] for x_dim in range(x_shape_block)] # pad the input data in the R-L direction data_im = np.pad(data_im, ((0, x_pad), (0, 0), (0, 0)), 'constant') # scale intensities between 0 and 255 data_im = scale_intensity(data_im) x_CoM, y_CoM = None, None z_sc_notDetected_cmpt = 0 for zz in range(data_im.shape[2]): # if SC was detected at zz-1, we will start doing the detection on the block centered around the previously # computed center of mass (CoM) if x_CoM is not None: z_sc_notDetected_cmpt = 0 # SC detected, cmpt set to zero x_0, x_1 = _find_crop_start_end(x_CoM, patch_shape[0], data_im.shape[0]) y_0, y_1 = _find_crop_start_end(y_CoM, patch_shape[1], data_im.shape[1]) block = data_im[x_0:x_1, y_0:y_1, zz] block_nn = np.expand_dims(np.expand_dims(block, 0), -1) block_nn_norm = _normalize_data(block_nn, mean_train, std_train) block_pred = model.predict(block_nn_norm, batch_size=BATCH_SIZE) # coordinates manipulation due to the above padding and cropping if x_1 > data.shape[0]: x_end = data.shape[0] x_1 = data.shape[0] x_0 = data.shape[0] - patch_shape[0] if data.shape[0] > patch_shape[0] else 0 else: x_end = patch_shape[0] if y_1 > data.shape[1]: y_end = data.shape[1] y_1 = data.shape[1] y_0 = data.shape[1] - patch_shape[1] if data.shape[1] > patch_shape[1] else 0 else: y_end = patch_shape[1] data[x_0:x_1, y_0:y_1, zz] = block_pred[0, :x_end, :y_end, 0] # computation of the new center of mass if np.max(data[:, :, zz]) > 0.5: z_slice_out_bin = data[:, :, zz] > 0.5 # if the SC was detection x_CoM, y_CoM = center_of_mass(z_slice_out_bin) x_CoM, y_CoM = int(x_CoM), int(y_CoM) else: x_CoM, y_CoM = None, None # if the SC was not detected at zz-1 or on the patch centered around CoM in slice zz, the entire cross-sectional # slice is scanned if x_CoM is None: z_slice, x_CoM, y_CoM, coord_lst = scan_slice(data_im[:, :, zz], model, mean_train, std_train, coord_lst, patch_shape, data.shape[:2]) data[:, :, zz] = z_slice z_sc_notDetected_cmpt += 1 # if the SC has not been detected on 10 consecutive z_slices, we stop the SC investigation if z_sc_notDetected_cmpt > 10 and brain_bool: sct.printv('Brain section detected.') break # distance transform to deal with the harsh edges of the prediction boundaries (Dice) data[:, :, zz][np.where(data[:, :, zz] < 0.5)] = 0 data[:, :, zz] = distance_transform_edt(data[:, :, zz]) if not np.any(data): logger.error( '\nSpinal cord was not detected using "-centerline cnn". Please try another "-centerline" method.\n') sys.exit(1) im_out.data = data # z_max is used to reject brain sections z_max = np.max(list(set(np.where(data)[2]))) if z_max == data.shape[2] - 1: return im_out, None else: return im_out, z_max
def attenuation_iaf(raws, picks=None, # noqa: C901 fmin=None, fmax=None, resolution=0.25, average=True, ax=None, savgol=False, window_length=11, polyorder=5, flat_max_r=0.98): """Estimate individual alpha frequency (IAF). Parameters ---------- raws : list-like of Raw Two Raws to calculate IAF from difference (attenuation) in PSD from. picks : array-like of int | None List of channels to use. fmin : int | None Lower bound of alpha frequency band. If None, it will be empirically estimated using a polynomial fitting method to determine the edges of the central parabolic peak density, with assumed center of 10 Hz. fmax : int | None Upper bound of alpha frequency band. If None, it will be empirically estimated using a polynomial fitting method to determine the edges of the central parabolic peak density, with assumed center of 10 Hz. resolution : float The resolution in the frequency domain for calculating the PSD. average : bool Whether to average the PSD estimates across channels or provide a separate estimate for each channel. Currently, only True is supported. ax : instance of matplotlib Axes | None | False Axes to plot PSD analysis into. If None, axes will be created (and plot not shown by default). If False, no plotting will be done. savgol : False | 'each' | 'diff' Use Savitzky-Golay filtering to smooth PSD estimates -- either applied to either each PSD estimate or to the difference (i.e. the attenuation estimate). window_length : int Window length in samples to use for Savitzky-Golay smoothing of PSD when estimating IAF. polyorder : int Polynomial order to use for Savitzky-Golay smoothing of PSD when estimating IAF. flat_max_r: float Maximum (Pearson) correlation allowed when comparing the raw PSD distributions to each other in the range 1 to 30 Hz. If this threshold is exceeded, then IAF is assumed unclear and None is returned for both PAF and CoG. Note that the sign of the coefficient is ignored. Returns ------- IafEst : instance of ``collections.namedtuple`` called IAFEstimate Named tuple with fields for the peak alpha frequency (PAF), alpha center of gravity (CoG), and the bounds of the alpha band (as a tuple). Notes ----- Based on method developed by `Andrew Corcoran <https://zenodo.org/badge/latestdoi/80904585>`_. In addition to appropriate software citation (Zenodo DOI or git commit), please cite: Corcoran, A. W., Alday, P. M., Schlesewsky, M., & Bornkessel-Schlesewsky, I. (2018). Toward a reliable, automated method of individual alpha frequency (IAF) quantification. Psychophysiology, e13064. doi:10.1111/psyp.13064 """ # TODO: check value of savgol parameter def psd_est(r): n_fft = int(r.info['sfreq'] / resolution) return mne.time_frequency.psd_welch(r, picks=picks, n_fft=n_fft, fmin=1., fmax=30.) psd, freqs = zip(*[psd_est(r) for r in raws]) assert np.allclose(*freqs) if savgol == 'each': psd = [savgol_filter(p, window_length=window_length, polyorder=polyorder) for p in psd] att_psd = psd[1] - psd[0] if average: att_psd = np.mean(att_psd, axis=0) psd = [np.mean(p, axis=0) for p in psd] att_psd = np.abs(att_psd) att_freqs = freqs[0] if ax is None: fig = plt.figure() # noqa: F841 ax = plt.gca() if fmin is None or fmax is None: if fmin is None: fmin_bound = 5 else: fmin_bound = fmin if fmax is None: fmax_bound = 15 else: fmax_bound = fmax alpha_search = np.logical_and(att_freqs >= fmin_bound, att_freqs <= fmax_bound) freqs_search = att_freqs[alpha_search] # set the window to the entire interval # don't use the sname window_length because that's used as a # parameter for the function as a whole wlen = att_psd[alpha_search].shape[0] psd_search = savgol_filter(att_psd[alpha_search], window_length=wlen, polyorder=10) # argrel min returns a tuple, so we flatten that with [0] # then we get the last element of the resulting array with [-1] # which is the minimum closest to the 'median' alpha of 10 Hz if fmin is None: try: left_min = argrelmin(psd_search[freqs_search < 10])[0][-1] fmin = freqs_search[freqs_search < 10][left_min] except IndexError: raise ValueError("Unable to automatically determine lower end of alpha band.") # noqa: 501 if fmax is None: # here we want the first element of the array which is closest to # the 'median' alpha of 10 Hz try: right_min = argrelmin(psd_search[freqs_search > 10])[0][0] fmax = freqs_search[freqs_search > 10][right_min] except IndexError: raise ValueError("Unable to automatically determine upper end of alpha band.") # noqa: 501 if savgol == 'diff': att_psd = savgol_filter(att_psd, window_length=window_length, polyorder=polyorder) alpha_band = np.logical_and(att_freqs >= fmin, att_freqs <= fmax) r, p = stats.pearsonr(psd[0], psd[1]) if np.abs(r) > np.abs(flat_max_r): paf = None cog = None else: paf_idx = np.argmax(att_psd[alpha_band]) paf = att_freqs[alpha_band][paf_idx] cog_idx = center_of_mass(att_psd[alpha_band]) cog_idx = int(np.round(cog_idx[0])) cog = att_freqs[alpha_band][cog_idx] if ax: sgnote = '(with SG-Smoothing)' if savgol == 'each' else '' plt_psd1, = ax.plot(freqs[0], psd[0], label="Raw PSD #1 {}".format(sgnote)) plt_psd2, = ax.plot(freqs[1], psd[1], label="Raw PSD #2 {}".format(sgnote)) sgnote = '(with SG-Smoothing)' if savgol == 'diff' else '' plt_att_psd, = ax.plot(att_freqs, att_psd, label="Attenuated PSD {}".format(sgnote)) # plt_pink, = ax.plot(att_freqs, # np.exp(slope * np.log(att_freqs) + intercept), # label='$1/f$ fit ($R^2={:0.2}$)'.format(r**2)) ax.text(np.max(att_freqs) * 0.5, np.max(att_psd) * 0.67, 'Raw PSD Pearson $r={:0.2}$'.format(r)) try: plt_search, = ax.plot(freqs_search, psd_search, label='Alpha-band Search Parabola') ax.legend(handles=[plt_psd1, plt_psd2, plt_att_psd, plt_search]) except UnboundLocalError: # this happens when the user fully specified an alpha band ax.legend(handles=[plt_psd1, plt_psd2, plt_att_psd]) ax.set_ylabel("PSD") ax.set_xlabel("Hz") return IafEst(paf, cog, (fmin, fmax))
n_centroids_to_keep = 30 labeled, nr_objects = mh.label(bw) sizes = mh.labeled.labeled_size( labeled ) # size[0] is the background size, sizes[1 and greater] are number of pixels in each region sorted_sizes_indexes = np.argsort(sizes)[::-1] # return in descending order good_spot_indexes = sorted_sizes_indexes[ 1:n_centroids_to_keep + 1] # avoiding the background regions entry at the beginning FWHMSub = [] xCenSub = [] yCenSub = [] peaks = [] fluxes = [] centers = center_of_mass(labeled, labels=labeled, index=[good_spot_indexes]) nbox = 20 for i, x in enumerate(centers): x = x[0] px = int(round(x[1])) py = int(round(x[0])) data = img[py - nbox:py + nbox, px - nbox:px + nbox] params = fitgaussian(data) fwhm = abs(2.355 * max(params[4], params[5])) if fwhm < .5: print(" fit failed - trying again with smaller fitbox") sbox = nbox - 1 data = img[py - sbox:py + sbox, px - sbox:px + sbox] params = fitgaussian(data) fwhm = abs(2.355 * max(params[4], params[5]))
index_offset = 0 for index in range(nb_img): if detector == 1: rawdata[index, :, :], mask = remove_hotpixels_maxipix( rawdata[index, :, :], mask, hotpixels_file) rawdata[index, :, :], mask = mask_maxipix(rawdata[index, :, :], mask) flatfield[mask == 1] = 0 rawdata[index, :, :] = rawdata[index, :, :] * flatfield piy, pix = np.unravel_index(rawdata[index, :, :].argmax(), rawdata[index, :, :].shape) sum_data = sum_data + rawdata[index, :, :] if index not in frames_to_exclude: if use_rawdata == 0: y0, x0 = center_of_mass(rawdata[index, :, :]) data[index - index_offset, piy - window_ver:piy + window_ver + 1, pix - window_hor:pix + window_hor + 1, ] = rawdata[index, piy - window_ver:piy + window_ver + 1, pix - window_hor:pix + window_hor + 1, ] else: data[index - index_offset, :, :] = rawdata[index, :, :] delta[index - index_offset] = raw_delta[index] gamma[index - index_offset] = raw_gamma[index] else: index_offset = index_offset + 1 print("Frame index", str(index), "excluded") plt.ion() plt.figure() plt.imshow(np.log10(sum_data)) plt.title("Sum of all frames")
def contourcuts(image, maxdist=15, minrange=10, mincdist=20, sigma=1.0, debug=0, r=8, s=0.5): if debug: figure(1) clf() imshow(image) # start by computing the contours contours = image2contours(image != 0) # generate a mask for grayscale morphology mask = s * ones((r, r)) mask[2:-2, 2:-2] = 0 cuts = [] # now handle each (external) contour individually for k, cs in enumerate(contours): # compute a matrix of all the pairwise distances of pixels # around the contour, then smooth it a little ds = distance.cdist(cs, cs) ds = filters.gaussian_filter(ds, (sigma, sigma), mode='wrap') # compute a circulant matrix telling us the pathlength # between any two pixels on the contour n = len(cs) l = abs(arange(n) - n / 2.0) l = l[0] - l cds = linalg.circulant(l) # find true local minima (exclude ridges) by using the # structuring element above ge = morphology.grey_erosion(ds, structure=mask, mode='wrap') locs = (ds <= ge) # restrict it to pairs of points that are closer than maxdist locs *= (ds < maxdist) # restrict it to paris of points that are separated by # at least mincdist on the contour locs *= (cds >= mincdist) # label the remaining minima and locate them locs, n = measurements.label(locs) cms = measurements.center_of_mass(locs, locs, range(1, n + 1)) # keep only on of each pair (in canonical ordering) cms = [(int(i + 0.5), int(j + 0.5)) for i, j in cms if i < j] for i, j in cms: x0, y0 = cs[i] x1, y1 = cs[j] # keep only the near vertical ones if abs(y1 - y0) > abs(x1 - x0): color = 'r' cuts.append((cs[i], cs[j])) else: color = 'b' if debug: print(x0, y0), (x1, y1) figure(1) plot([x0, x1], [y0, y1], color) if debug: figure(2) clf() ion() imshow(locs != 0) figure(3) clf() imshow(minimum(ds, maxdist * 1.5), interpolation='nearest') ginput(1, 0.1) print "hit ENTER" raw_input() # now construct a cut image cutimage = zeros(image.shape) for ((x0, y0), (x1, y1)) in cuts: image_draw_line(cutimage, y0, x0, y1, x1) cutimage = filters.maximum_filter(cutimage, (3, 3)) if debug: figure(4) clf() imshow(maximum(0, image - 0.5 * cutimage)) return cutimage
cv2.destroyAllWindows() #%% threshold=95 imCrop[imCrop<threshold] = 0 f1lab,f1num = measurements.label(imCrop) f1slices = measurements.find_objects(f1lab) min_size=9 cal_points = [] for s, f1slice in enumerate(f1slices): imCopy = np.zeros(imCrop.shape) img_object = imCrop[f1slice]*(f1lab[f1slice]==(s+1)) obj_size = np.count_nonzero(img_object) #threshold objects based on size if obj_size > min_size: imCopy[f1slice] = img_object centroid = measurements.center_of_mass(imCopy) cal_points.append(np.array([s,f1slice,centroid[1]+0.5,centroid[0]+0.5])) cal_points=np.asarray(cal_points) #%% pts = 6 c = np.array([r[0],r[1]]) plt.figure(1) plt.pcolormesh((imCrop),cmap=cm.gray) plt.plot(cal_points[:,2],cal_points[:,3],'rx') print('Choose shared points between images') x=[] for i in range(0,pts): x0 = plt.ginput(1)[0] dist = (cal_points[:,3]-x0[1])**2+(cal_points[:,2]-x0[0])**2 (mindist, i0) = (dist.min(),np.where(dist==dist.min())[0])
def _get_intensities_summation_method( z, vectors, box_inner: int = 7, box_outer: int = 10, n_min: int = 5, n_max: int = None, snr_thresh=3.0, verbose: bool = False, ): """Integrate reflections using the summation method. Two boxes are defined, the inner box is used to define the integration area. The outer box is used to calculate the average signal-to-noise ratio (SNR). All pixels with a large enough SNR are considered to be signal. The largest region of connected signal pixels are summed to calculate the reflection intensity. Parameters ---------- vectors : DiffractionVectors Vectors to the locations of the spots to be integrated. box_inner : int Defines the radius (size) of the inner box, which must be larger than the reflection. The total box size is 2*box_inner box_outer : int Defines radius (size) of the outer box. The total box size is 2*box_inner The border between the inner and outer box is considered background and used to calculate the (SNR) for each pixel: SNR = (I - <I>/std(I_bkg)). snr_thresh : float Minimum signal-to-noise for a pixel to be considered as `signal`. n_min: int If the number of SNR pixels in the inner box < n_min, the reflection is discared n_max: If the number of SNR pixels in the inner box >= n_max, the reflection is discareded Defaults to the inner box size (`box_inner**2`. verbose : bool Print statistics for every reflection (for debugging) Returns ------- peaks : np.array Array with 4 columns: X-position, Y-position, intensity, reflection SNR Notes ----- Implementation based on Barty et al, J. Appl. Cryst. (2014). 47, 1118-1131 Lesli, Acta Cryst. (2006). D62, 48-57 """ if not n_max: # pragma: no cover n_max = box_inner ** 2 peaks = [] for i, j in vectors: box = z[j - box_inner : j + box_inner, i - box_inner : i + box_inner].copy() bkg = np.hstack( [ z[j - box_outer : j + box_outer, i - box_outer : i - box_inner].ravel(), z[j - box_outer : j + box_outer, i + box_inner : i + box_outer].ravel(), z[j - box_outer : j - box_inner, i - box_inner : i + box_inner].ravel(), z[j + box_inner : j + box_outer, i - box_inner : i + box_inner].ravel(), ] ) bkg_mean = bkg.mean() bkg_std = bkg.std() box_snr = (box - bkg_mean) / bkg_std # get mask for signal (I > SNR) signal_mask = _get_largest_connected_region(box_snr > snr_thresh) n_pix = signal_mask.sum() signal = (box - bkg_mean) * signal_mask inty = signal.sum() snr = (inty / n_pix) / bkg_std sigma = inty / snr # calculate center of mass com_X, com_Y = center_of_mass(box, labels=signal_mask, index=1) dX = com_X - box_inner dY = com_Y - box_inner X = i + dX Y = j + dY if verbose: # pragma: no cover print( f"\nMean(I): {bkg_mean:.2f} | Std(I): {bkg_std:.2f} | n_pix: {n_pix} \n" f"I: {inty:.2f} | Sigma(I): {sigma:.2f} | SNR(I): {snr:.2f} | I/pix: {inty/n_pix:.2f} \n" f"i: {i:.2f} | j: {j:.2f} | dX: {dX:.2f} | dY: {dY:.2f} | X: {X:.2f} | Y: {Y:.2f} " ) # for debugging purposes import matploltib.pyplot as plt plt.imshow(signal) plt.plot(dY + box_inner, dX + box_inner, "r+") # center_of_mass plt.plot(box_inner, box_inner, "g+") # input plt.show() if n_pix > n_max: # pragma: no cover continue if n_pix < n_min: # pragma: no cover continue # for some reason X/Y are reversed here peaks.append([Y, X, inty, sigma]) peaks = np.array(peaks) return np.array(peaks)
detector.pixelsize_y, detector.pixelsize_x, '(m)') diff_pattern = pu.bin_data(array=diff_pattern, binning=phasing_binning, debugging=False) mask = pu.bin_data(array=mask, binning=phasing_binning, debugging=False) numz, numy, numx = diff_pattern.shape # this shape will be used for the calculation of q values print( f'\nMeasured data shape = {numz}, {numy}, {numx}, Max(measured amplitude)={np.sqrt(diff_pattern).max():.1f}' ) diff_pattern[np.nonzero(mask)] = 0 ###################################################### # find the center of mass of the diffraction pattern # ###################################################### z0, y0, x0 = center_of_mass(diff_pattern) print(f'COM of measured pattern after masking: {z0:.2f}, {y0:.2f}, {x0:.2f}') # refine the COM in a small ROI centered on the approximate COM, to avoid detector gaps fine_com = center_of_mass(diff_pattern[int(z0) - 20:int(z0) + 21, int(y0) - 20:int(y0) + 21, int(x0) - 20:int(x0) + 21]) z0, y0, x0 = [ int(np.rint(z0 - 20 + fine_com[0])), int(np.rint(y0 - 20 + fine_com[1])), int(np.rint(x0 - 20 + fine_com[2])) ] print( f'refined COM: {z0}, {y0}, {x0}, Number of unmasked photons = {diff_pattern.sum():.0f}\n' ) fig, _, _ = gu.multislices_plot(np.sqrt(diff_pattern),
def mask_to_transform(seg, rotation=0.0, margin=0.0, radians=True, return_images=False): assert seg.ndim == 2 seg_original = seg.copy() seg = dv.binarize_array(seg) ## ## Calculate Useful Quantities ## ctr = [s // 2 for s in seg.shape] com = center_of_mass(seg) nrm = [ 2.0 * (i_com - i_ctr) / i_shp for i_com, i_ctr, i_shp in zip(com, ctr, seg.shape) ] ost = [-n * c for n, c in zip(nrm, ctr)] if radians: rotation = np.degrees(rotation) ## ## Translation ## seg_xy = itp.shift(seg, ost, order=0, mode="constant", cval=0) ## ## Rotation ## seg_rt = itp.rotate(seg_xy, rotation, reshape=False, order=0, mode="nearest") ## ## Zoom ## bbox = dv.bounding_box(seg_rt) scale = [(i_max - i_min) / i_shp for (i_min, i_max), i_shp in zip(bbox, seg.shape)] scale = max(scale) scale = min(1.0, scale + margin * 2.0) if return_images: seg_xy = itp.shift(seg_original, ost, order=0, mode="constant", cval=0) seg_rt = itp.rotate(seg_xy, rotation, reshape=False, order=0, mode="nearest") seg_zm = dv.crop_or_pad(itp.zoom(seg_rt, 1.0 / scale, order=0), seg.shape) return nrm, -np.radians(rotation), scale, seg_xy, seg_rt, seg_zm else: return nrm, -np.radians(rotation), scale
obj0, _ = util.load_file(file_path[0]) ndim = obj0.ndim if ndim != 3: print('3D objects are expected') sys.exit() nz, ny, nx = obj0.shape obj0 = pu.crop_pad(array=obj0, output_shape=(nz+10, ny+10, nx+10)) nz, ny, nx = obj0.shape print('Array shape', obj0.shape) amp0 = abs(obj0) sum0 = amp0.sum() phase0 = np.angle(obj0) if alignment_method in ['modulus', 'skip']: piz0, piy0, pix0 = center_of_mass(amp0) else: # 'support' support = np.zeros(amp0.shape) support[amp0 > support_threshold * amp0.max()] = 1 piz0, piy0, pix0 = center_of_mass(support) piz0, piy0, pix0 = int(piz0), int(piy0), int(pix0) phase0 = phase0 - phase0[piz0, piy0, pix0] # set the phase to 0 at the COM of the support obj0 = amp0 * np.exp(1j * phase0) stack = np.zeros((nbfiles, nz, ny, nx), dtype=complex) stack[0, :, :, :] = obj0 del amp0, phase0 gc.collect() for idx in range(1, nbfiles): print('\n' + os.path.basename(file_path[idx]))
def findBlobs(S,Thresh=None,EdgeBound=None): ''' Finds distinct blobs of a scalar that are bigger than a certain size (Thresh) Now new and improved! and much faster! Inputs: S - sets of 2D scalar fields that have already been thresholded (0s or 1s). The third dimension denotes the frame Thresh - Number of vectors that must be contained in a blob. If not defined, then no threshold filter will be used EdgeBound - Crops all blobs that are too close to the edge of the domain. No crop if left as none. Outputs: cent - labelled_array - The labeled array of blobs (in format of ndimage.measurements.label function). This is all the labels including the ones that might be too close to edge of domain num_features - Total number of features accross datasets features_per frame - Number of features identified in each frame ''' import numpy as np from scipy.ndimage.measurements import label,find_objects,center_of_mass uSize = S.shape if S.ndim == 3: str_3D=np.array([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 1, 0], [1, 1, 1], [0, 1, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], dtype='uint8') #str_3D = str_3D.transpose(2,1,0) labeled_array, num_features = label(S.transpose(2,1,0),str_3D) labeled_array = labeled_array.transpose(2,1,0) else: labeled_array, num_features = label(S) #print(np.unique(labeled_array)) #print(np.unique(labeled_array[:,:,0])) #print(labeled_array.shape) print('There are ', num_features, ' features identified') if Thresh is not None: loc = find_objects(labeled_array) labeled_array_out = labeled_array.copy() counts = np.bincount(labeled_array.ravel()) ind = np.where(counts>Thresh)[0][1:] mask = np.in1d(labeled_array.ravel(), ind).reshape(labeled_array.shape) labeled_array_out[~mask] = 0 [_, labeled_array_out] = np.unique(labeled_array_out,return_inverse=True) labeled_array_out = labeled_array_out.reshape(labeled_array.shape) num_features_out = len(ind) print('A total of ', num_features_out, ' are larger than the threshold size') else: labeled_array_out = labeled_array num_features_out = num_features features_per_frame = np.zeros(uSize[2],dtype=int); cent = []; for i in range(uSize[2]): features_per_frame[i] = len(np.unique(labeled_array_out[:,:,i])[1:]) cent.append(center_of_mass(S[:,:,i],labeled_array_out[:,:,i],np.unique(labeled_array_out[:,:,i])[1:])) #Round center locations to nearest index for i in range(len(cent)): for j in range(len(cent[i])): cent[i][j] = (int(round(cent[i][j][0])), int(round(cent[i][j][1]))) #Remove all centers too close to edge of domain if EdgeBound is not None: newCent = [] for i in range(len(cent)): newCent.append([]) features_per_frame[i] = 0 for j in range(len(cent[i])): if (cent[i][j][0]>EdgeBound-1 and cent[i][j][0]<uSize[0]-EdgeBound) and (cent[i][j][1]>EdgeBound-1 and cent[i][j][1] <uSize[1]-EdgeBound): newCent[i].append(cent[i][j]) features_per_frame[i]+=1 num_features_out = sum(features_per_frame) cent = newCent print('Of these', num_features_out, ' are far enough away from edge of domain') return [num_features_out, features_per_frame, labeled_array_out, cent]
import sys import os from PIL import Image, ImageFont, ImageDraw from matplotlib.pyplot import imshow import numpy as np from scipy.ndimage.measurements import center_of_mass image = Image.new("L", (80, 80), color=(1)) draw = ImageDraw.Draw(image) path = "data/train/wt004.ttf" #path = "data/train/NotoSansCJKtc-Light.otf" font = ImageFont.truetype(path, 64) #w, h = draw.textsize("的", font=font) #draw.text((40-w/2, 40-h/2), "的", font=font) draw.text((0, 10), "的", (255), font=font) print(center_of_mass(np.array(image))) image.show()
psf_partial_coh = abs(psf_partial_coh) / abs(psf_partial_coh).max() min_error_idx = np.unravel_index(error.argmin(), shape=(rl_iterations, ))[0] peaks, _ = find_peaks(-1 * error) if peaks.size == 1 and peaks[0] == rl_iterations - 1: print("no local minimum for this number of iterations") else: print(f"error local minima at iterations {peaks}") print(f"min error={error.min():.6f} at iteration {min_error_idx}\n") ############################################### # plot the retrieved psf and the error metric # ############################################### if center_method == "com": psf_cen = list( map(lambda x: int(np.rint(x)), center_of_mass(psf_partial_coh))) else: # 'max' psf_cen = list( map( int, np.unravel_index(psf_partial_coh.argmax(), shape=psf_partial_coh.shape), )) fig, _, _ = gu.multislices_plot( psf_partial_coh, scale="linear", sum_frames=False, title="psf", reciprocal_space=False, is_orthogonal=True,
def track_location( video_path, ref_frame, thresh=99, start_frame=0, stop_frame=None, crop_interactive=None, crop_cmin=None, crop_cmax=None, crop_rmin=None, crop_rmax=None, ): """ Track the location of the largest object in the frame. Tracking is performed by a method involving subtracting a reference frame from each frame and applying a threshold. Args: video_path (str): Path to the video ref_frame (arraylike): The reference frame to use. Can be generated from mfreeze.locolib.reference_create thresh (float): A value between 0 and 100. Change this value if the location parameter is performing poorly. start_frame (int): The first frame to use. stop_frame (int): The final frame to use. Defaults to the last frame. crop_interactive (holoviews.streams.BoxEdit): Holoviews stream object to use if using the interactive cropping functionality. This can be obtained from the mfreeze.video.crop function. crop_cmin (int): Optional value for manual cropping. Specifies minimum column value for each frame. crop_cmax (int): Optional value for manual cropping. Specifies maximum column value for each frame. crop_rmin (int): Optional value for manual cropping. Specifies minimum row value for each frame. crop_rmax (int): Optional value for manual cropping. Specifies maximum row values for each frame. Returns: The estimated position of the tracked object. A (n_frames, 2) numpy array with rows corresponding to the row and column position of the mouse for a given frame. """ cap = cv2.VideoCapture(video_path) stop_frame = (int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if stop_frame is None else stop_frame) num_frames = stop_frame - start_frame cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame) _, frame_old = cap.read() frame_old = cv2.cvtColor(frame_old, cv2.COLOR_BGR2GRAY) frame_nrow, frame_ncol = frame_old.shape using_crop, crop_settings = _parse_crop_settings( frame_nrow, frame_ncol, crop_interactive, crop_cmin, crop_cmax, crop_rmin, crop_rmax, ) if using_crop: frame_old = _crop_frame(frame_old, *crop_settings) x_y = np.empty((num_frames, 2)).astype("uint16") for i in range(num_frames - 1): frame_present, frame_new = cap.read() if frame_present: frame_new = cv2.cvtColor(frame_new, cv2.COLOR_BGR2GRAY) if using_crop: frame_new = _crop_frame(frame_new, *crop_settings) diff = cv2.absdiff(ref_frame, frame_new) diff[diff < np.percentile(diff, thresh)] = 0 x_y[i, :] = center_of_mass(diff) return x_y
def gen_instance_hv_map(ann, crop_shape): """Input annotation must be of original shape. The map is calculated only for instances within the crop portion but based on the original shape in original image. Perform following operation: Obtain the horizontal and vertical distance maps for each nuclear instance. """ orig_ann = ann.copy() # instance ID map fixed_ann = fix_mirror_padding(orig_ann) # re-cropping with fixed instance id map crop_ann = cropping_center(fixed_ann, crop_shape) # TODO: deal with 1 label warning crop_ann = morph.remove_small_objects(crop_ann, min_size=30) x_map = np.zeros(orig_ann.shape[:2], dtype=np.float32) y_map = np.zeros(orig_ann.shape[:2], dtype=np.float32) inst_list = list(np.unique(crop_ann)) inst_list.remove(0) # 0 is background for inst_id in inst_list: inst_map = np.array(fixed_ann == inst_id, np.uint8) inst_box = get_bounding_box(inst_map) # expand the box by 2px # Because we first pad the ann at line 207, the bboxes # will remain valid after expansion inst_box[0] -= 2 inst_box[2] -= 2 inst_box[1] += 2 inst_box[3] += 2 inst_map = inst_map[inst_box[0]:inst_box[1], inst_box[2]:inst_box[3]] if inst_map.shape[0] < 2 or inst_map.shape[1] < 2: continue # instance center of mass, rounded to nearest pixel inst_com = list(measurements.center_of_mass(inst_map)) inst_com[0] = int(inst_com[0] + 0.5) inst_com[1] = int(inst_com[1] + 0.5) inst_x_range = np.arange(1, inst_map.shape[1] + 1) inst_y_range = np.arange(1, inst_map.shape[0] + 1) # shifting center of pixels grid to instance center of mass inst_x_range -= inst_com[1] inst_y_range -= inst_com[0] inst_x, inst_y = np.meshgrid(inst_x_range, inst_y_range) # remove coord outside of instance inst_x[inst_map == 0] = 0 inst_y[inst_map == 0] = 0 inst_x = inst_x.astype("float32") inst_y = inst_y.astype("float32") # normalize min into -1 scale if np.min(inst_x) < 0: inst_x[inst_x < 0] /= -np.amin(inst_x[inst_x < 0]) if np.min(inst_y) < 0: inst_y[inst_y < 0] /= -np.amin(inst_y[inst_y < 0]) # normalize max into +1 scale if np.max(inst_x) > 0: inst_x[inst_x > 0] /= np.amax(inst_x[inst_x > 0]) if np.max(inst_y) > 0: inst_y[inst_y > 0] /= np.amax(inst_y[inst_y > 0]) #### x_map_box = x_map[inst_box[0]:inst_box[1], inst_box[2]:inst_box[3]] x_map_box[inst_map > 0] = inst_x[inst_map > 0] y_map_box = y_map[inst_box[0]:inst_box[1], inst_box[2]:inst_box[3]] y_map_box[inst_map > 0] = inst_y[inst_map > 0] hv_map = np.dstack([x_map, y_map]) return hv_map
def savgol_iaf(raw, picks=None, # noqa: C901 fmin=None, fmax=None, resolution=0.25, average=True, ax=None, window_length=11, polyorder=5, pink_max_r2=0.9): """Estimate individual alpha frequency (IAF). Parameters ---------- raw : instance of Raw The raw data to do these estimations on. picks : array-like of int | None List of channels to use. fmin : int | None Lower bound of alpha frequency band. If None, it will be empirically estimated using a polynomial fitting method to determine the edges of the central parabolic peak density, with assumed center of 10 Hz. fmax : int | None Upper bound of alpha frequency band. If None, it will be empirically estimated using a polynomial fitting method to determine the edges of the central parabolic peak density, with assumed center of 10 Hz. resolution : float The resolution in the frequency domain for calculating the PSD. average : bool Whether to average the PSD estimates across channels or provide a separate estimate for each channel. Currently, only True is supported. ax : instance of matplotlib Axes | None | False Axes to plot PSD analysis into. If None, axes will be created (and plot not shown by default). If False, no plotting will be done. window_length : int Window length in samples to use for Savitzky-Golay smoothing of PSD when estimating IAF. polyorder : int Polynomial order to use for Savitzky-Golay smoothing of PSD when estimating IAF. pink_max_r2 : float Maximum R^2 allowed when comparing the PSD distribution to the pink noise 1/f distribution on the range 1 to 30 Hz. If this threshold is exceeded, then IAF is assumed unclear and None is returned for both PAF and CoG. Returns ------- IafEst : instance of ``collections.namedtuple`` called IAFEstimate Named tuple with fields for the peak alpha frequency (PAF), alpha center of gravity (CoG), and the bounds of the alpha band (as a tuple). Notes ----- Based on method developed by `Andrew Corcoran <https://zenodo.org/badge/latestdoi/80904585>`_. In addition to appropriate software citation (Zenodo DOI or git commit), please cite: Corcoran, A. W., Alday, P. M., Schlesewsky, M., & Bornkessel-Schlesewsky, I. (2018). Toward a reliable, automated method of individual alpha frequency (IAF) quantification. Psychophysiology, e13064. doi:10.1111/psyp.13064 """ n_fft = int(raw.info['sfreq'] / resolution) psd, freqs = mne.time_frequency.psd_welch(raw, picks=picks, n_fft=n_fft, fmin=1., fmax=30.) if ax is None: fig = plt.figure() # noqa: F841 ax = plt.gca() if average: psd = np.mean(psd, axis=0) if fmin is None or fmax is None: if fmin is None: fmin_bound = 5 else: fmin_bound = fmin if fmax is None: fmax_bound = 15 else: fmax_bound = fmax alpha_search = np.logical_and(freqs >= fmin_bound, freqs <= fmax_bound) freqs_search = freqs[alpha_search] psd_search = savgol_filter(psd[alpha_search], window_length=psd[alpha_search].shape[0], polyorder=10) # argrel min returns a tuple, so we flatten that with [0] # then we get the last element of the resulting array with [-1] # which is the minimum closest to the 'median' alpha of 10 Hz if fmin is None: try: left_min = argrelmin(psd_search[freqs_search < 10])[0][-1] fmin = freqs_search[freqs_search < 10][left_min] except IndexError: raise ValueError("Unable to automatically determine lower end of alpha band.") # noqa: 501 if fmax is None: # here we want the first element of the array which is closest to # the 'median' alpha of 10 Hz try: right_min = argrelmin(psd_search[freqs_search > 10])[0][0] fmax = freqs_search[freqs_search > 10][right_min] except IndexError: raise ValueError("Unable to automatically determine upper end of alpha band.") # noqa: 501 psd_smooth = savgol_filter(psd, window_length=window_length, polyorder=polyorder) alpha_band = np.logical_and(freqs >= fmin, freqs <= fmax) slope, intercept, r, p, se = stats.linregress(np.log(freqs), np.log(psd_smooth)) if r**2 > pink_max_r2: paf = None cog = None else: paf_idx = np.argmax(psd_smooth[alpha_band]) paf = freqs[alpha_band][paf_idx] cog_idx = center_of_mass(psd_smooth[alpha_band]) try: cog_idx = int(np.round(cog_idx[0])) cog = freqs[alpha_band][cog_idx] except ValueError: cog = None # set PAF to None as well, because this is a pathological case paf = None if ax: plt_psd, = ax.plot(freqs, psd, label="Raw PSD") plt_smooth, = ax.plot(freqs, psd_smooth, label="Smoothed PSD") plt_pink, = ax.plot(freqs, np.exp(slope * np.log(freqs) + intercept), label='$1/f$ fit ($R^2={:0.2}$)'.format(r**2)) try: plt_search, = ax.plot(freqs_search, psd_search, label='Alpha-band Search Parabola') ax.legend(handles=[plt_psd, plt_smooth, plt_search, plt_pink]) except UnboundLocalError: # this happens when the user fully specified an alpha band ax.legend(handles=[plt_psd, plt_smooth, plt_pink]) ax.set_ylabel("PSD") ax.set_xlabel("Hz") return IafEst(paf, cog, (fmin, fmax))
def store_preloaded_hdf5_file( data_directories, output_filepath, modalities=['FLAIR_pp.nii.gz', 'T1post_pp.nii.gz'], label='full_edemamask_pp.nii.gz', verbose=True, levels=[4, 8, 16, 32, 64, 128], boundary_padding=10, max_dimension=64, samples_per_patient=100, preload_levels=False, wholevolume=False): patient_vols = [] for directory in data_directories: patients = glob.glob(os.path.join(directory, '*/')) for patient in patients: single_patient_vols = [] for modality in modalities + [label]: if modality is None: continue single_patient_vols += [ glob.glob(os.path.join(patient, modality))[0] ] patient_vols += [single_patient_vols] if wholevolume: num_cases = len(patient_vols) else: num_cases = len(modalities) * len(patient_vols) hdf5_file = tables.open_file(output_filepath, mode='w') filters = tables.Filters(complevel=5, complib='blosc') hdf5_file.create_earray(hdf5_file.root, 'imagenames', tables.StringAtom(256), shape=(0, 1), filters=filters, expectedrows=num_cases) # If we want to pre-store different levels... if preload_levels: for dimension in levels: data_shape = (0, dimension + boundary_padding, dimension + boundary_padding, dimension + boundary_padding, 2) hdf5_file.create_earray(hdf5_file.root, 'data_' + str(dimension), tables.Float32Atom(), shape=data_shape, filters=filters, expectedrows=num_cases) else: # If we don't. if wholevolume: data_shape = (0, 200, 200, 200, len(modalities)) else: data_shape = (0, max_dimension + boundary_padding, max_dimension + boundary_padding, max_dimension + boundary_padding, len(modalities)) print data_shape hdf5_file.create_earray(hdf5_file.root, 'data', tables.Float32Atom(), shape=data_shape, filters=filters, expectedrows=num_cases) for p_idx, single_patient_vols in enumerate(patient_vols): hdf5_file.root.imagenames.append( np.array(os.path.basename(os.path.dirname( single_patient_vols[0])))[np.newaxis][np.newaxis]) print os.path.basename(os.path.dirname(single_patient_vols[0])) if label is not None: # Find tumor label center of mass label = single_patient_vols[-1] label_numpy = convert_input_2_numpy(label) label_center = [int(x) for x in center_of_mass(label_numpy)] # Load volumes, volumes = np.stack([ convert_input_2_numpy(vol) for vol in single_patient_vols[:-1] ], axis=3) # pad if necessary, using black magic pad_dims = [] radius = (max_dimension + boundary_padding) / 2 for idx, dim in enumerate(volumes.shape[:-1]): padding = (-1 * min(0, label_center[idx] - radius), -1 * min(0, dim - (label_center[idx] + radius))) pad_dims += [padding] pad_dims += [(0, 0)] print pad_dims volumes = np.pad(volumes, pad_dims, mode='constant') # and subsample, with more black magic ;) print label_center label_center = [ x + pad_dims[i][0] for i, x in enumerate(label_center) ] print label_center print volumes.shape patch = volumes[label_center[0] - radius:label_center[0] + radius, label_center[1] - radius:label_center[1] + radius, label_center[2] - radius:label_center[2] + radius, :] print patch.shape # Add to HDF5 getattr(hdf5_file.root, 'data').append(patch[np.newaxis]) save_numpy_2_nifti( patch[..., 1], single_patient_vols[0], os.path.join(os.path.dirname(single_patient_vols[0]), 'gan_patch.nii.gz')) elif wholevolume: # Load volumes, volumes = np.stack( [convert_input_2_numpy(vol) for vol in single_patient_vols], axis=3) # Crop volumes volumes = crop2(volumes) large = False # Skip strangely processed volumes for dim in volumes.shape: if dim > 200: large = True if large: continue same_size_volume = np.zeros((200, 200, 200, len(modalities))) same_size_volume[0:volumes.shape[0], 0:volumes.shape[1], 0:volumes.shape[2], :] = volumes # Add to HDF5 getattr(hdf5_file.root, 'data').append(same_size_volume[np.newaxis]) else: # Generic MRI patching goes on here.. continue if verbose: print 'Processed...', os.path.basename( os.path.dirname(single_patient_vols[0])), 'idx', p_idx # except KeyboardInterrupt: # raise # except: # print 'ERROR converting', filepath, 'at dimension', dimension hdf5_file.close() return
def deep_segmentation_spinalcord(im_image, contrast_type, ctr_algo='cnn', ctr_file=None, brain_bool=True, kernel_size='2d', threshold_seg=None, remove_temp_files=1, verbose=1): """ Main pipeline for CNN-based segmentation of the spinal cord. :param im_image: :param contrast_type: {'t1', 't2', t2s', 'dwi'} :param ctr_algo: :param ctr_file: :param brain_bool: :param kernel_size: :param threshold_seg: Binarization threshold (between 0 and 1) to apply to the segmentation prediction. Set to -1 for no binarization (i.e. soft segmentation output) :param remove_temp_files: :param verbose: :return: """ if threshold_seg is None: threshold_seg = THR_DEEPSEG[contrast_type] # Display stuff logger.info("Config deepseg_sc:") logger.info(" Centerline algorithm: {}".format(ctr_algo)) logger.info(" Brain in image: {}".format(brain_bool)) logger.info(" Kernel dimension: {}".format(kernel_size)) logger.info(" Contrast: {}".format(contrast_type)) logger.info(" Threshold: {}".format(threshold_seg)) # create temporary folder with intermediate results tmp_folder = sct.TempFolder(verbose=verbose) tmp_folder_path = tmp_folder.get_path() if ctr_algo == 'file': # if the ctr_file is provided tmp_folder.copy_from(ctr_file) file_ctr = os.path.basename(ctr_file) else: file_ctr = None tmp_folder.chdir() # re-orient image to RPI logger.info("Reorient the image to RPI, if necessary...") original_orientation = im_image.orientation # fname_orient = 'image_in_RPI.nii' im_image.change_orientation('RPI') # Resample image to 0.5mm in plane im_image_res = \ resampling.resample_nib(im_image, new_size=[0.5, 0.5, im_image.dim[6]], new_size_type='mm', interpolation='linear') fname_orient = 'image_in_RPI_res.nii' im_image_res.save(fname_orient) # find the spinal cord centerline - execute OptiC binary logger.info("Finding the spinal cord centerline...") _, im_ctl, im_labels_viewer = find_centerline(algo=ctr_algo, image_fname=fname_orient, contrast_type=contrast_type, brain_bool=brain_bool, folder_output=tmp_folder_path, remove_temp_files=remove_temp_files, centerline_fname=file_ctr) if ctr_algo == 'file': im_ctl = \ resampling.resample_nib(im_ctl, new_size=[0.5, 0.5, im_image.dim[6]], new_size_type='mm', interpolation='linear') # crop image around the spinal cord centerline logger.info("Cropping the image around the spinal cord...") crop_size = 96 if (kernel_size == '3d' and contrast_type == 't2s') else 64 X_CROP_LST, Y_CROP_LST, Z_CROP_LST, im_crop_nii = crop_image_around_centerline(im_in=im_image_res, ctr_in=im_ctl, crop_size=crop_size) # normalize the intensity of the images logger.info("Normalizing the intensity...") im_norm_in = apply_intensity_normalization(im_in=im_crop_nii) del im_crop_nii if kernel_size == '2d': # segment data using 2D convolutions logger.info("Segmenting the spinal cord using deep learning on 2D patches...") segmentation_model_fname = \ os.path.join(sct.__sct_dir__, 'data', 'deepseg_sc_models', '{}_sc.h5'.format(contrast_type)) seg_crop = segment_2d(model_fname=segmentation_model_fname, contrast_type=contrast_type, input_size=(crop_size, crop_size), im_in=im_norm_in) elif kernel_size == '3d': # segment data using 3D convolutions logger.info("Segmenting the spinal cord using deep learning on 3D patches...") segmentation_model_fname = \ os.path.join(sct.__sct_dir__, 'data', 'deepseg_sc_models', '{}_sc_3D.h5'.format(contrast_type)) seg_crop = segment_3d(model_fname=segmentation_model_fname, contrast_type=contrast_type, im_in=im_norm_in) # Postprocessing seg_crop_postproc = np.zeros_like(seg_crop) x_cOm, y_cOm = None, None for zz in range(im_norm_in.dim[2]): # Fill holes (only for binary segmentations) if threshold_seg >= 0: pred_seg_th = fill_holes_2d((seg_crop[:, :, zz] > threshold_seg).astype(int)) pred_seg_pp = keep_largest_object(pred_seg_th, x_cOm, y_cOm) # Update center of mass for slice i+1 if 1 in pred_seg_pp: x_cOm, y_cOm = center_of_mass(pred_seg_pp) x_cOm, y_cOm = np.round(x_cOm), np.round(y_cOm) else: # If soft segmentation, do nothing pred_seg_pp = seg_crop[:, :, zz] seg_crop_postproc[:, :, zz] = pred_seg_pp # dtype is float32 # reconstruct the segmentation from the crop data logger.info("Reassembling the image...") im_seg = uncrop_image(ref_in=im_image_res, data_crop=seg_crop_postproc, x_crop_lst=X_CROP_LST, y_crop_lst=Y_CROP_LST, z_crop_lst=Z_CROP_LST) # seg_uncrop_nii.save(sct.add_suffix(fname_res, '_seg')) # for debugging del seg_crop, seg_crop_postproc, im_norm_in # resample to initial resolution logger.info("Resampling the segmentation to the native image resolution using linear interpolation...") im_seg_r = resampling.resample_nib(im_seg, image_dest=im_image, interpolation='linear') if ctr_algo == 'viewer': # for debugging im_labels_viewer.save(sct.add_suffix(fname_orient, '_labels-viewer')) # Binarize the resampled image (except for soft segmentation, defined by threshold_seg=-1) if threshold_seg >= 0: logger.info("Binarizing the resampled segmentation...") im_seg_r.data = (im_seg_r.data > 0.5).astype(np.uint8) # post processing step to z_regularized im_seg_r_postproc = post_processing_volume_wise(im_seg_r) # Change data type. By default, dtype is float32 if threshold_seg >= 0: im_seg_r_postproc.change_type(np.uint8) tmp_folder.chdir_undo() # remove temporary files if remove_temp_files: logger.info("Remove temporary files...") tmp_folder.cleanup() # reorient to initial orientation im_seg_r_postproc.change_orientation(original_orientation) # copy q/sform from input image to output segmentation im_seg.copy_qform_from_ref(im_image) return im_seg_r_postproc, im_image_res, im_seg.change_orientation('RPI')
def Case5(AvgFlux, X,Y,Spacing=1): Spacing = int(Spacing) Xint, Yint = [int(round(X,0)), int(round(Y,0))] BkgVal = np.median(AvgFlux) XValues = np.arange(Xint-Spacing,Xint+Spacing+1,1) YValues = np.arange(Yint-Spacing,Yint+Spacing+1,1) ReferenceValue = 0 Dist_tolerance = 0.75 for i,j in list(itertools.product(XValues,YValues)): try: TempAper2_2 = np.zeros((len(AvgFlux),len(AvgFlux[0]))) TempAper2_2[i:i+2, j:j+2] = 1 Num = np.sum(TempAper2_2) Signal = np.sum(AvgFlux*TempAper2_2)-Num*BkgVal Y_Cen, X_Cen = measurements.center_of_mass(AvgFlux*TempAper2_2) Distance = np.sqrt((X- X_Cen)**2+(Y- Y_Cen)**2) if Distance<Dist_tolerance: Value2_2 = Signal/np.sqrt(Signal+ (Num+1)*BkgVal) else: Value2_2 = 1 except: Value2_2 = 1 try: TempAper2_3 = np.zeros(len(AvgFlux[0])*len(AvgFlux)).reshape(len(AvgFlux),len(AvgFlux[0])) TempAper2_3[i:i+2, j:j+3] = 1 Num = np.sum(TempAper2_3) Signal = np.sum(AvgFlux*TempAper2_3)-Num*BkgVal Y_Cen, X_Cen = measurements.center_of_mass(AvgFlux*TempAper2_3) Distance = np.sqrt((X- X_Cen)**2+(Y- Y_Cen)**2) if Distance<Dist_tolerance: Value2_3 = Signal/np.sqrt(Signal+(Num+1)*BkgVal) else: Value2_3 = 2 except: Value2_3 = 2 try: TempAper3_2 = np.zeros(len(AvgFlux[0])*len(AvgFlux)).reshape(len(AvgFlux),len(AvgFlux[0])) TempAper3_2[i:i+3, j:j+2] = 1 Num = np.sum(TempAper3_2) Value3_2 = np.sum(AvgFlux*TempAper3_2)-Num*BkgVal Y_Cen, X_Cen = measurements.center_of_mass(AvgFlux*TempAper3_2) Distance = np.sqrt((X- X_Cen)**2+(Y- Y_Cen)**2) if Distance<Dist_tolerance: Value3_2 = Signal/np.sqrt(Signal+(Num+1)*BkgVal) else: Value3_2 = 3 except: Value3_2 = 3 try: TempAper3_3 = np.zeros(len(AvgFlux[0])*len(AvgFlux)).reshape(len(AvgFlux),len(AvgFlux[0])) TempAper3_3[i:i+3, j:j+3] = 1 Num = np.sum(TempAper3_3) Signal = np.sum(AvgFlux*TempAper3_3)-Num*BkgVal Y_Cen, X_Cen = measurements.center_of_mass(AvgFlux*TempAper3_3) Distance = np.sqrt((X- X_Cen)**2+(Y- Y_Cen)**2) if Distance<Dist_tolerance: Value3_3 = Signal/np.sqrt(Signal+(Num+1)*BkgVal) else: Value3_3 = 4 except: Value3_3 = 4 #star like shaped with five selection try: TempAper_Star = np.zeros(len(AvgFlux[0])*len(AvgFlux)).reshape(len(AvgFlux),len(AvgFlux[0])) TempAper_Star[i+1:i+2, j:j+3] = 1 TempAper_Star[i:i+3, j+1:j+2] = 1 Num = np.sum(TempAper_Star) Signal = np.sum(AvgFlux*TempAper_Star)-Num*BkgVal Y_Cen, X_Cen = measurements.center_of_mass(AvgFlux*TempAper_Star) Distance = np.sqrt((X- X_Cen)**2+(Y- Y_Cen)**2) if Distance<Dist_tolerance: Value_Star = Signal/np.sqrt(Signal+(Num+1)*BkgVal) else: Value_Star = 5 except: Value_Star = 5 #See which one is the best fit Values = np.array([Value2_2, Value2_3, Value3_2, Value3_3, Value_Star]) MaxValue = max(Values) if MaxValue>ReferenceValue: ReferenceValue = MaxValue RefX, RefY = [i,j] TypeAperture = np.where(MaxValue == Values)[0][0] if ReferenceValue<7: #Find suitable 4 by 4 aperture based on distance print "-"*50 print "Failed to find a good aperture" print "-"*50 #Aperture just based on the distance RefX, RefY = [Xint, Yint] DistanceRef = 5 for i,j in list(itertools.product(XValues,YValues)): try: TempAper2_2 = np.zeros(len(AvgFlux[0])*len(AvgFlux)).reshape(len(AvgFlux),len(AvgFlux[0])) TempAper2_2[i:i+2, j:j+2] = 1 Y_Cen, X_Cen = measurements.center_of_mass(AvgFlux*TempAper2_2) Distance = np.sqrt((X- X_Cen)**2+(Y- Y_Cen)**2) if Distance<DistanceRef: RefX,RefY = [i,j] DistanceRef = Distance except: pass TypeAperture = 0 Aperture = np.zeros(len(AvgFlux[0])*len(AvgFlux)).reshape(len(AvgFlux),len(AvgFlux[0])) i,j = [RefX, RefY] if TypeAperture == 0: Aperture[i:i+2,j:j+2] = 1 elif TypeAperture == 1: Aperture[i:i+2, j:j+3] = 1 elif TypeAperture == 2: Aperture[i:i+3, j:j+2] = 1 elif TypeAperture == 3: Aperture[i:i+3, j:j+3] = 1 elif TypeAperture == 4: Aperture[i+1:i+2, j:j+3] = 1 Aperture[i:i+3, j+1:j+2] = 1 else: raise Exception('Error finding a good aperture') return Aperture
def fit_nema_2008_cylinder_profiles(vol, voxsize, Rrod_init = [2.5,2,1.5,1,0.5], fwhm_init = 1.5, S_init = 1, fix_S = True, fix_R = False, fix_fwhm = False, nrods = 4, phantom = 'standard'): """ Fit the radial profiles of the rods in a nema 2008 small animal PET phantom Parameters ---------- vol : 3D numpy float array containing the image voxsize : 3 element 1D numpy array containing the voxel size Rrod_init : list or 1D numpy array of floats, optional containing the initial values of the rod radii S_init, fwhm_init: float, optional initial values for the signal and the FWHM in the fit fix_S, fix_R, fix_fwhm : bool, optional whether to keep the initial values of signal, radius and FWHM fixed during the fix nrods: int, optional number of rods to fit phantom : string phantom version ('standard' or 'mini') Returns ------- a list of lmfit fit results Note ---- The axial direction should be the right most direction in the 3D numpy array. The slices containing the rods are found automatically and summed. In the summed image, all rods (disks) are segmented followed by a fit of the radial profile. """ roi_vol = nema_2008_small_animal_pet_rois(vol, voxsize, phantom = phantom) rod_bbox = find_objects(roi_vol==4) # find the rods in the summed image sum_img = vol[:,:,rod_bbox[0][2].start:rod_bbox[0][2].stop].mean(2) label_img, nlab = label(sum_img > 0.1*sum_img.max()) labels = np.arange(1,nlab+1) # sort the labels according to volume npix = labeled_comprehension(sum_img, label_img, labels, len, int, 0) sort_inds = npix.argsort()[::-1] labels = labels[sort_inds] npix = npix[sort_inds] #---------------------------------------------------------------------- ncols = 2 nrows = int(np.ceil(nrods/ncols)) fig, ax = py.subplots(nrows,ncols,figsize = (12,7*nrows/2), sharey = True, sharex = True) retval = [] for irod in range(nrods): rod_bbox = find_objects(label_img == labels[irod]) rod_bbox = [(slice(rod_bbox[0][0].start - 2,rod_bbox[0][0].stop + 2), slice(rod_bbox[0][1].start - 2,rod_bbox[0][1].stop + 2))] rod_img = sum_img[rod_bbox[0]] com = np.array(center_of_mass(rod_img)) x0 = (np.arange(rod_img.shape[0]) - com[0]) * voxsize[0] x1 = (np.arange(rod_img.shape[1]) - com[1]) * voxsize[1] X0, X1 = np.meshgrid(x0, x1, indexing = 'ij') RHO = np.sqrt(X0**2 + X1**2) rho = RHO.flatten() signal = rod_img.flatten() # sort the values according to rho sort_inds = rho.argsort() rho = rho[sort_inds] signal = signal[sort_inds] pmodel = Model(cylinder_profile) params = pmodel.make_params(S = S_init, R = Rrod_init[irod], fwhm = fwhm_init) if fix_S: params['S'].vary = False if fix_R: params['R'].vary = False if fix_fwhm: params['fwhm'].vary = False fitres = pmodel.fit(signal, r = rho, params = params) retval.append(fitres) fit_report = fitres.fit_report() iplot = np.unravel_index(irod, ax.shape) ax[iplot].plot(rho,signal,'k.') rfit = np.linspace(0,rho.max(),100) ax[iplot].plot(rfit,fitres.eval(r = rfit),'r-') ax[iplot].text(0.99, 0.99, fit_report, fontsize = 6, transform = ax[iplot].transAxes, verticalalignment='top', horizontalalignment = 'right', backgroundcolor = 'white', bbox = {'pad':0, 'facecolor':'white','lw':0}) ax[iplot].grid() for axx in ax[-1,:]: axx.set_xlabel('R (mm)') for axx in ax[:,0]: axx.set_ylabel('signal') fig.tight_layout() fig.show() return retval
def get_patches_and_vectors(I, bx, by, bz, pixel_limit=20, thr=0.5, floodfill=4): ''' I - intensity map for detecting pores; should be normalized to quiet sun bx - bx data (should be Bp from sharps) type should be sunpy map by - by data (should be Bt from sharps) type should be sunpy map. DO NOT CHANGE SIGN OF DATA, THIS FUNCTION WILL DO IT! bz - bz data (should be Br from sharps) type should be sunpy map pixel_limit - ignore patches that are smaller than this size thr - if I < thr => we assign it as pixel of interes; if data is normalized, 0.5 should work floodfill - in how many direction structure should perform flood fill https://en.wikipedia.org/wiki/Flood_fill floodfill = 4 looks in 4 direction and search structure looks like this [[0,1,0], [1,1,1], [0,1,0]] floodfill = 8 looks in 8 direction and search structure looks like this [[1,1,1], [1,1,1], [1,1,1]] Returns: This function returns two arrays: RETURN_MATRIX - Matrix that has data for patches center in dims [6xN] where N is number of patches. It is of folowing structure c_x[pix], c_y[pix], <Bx>[G], <By>[G], <Bz>[G], A[pixel_count] If there is no patches, this matrix is empty labeled_array - Matrix of same size as input intensity image if there are no patches this matrix is filled with zeros ''' # Create masked array from I data if floodfill == 8: print("Using 8 directions search map %s" % (I.name)) s = generate_binary_structure(2, 2) else: print("Using 4 directions search map on %s" % (I.name)) s = generate_binary_structure(2, 1) X = np.ma.masked_where((I.data <= thr) & (I.data > 0), I.data) #LOL! #So, if mask is false (nothing satisfies condition), and you use structure in label #it will crash because its comparing structure off size [3,3] with 1D array #So lets handle it right here #And its faster at the end, we are leaving function right here if not X.mask.any(): return np.zeros([]), np.zeros([I.data.shape[0], I.data.shape[1]]) try: # sometimes this fails because of endianness # Select regions based on structures # labeled array is same dimension as input image labeled_array, num_features = label(X.mask, structure=s) except: labeled_array, num_features = label(X.mask.newbyteorder(), structure=s) # find how many pixel is in each patch regions, counts = np.unique(labeled_array, return_counts=True) # if pixel count for patch is smaller then pixel_limit # This labels of patches with small pixel count remove_patches = (counts < pixel_limit).nonzero()[0] # Set it to zero for i in remove_patches: labeled_array[labeled_array == i] = 0 # THIS IS LAZY PROGRAMMING!!! DONT DO THIS! # i wanted smooth region labelin (0,1,2,3,4) not gapped (0,1,4,6,7), i could do that manually, but im lazy # I cant overwrite labeled_array variable because im using it later in cmass labeled_array1, num_features1 = label(labeled_array) #print(num_featurues) #Check again if we removed all features because of trh for region of interest #I tought that we are smarter than nested if/elif/else if num_features1 == 0: return np.zeros([]), np.zeros([I.data.shape[0], I.data.shape[1]]) ####### # lets calculate centers of patches # Actuall patches are marked as 1 and above, 0 is background elif num_features1 == 1: features_label = np.array([1]) else: #it has to be +1 because arange(1,2,1) returns np.array([1]) #so we are missing some data features_label = np.arange(1, num_features1 + 1, 1) cmass = center_of_mass(labeled_array, labeled_array1, features_label) # print(labeled_array) # Create placeholder matrix that has # cx[pix], cy[pix], <bx>[G], <by>[G], <bz>[G], A[pix_count] # #because 0 is not feature we are interested in #print(num_features1) RETURN_MATRIX = np.zeros([num_features1, 6]) regions1, counts1 = np.unique(labeled_array1, return_counts=True) for pore_index in features_label: # valid pixels for that pore index over which we should average valid_pixels = np.argwhere(labeled_array1 == pore_index) RETURN_MATRIX[pore_index - 1][0] = cmass[pore_index - 1][1] RETURN_MATRIX[pore_index - 1][1] = cmass[pore_index - 1][0] RETURN_MATRIX[pore_index - 1][2] = np.mean(bx.data[valid_pixels[:, 0], valid_pixels[:, 1]]) #Note that here we are using -by because Bt = -By RETURN_MATRIX[pore_index - 1][3] = np.mean(-by.data[valid_pixels[:, 0], valid_pixels[:, 1]]) RETURN_MATRIX[pore_index - 1][4] = np.mean(bz.data[valid_pixels[:, 0], valid_pixels[:, 1]]) #Pixel count RETURN_MATRIX[pore_index - 1][5] = counts1[pore_index] return RETURN_MATRIX, labeled_array1
def initialize_components(Y, K=30, gSig=[5, 5], gSiz=None, ssub=1, tsub=1, nIter=5, maxIter=5, nb=1, kernel=None, use_hals=True, normalize_init=True, img=None, method='greedy_roi', max_iter_snmf=500, alpha_snmf=10e2, sigma_smooth_snmf=(.5, .5, .5), perc_baseline_snmf=20, options_local_NMF=None): """Initalize components This method uses a greedy approach followed by hierarchical alternative least squares (HALS) NMF. Optional use of spatio-temporal downsampling to boost speed. Parameters ---------- Y: np.ndarray d1 x d2 [x d3] x T movie, raw data. K: [optional] int number of neurons to extract (default value: 30). tau: [optional] list,tuple standard deviation of neuron size along x and y [and z] (default value: (5,5). gSiz: [optional] list,tuple size of kernel (default 2*tau + 1). nIter: [optional] int number of iterations for shape tuning (default 5). maxIter: [optional] int number of iterations for HALS algorithm (default 5). ssub: [optional] int spatial downsampling factor recommended for large datasets (default 1, no downsampling). tsub: [optional] int temporal downsampling factor recommended for long datasets (default 1, no downsampling). kernel: [optional] np.ndarray User specified kernel for greedyROI (default None, greedy ROI searches for Gaussian shaped neurons) use_hals: [optional] bool Whether to refine components with the hals method normalize_init: [optional] bool Whether to normalize_init data before running the initialization img: optional [np 2d array] Image with which to normalize. If not present use the mean + offset method: str Initialization method 'greedy_roi' or 'sparse_nmf' max_iter_snmf: int Maximum number of sparse NMF iterations alpha_snmf: scalar Sparsity penalty Returns -------- Ain: np.ndarray (d1*d2[*d3]) x K , spatial filter of each neuron. Cin: np.ndarray T x K , calcium activity of each neuron. center: np.ndarray K x 2 [or 3] , inferred center of each neuron. bin: np.ndarray (d1*d2[*d3]) x nb, initialization of spatial background. fin: np.ndarray nb x T matrix, initalization of temporal background. """ if method == 'local_nmf': tsub_lnmf = tsub ssub_lnmf = ssub tsub = 1 ssub = 1 if gSiz is None: gSiz = 2 * np.asarray(gSig) + 1 d, T = np.shape(Y)[:-1], np.shape(Y)[-1] # rescale according to downsampling factor gSig = np.round(np.asarray(gSig) / ssub).astype(np.int) gSiz = np.round(np.asarray(gSiz) / ssub).astype(np.int) print('Noise Normalization') if normalize_init is True: if img is None: img = np.mean(Y, axis=-1) img += np.median(img) Y = old_div(Y, np.reshape(img, d + (-1, ), order='F')) alpha_snmf /= np.mean(img) # spatial downsampling mean_val = np.mean(Y) if ssub != 1 or tsub != 1: print("Spatial Downsampling ...") Y_ds = downscale_local_mean(Y, tuple([ssub] * len(d) + [tsub]), cval=mean_val) else: Y_ds = Y print('Roi Extraction...') if method == 'greedy_roi': Ain, Cin, _, b_in, f_in = greedyROI(Y_ds, nr=K, gSig=gSig, gSiz=gSiz, nIter=nIter, kernel=kernel, nb=nb) if use_hals: print('Refining Components...') Ain, Cin, b_in, f_in = hals(Y_ds, Ain, Cin, b_in, f_in, maxIter=maxIter) elif method == 'sparse_nmf': Ain, Cin, _, b_in, f_in = sparseNMF(Y_ds, nr=K, nb=nb, max_iter_snmf=max_iter_snmf, alpha=alpha_snmf, sigma_smooth=sigma_smooth_snmf, remove_baseline=True, perc_baseline=perc_baseline_snmf) # print np.sum(Ain), np.sum(Cin) # print 'Refining Components...' # Ain, Cin, b_in, f_in = hals(Y_ds, Ain, Cin, b_in, f_in, maxIter=maxIter) # print np.sum(Ain), np.sum(Cin) elif method == 'pca_ica': Ain, Cin, _, b_in, f_in = ICA_PCA(Y_ds, nr = K, sigma_smooth=sigma_smooth_snmf, truncate = 2, fun='logcosh',\ max_iter=max_iter_snmf, tol=1e-10,remove_baseline=True, perc_baseline=perc_baseline_snmf, nb=nb) elif method == 'local_nmf': from SourceExtraction.CNMF4Dendrites import CNMF4Dendrites from SourceExtraction.AuxilaryFunctions import GetCentersData #Get initialization for components center print(Y_ds.transpose([2, 0, 1]).shape) if options_local_NMF is None: raise Exception('You need to define arguments for local NMF') # #Define CNMF parameters # mbs=[tsub_lnmf] # temporal downsampling of data in intial phase of NMF # ds=ssub_lnmf # spatial downsampling of data in intial phase of NMF. Ccan be an integer or a list of the size of spatial dimensions # TargetAreaRatio=[0.01,0.06] # target sparsity range for spatial components # #repeats=1 # how many repeations to run NMF algorithm # iters0=[5] #30 number of intial NMF iterations, in which we downsample data and add components # iters=20 #100 number of main NMF iterations, in which we fine tune the components on the full data # lam1_s=10# l1 regularization parameter initialization (for increased sparsity). If zero, we have no l1 sparsity penalty # bkg_per=0.1 # intialize of background shape at this percentile (over time) of video # sig=Y_ds.shape[:-1] # estiamte size of neuron - bounding box is 3 times this size. If larger then data, we have no bounding box. # MergeThreshold_activity=0.85#merge components if activity is correlated above the this threshold (and sufficiently close) # MergeThreshold_shapes=0.99 #merge components if activity is correlated above the this threshold (and sufficiently close) # Connected=True # should we constrain all spatial component to be connected? # SigmaMask=3 # if not [], then update masks so that they are non-zero a radius of SigmaMasks around previous non-zero support of shapes #Get initialization for components center # NumCent=400 # Max number of centers to import from Group Lasso intialization - if 0, we don't run group lasso # cent=GetCentersData(Y_ds.transpose([2,0,1]),NumCent) # # #Define CNMF parameters # mbs=[10] # temporal downsampling of data in intial phase of NMF # ds=1 # spatial downsampling of data in intial phase of NMF. Ccan be an integer or a list of the size of spatial dimensions # TargetAreaRatio=[0.01,0.06] # target sparsity range for spatial components # #repeats=1 # how many repeations to run NMF algorithm # iters0=[5] #30 number of intial NMF iterations, in which we downsample data and add components # iters=20 #100 number of main NMF iterations, in which we fine tune the components on the full data # lam1_s=10# l1 regularization parameter initialization (for increased sparsity). If zero, we have no l1 sparsity penalty # updateLambdaIntervals=2 # update sparsity parameter every updateLambdaIntervals iterations # addComponentsIntervals=1 # in initial NMF phase, add new component every updateLambdaIntervals*addComponentsIntervals iterations # updateRhoIntervals=1 # in main NMF phase, update sparsity learning speed (Rho) every updateLambdaIntervals*updateRhoIntervals iterations # Background_num=1 #number of background components - one of which at every repetion # bkg_per=0.1 # intialize of background shape at this percentile (over time) of video # sig=Y_ds.shape[:-1] # estiamte size of neuron - bounding box is 3 times this size. If larger then data, we have no bounding box. # MergeThreshold_activity=0.85#merge components if activity is correlated above the this threshold (and sufficiently close) # MergeThreshold_shapes=0.99 #merge components if activity is correlated above the this threshold (and sufficiently close) # Connected=True # should we constrain all spatial component to be connected? # SigmaMask=3 # if not [], then update masks so that they are non-zero a radius of SigmaMasks around previous non-zero support of shapes # cnmf_obj=CNMF4Dendrites(sig=sig, verbose=True,adaptBias=True,TargetAreaRatio=TargetAreaRatio, # Connected=Connected, SigmaMask=SigmaMask,bkg_per=bkg_per,iters=iters,iters0=iters0, mbs=mbs, # ds=ds,lam1_s=lam1_s,MergeThreshold_activity=MergeThreshold_activity,MergeThreshold_shapes=MergeThreshold_shapes) else: NumCent = options_local_NMF.pop( 'NumCent', None ) # Max number of centers to import from Group Lasso intialization - if 0, we don't run group lasso cent = GetCentersData(Y_ds.transpose([2, 0, 1]), NumCent) sig = Y_ds.shape[: -1] # estiamte size of neuron - bounding box is 3 times this size. If larger then data, we have no bounding box. cnmf_obj = CNMF4Dendrites(sig=sig, verbose=True, adaptBias=True, **options_local_NMF) #Define CNMF parameters _, _, _ = cnmf_obj.fit( np.array(Y_ds.transpose([2, 0, 1]), dtype=np.float), cent) Ain = cnmf_obj.A Cin = cnmf_obj.C b_in = cnmf_obj.b f_in = cnmf_obj.f # Cin, _, b_in, f_in = ICA_PCA(Y_ds, nr = K, sigma_smooth=sigma_smooth_snmf, truncate = 2, fun='logcosh',\ # max_iter=max_iter_snmf, tol=1e-10,remove_baseline=True, perc_baseline=perc_baseline_snmf, nb=nb) else: print(method) raise Exception("Unsupported method") K = np.shape(Ain)[-1] ds = Y_ds.shape[:-1] Ain = np.reshape(Ain, ds + (K, ), order='F') if len(ds) == 2: Ain = resize(Ain, d + (K, ), order=1) else: # resize only deals with 2D images, hence apply resize twice Ain = np.reshape([resize(a, d[1:] + (K, ), order=1) for a in Ain], (ds[0], d[1] * d[2], K), order='F') Ain = resize(Ain, (d[0], d[1] * d[2], K), order=1) Ain = np.reshape(Ain, (np.prod(d), K), order='F') #import pdb # pdb.set_trace() b_in = np.reshape(b_in, ds + (nb, ), order='F') if len(ds) == 2: b_in = resize(b_in, d + (nb, ), order=1) else: b_in = np.reshape([resize(b, d[1:] + (nb, ), order=1) for b in b_in], (ds[0], d[1] * d[2], nb), order='F') b_in = resize(b_in, (d[0], d[1] * d[2], nb), order=1) b_in = np.reshape(b_in, (np.prod(d), nb), order='F') Cin = resize(Cin, [K, T]) f_in = resize(np.atleast_2d(f_in), [nb, T]) # center = com(Ain, *d) center = np.asarray( [center_of_mass(a.reshape(d, order='F')) for a in Ain.T]) if normalize_init is True: #import pdb # pdb.set_trace() Ain = Ain * np.reshape(img, (np.prod(d), -1), order='F') b_in = b_in * np.reshape(img, (np.prod(d), -1), order='F') # b_in = np.atleast_2d(b_in * img.flatten('F')) #np.reshape(img, # (np.prod(d), -1),order='F') Y = Y * np.reshape(img, d + (-1, ), order='F') return Ain, Cin, b_in, f_in, center
prediction[prediction < THRESHOLD] = 0 # thresholding prediction[prediction > 0] = 1 prediction = prediction.reshape(324, 324) # localize the center of nodule if np.amax(prediction) > 0: centers = [] #erosion selem = morphology.disk(1) image_eroded = morphology.binary_erosion( prediction, selem=selem) label_im, nb_labels = ndimage.label(image_eroded) for i in xrange(1, nb_labels + 1): blob_i = np.where(label_im == i, 1, 0) mass = center_of_mass(blob_i) centers.append([mass[1], mass[0]]) for center in centers: world_coords = voxel_2_world( np.asarray( [center[0], center[1], slice_index]), np.asarray(origin), np.asarray([1, 1, 1])) resnet_coords = world_2_voxel( np.asarray(world_coords), np.asarray(origin), np.asarray(OUTPUT_SPACING)) resnet_coords = np.floor(resnet_coords).astype( 'int16') # print world_coords, resnet_coords
def display_masks(anns, colors, im_height=448, im_width=448, no_display_text=False, display_route=False): """Display annotations in image.""" if len(anns) == 0: return 0 ax = plt.gca() box_width = 30 box_height = 10 ax.set_autoscale_on(False) xdata = [] ydata = [] for i, ann in enumerate(anns): if display_route: display_txt = "%d" % (i) else: display_txt = "%d: %s. %.2f" % (i, ann['category_name'], ann['score']) if 'ignore' in ann: if ann['ignore'] == 1: continue display_txt = ann['category_name'] if display_txt == 'motorbike': display_txt = 'motor' elif display_txt == 'bicycle': display_txt = 'bike' elif display_txt == 'dining table': display_txt = 'table' elif display_txt == 'potted plant': display_txt = 'plant' elif display_txt == 'airplane': display_txt = 'plane' if type(ann['segmentation']['counts']) == list: rle = mask.frPyObjects([ann['segmentation']], im_height, im_width) else: rle = [ann['segmentation']] m = mask.decode(rle) y, x = center_of_mass(m.squeeze()) x = max(0, x - box_width) y = max(0, y - box_height) y = min(m.shape[0] - box_height, y) x = min(m.shape[1] - box_width, x) xdata.append(x) ydata.append(y) img = np.ones((m.shape[0], m.shape[1], 3)) color_mask = np.array(colors[i]) / 255.0 for i in range(3): img[:, :, i] = color_mask[i] ax.imshow(np.dstack((img, m * 0.5))) if not no_display_text: ax.text(x, y, display_txt, bbox={ 'facecolor': color_mask, 'alpha': 0.6 }) xdata = np.array(xdata) ydata = np.array(ydata) if display_route: line = matplotlib.lines.Line2D(xdata, ydata, color='r', linewidth=1) ax = plt.subplot(111) ax.add_line(line)
data[np.isnan(data)] = 0 mask[np.isnan(mask)] = 1 # check for Inf mask[np.isinf(data)] = 1 data[np.isinf(data)] = 0 mask[np.isinf(mask)] = 1 data[mask == 1] = 0 if save_asint: data = data.astype(int) #################### # debugging plots # #################### if debug: z0, y0, x0 = center_of_mass(data) fig, _, _ = gu.multislices_plot(data, sum_frames=False, scale='log', plot_colorbar=True, vmin=0, title='Masked data', slice_position=[int(z0), int(y0), int(x0)], is_orthogonal=not use_rawdata, reciprocal_space=True) plt.savefig(savedir + 'middle_frame_S' + str(scans[scan_nb]) + '_' + str(nz) + '_' + str(ny) + '_' + str(nx) + binning_comment + '.png') if not flag_interact: plt.close(fig) fig, _, _ = gu.multislices_plot(data, sum_frames=True, scale='log', plot_colorbar=True, vmin=0, title='Masked data', is_orthogonal=not use_rawdata, reciprocal_space=True) plt.savefig(savedir + 'sum_S' + str(scans[scan_nb]) + '_' + str(nz) + '_' + str(ny) + '_' + str(nx) + binning_comment + '.png') if not flag_interact: plt.close(fig)
plt.axis('scaled') plt.title("phase after ramp removal") plt.pause(0.1) #################### # remove phase offset #################### support = np.zeros(amp.shape) support[amp > 0.05] = 1 plt.figure() plt.imshow(support, cmap=my_cmap) plt.colorbar() plt.axis('scaled') plt.title("support used for offset removal") plt.pause(0.1) ycom, xcom = center_of_mass(support) print("Mean phase:", phase[support == 1].mean(), "rad") print("COM at (y, x): (", ',', str('{:.2f}'.format(ycom)), ',', str('{:.2f}'.format(xcom)), ')') print("Phase offset at COM(amp) of:", str('{:.2f}'.format(phase[int(ycom), int(xcom)])), "rad") phase = phase - phase[int(ycom), int(xcom)] plt.figure() plt.imshow(phase, cmap=my_cmap) plt.colorbar() plt.axis('scaled') plt.title("phase after offset removal") plt.pause(0.1) #################### # wrap phase
def giveRod(TestImage,rodfilter,penaltyfilter,\ iters=[15,30,45,60,75,90,105,120,135,150,165,180],\ snrthres=2.0,\ somaFilter=None, somathres=0.32, fragRodRefine=True,\ areaRefine=True,\ areathres = 0.03): """ Rotate the rod and pennalty filter for each angle in the iters, get the SNR and then threshold (snrthres), merge the detected cells at each angle and give the final deteced rod cells The final detected cells will go through two refining processes For the fragRodRefine process, a soma only filter is needed, currently, we simply use the amoeboid filter For the areaRefine process, we request that the detected cells must have 5% of filter size (75*75*0.05) """ CrPlanes = dict() final_results = np.zeros((TestImage.shape[0], TestImage.shape[1])) for i in iters: rotated_rod = rotate_image(rodfilter, i) rotated_rodp = rotate_image(penaltyfilter, i) # do convolution Cr = ndimage.convolve(TestImage, rotated_rod) Crp = ndimage.convolve(TestImage, rotated_rodp) SNR = Cr / Crp CrPlanes[i] = [Cr, Crp] rodcells = np.greater(SNR, snrthres).astype(np.float) final_results = np.logical_or(final_results, rodcells).astype(np.float) # Filtering the resutls labels, numofgroups = measurements.label(final_results) if fragRodRefine: #1) use the soma filter correlation plane to reduce false positive detection # (fragmented rod-like cells) in which two sepearated amoeboid cells # produces a false positive detection # ooo ooo /ooo==ooo\ # ooo ooo \ooo==ooo/ somaCrPlane = ndimage.convolve(TestImage, somaFilter) somaDetected = np.greater(somaCrPlane, somathres).astype(np.float) overlap = somaDetected * final_results # get the centers of the detection labels, nGroups = measurements.label(final_results) centers = measurements.center_of_mass(final_results, labels, list(range(1, nGroups + 1))) # check if the somaDetected overlapped with center of rod detections for i in range(nGroups): if overlap[int(centers[i][0]), int(centers[i][1])] == 0: final_results[labels == i + 1] = 0 if areaRefine: final_results = areaRefinement(final_results) # 2) put an area restraint: if the detected area are too small, ignore #for i in range(1,nGroups+1): #if np.sum(final_results[labels==i]) <= 75*75*areathres: #final_results[labels == i] = 0.0 return final_results, CrPlanes