def parasites(image, cells, voronoi): img = Functions.global_otsu(image) cells = Functions.global_otsu(cells) s_elem = Functions.fig(Functions.fig_size) # Remove cells for i in range(Functions.iterations): cells = binary_dilation(cells, s_elem) return_image = Functions.subtraction(img, cells) # Remove stuff from cells for i in range(Functions.iterations-1): return_image = binary_erosion(return_image) return_image = binary_opening(return_image) for i in range(Functions.iterations - 1): return_image = binary_dilation(return_image) # Remove bigger objects removal_image = return_image.copy() for i in range(Functions.iterations + 5): removal_image = binary_erosion(removal_image) removal_image = binary_opening(removal_image) for i in range(Functions.iterations + 10): removal_image = binary_dilation(removal_image) return_image = Functions.subtraction(return_image, removal_image) # Remove voronoi lines for better quality return Functions.subtraction(return_image, voronoi)
def process_cell(img): # la binariza en caso de que sea escala de grises if not img.dtype == 'bool': img = img > 0 # Binarizar # Calcular máscaras para limpiar lineas largas verticales h_k = 0.8 sum0 = np.sum(img, 0) # Aplastar la matriz a una fila con las sumas de los valores de cada columna. thr0 = sum0 < h_k * img.shape[0] thr0 = thr0.reshape(len(thr0), 1) # Convertirlo a vector de una dimensión # Calcular máscaras para limpiar lineas largas horizontales w_k = 0.5 sum1 = np.sum(img, 1) thr1 = sum1 < w_k * img.shape[1] thr1 = thr1.reshape(len(thr1), 1) mask = thr0.transpose() * thr1 # Generar máscara final para la celda mask_lines = mask.copy() elem = morphology.square(5) mask = morphology.binary_erosion(mask, elem) # Eliminar ruido img1 = np.bitwise_and(mask, img) # Imagen filtrada # segmentación del bloque de números kerw = 5 # Kernel width thr_k = 0.8 # Calcular mascara para marcar inicio y fin de región con dígitos horizontalmente sum0 = np.sum(img1, 0) sum0 = signal.medfilt(sum0, kerw) thr0 = sum0 > thr_k * np.median(sum0) thr0 = np.bitwise_and(thr0.cumsum() > 0, np.flipud(np.flipud(thr0).cumsum() > 0)) thr0 = thr0.reshape(len(thr0), 1) # Calcular mascara para marcar inicio y fin de región con dígitos verticalmente sum1 = np.sum(img1, 1) sum1 = signal.medfilt(sum1, kerw) thr1 = sum1 > thr_k * np.median(sum1) thr1 = np.bitwise_and(thr1.cumsum() > 0, np.flipud(np.flipud(thr1).cumsum() > 0)) thr1 = thr1.reshape(len(thr1), 1) # Mascara final para inicio y fin de caracteres (bounding box of digit region) mask = thr0.transpose() * thr1 mask = morphology.binary_dilation(mask, morphology.square(2)) img = np.bitwise_and(mask_lines.astype(img.dtype), img) # Aplicar máscara para quitar lineas img = morphology.binary_dilation(img, morphology.disk(1)) # Dilatación para unir números quebrados por la máscara anterior img = morphology.binary_erosion(img, morphology.disk(1)) # Volver a la fomorma 'original' con los bordes unidos return np.bitwise_and(mask, img)
def eroding3D(data, selem=skimor.disk(3), slicewise=False, sliceId=0): if slicewise: if sliceId == 0: for i in range(data.shape[0]): data[i, :, :] = skimor.binary_erosion(data[i, :, :], selem) elif sliceId == 2: for i in range(data.shape[2]): data[:, :, i] = skimor.binary_erosion(data[:, :, i], selem) else: data = scindimor.binary_erosion(data, selem) return data
def __call__(self, image, range_, shrink_per_label=False): radius = np.abs(range_[0]) struct = median(disk(radius), disk(1)) if shrink_per_label: out = np.zeros(image.shape, dtype=np.int16) for label in np.unique(image)[1:]: bin_ = (image == label).astype(np.uint8) # ev. as bool bin_ = binary_erosion(bin_, struct) out += (bin_*label).astype(out.dtype) else: out = binary_erosion(image.astype(np.uint8), struct) return out*image.astype(np.int16)
def cleanImage(img, min_size, scale_factor, img_otsu=None, saver=lambda n,x: x): img, exposure_data = normalize_exposure2(img) img = saver("01-exposure", img) img_otsu = ski.filter.threshold_otsu(img) if not img_otsu else img_otsu print('otsu:',img_otsu, ski.filter.threshold_otsu(img)) img = saver("02-zoom", scipy.ndimage.zoom(img, scale_factor, order=3)) print("shape after zoom:", img.shape) # img_pil = PIL.Image.fromarray(img).resize((np.array(img.shape)*scale_factor).tolist()[:2], resample=PIL.Image.BICUBIC) # img = saver("02-zoom", PIL2array(img_pil)) print("img:",img.shape,img.dtype) img_cleaned = saver("03-bw", (img > img_otsu)) # img_cleaned = saver("03-bw", (img > 0.2)) dbg = DebugData() img_cleaned = morphology.binary_erosion(img_cleaned,morphology.disk(int(2*scale_factor))) img_cleaned = saver("04-erosion", img_cleaned, dbg=dbg) img_cleaned = morphology.remove_small_objects(img_cleaned, min_size=int(min_size*scale_factor), connectivity=2) img_cleaned = saver("05-remove", img_cleaned) cleaned_sum = np.sum(img_cleaned) print("img_cleaned size:",cleaned_sum) # if cleaned_sum < 1000 or cleaned_sum > 300000: # display(Image(str(dbg.saved_path))) # raise Exception("Image not cleaned correctly"+str(locals())) return img_cleaned, exposure_data
def estimate_rotation(img): assert(img.dtype == 'bool') # elimina bloques rellenos para acelerar la deteccion de lineas elem = morphology.square(2) aux = morphology.binary_dilation(img, elem) - morphology.binary_erosion(img, elem) # Detección de lineas usando transformada de Hough probabilística thres = 50 minlen = 0.1 * min(aux.shape) maxgap = 0.01 * minlen lines = transform.probabilistic_hough(aux, threshold=thres, line_length=minlen, line_gap=maxgap) # me aseguro que el primer punto de cada línea sea el más próximo al origen for lin in lines: (x0,y0), (x1,y1) = lin if x1*x1+y1*y1 < x0*x0+y0*y0: (x0, x1) = (x1, x0) (y0, y1) = (y1, y0) # orientación dominante angle_half_range = np.math.pi / 4 nbins = int(2 * angle_half_range * (180./np.math.pi) / 0.2) orient = [] for lin in lines: (x0,y0), (x1,y1) = lin orient.append(np.math.atan2(y1-y0, x1-x0)) (h, binval) = np.histogram(orient, range=(-angle_half_range, angle_half_range), bins=nbins) alpha = binval[h.argmax()] * (180./ np.math.pi) return alpha + 0.5 * (binval[1] - binval[0]) * (180./ np.math.pi)
def calculate_masked_stats(): plate_no = "59798" parsed = get_plate_files(plate_no) for w in ['w2']: files = filter(lambda f: f.wave == w[1], parsed) # accum = np.zeros((2160, 2160), dtype=np.uint32) # files = filter(lambda x: 's1' not in x and 's7' not in x, all_files) nof = len(files) for i, frame in enumerate(files[0:5], 1): LogHelper.logText(frame.fullpath) img = imread(frame.fullpath) t = filters.threshold_yen(img) b1 = img > t b2 = binary_erosion(b1, square(2)) b3 = binary_dilation(b2, square(10)) b4 = binary_closing(b3, square(3)) imm = np.ma.masked_where(b4, img) mn, mx = np.percentile(imm, (1, 99)) LogHelper.logText( '%3d of %d, %4d-%4d-%4d-%5d, %.0f-%.0f' % (i, nof, imm.min(), mn, mx, imm.max(), imm.mean(), imm.std()) ) im2 = imm.filled(int(imm.mean())) out_name = "{0}\\{5}-{1}{2}-{3}-{4}.tif".format(ROOT_DIR, frame.row, frame.column, frame.site, LogHelper.init_ts, frame.experiment) imsave(out_name, im2)
def get_segmented_lungs(im): binary = im < -320 cleared = clear_border(binary) cleared=morph(cleared,5) label_image = label(cleared) areas = [r.area for r in regionprops(label_image)] areas.sort() if len(areas) > 2: for region in regionprops(label_image): if region.area < areas[-2]: for coordinates in region.coords: label_image[coordinates[0], coordinates[1]] = 0 binary = label_image > 0 selem = disk(2) binary = binary_erosion(binary, selem) selem = disk(10) binary = binary_closing(binary, selem) edges = roberts(binary) binary = ndi.binary_fill_holes(edges) get_high_vals = binary == 0 im[get_high_vals] = 0 binary = morphology.dilation(binary,np.ones([5,5])) return binary
def double_erosion(binary, selem): '''Returns the result of two sequential binary erosions''' for i in (1,2): binary = binary_erosion(binary, selem) return binary
def cleanImageOld(img, min_size, scale_factor, img_otsu=None, saver=lambda n,x: x): img, exposure_data = normalize_exposure2(img) img = saver("01-exposure", img) img_otsu = ski.filter.threshold_otsu(img) if not img_otsu else img_otsu img = saver("02-zoom", scipy.ndimage.zoom(img, scale_factor, order=3)) print("img:",img.shape,img.dtype) img_cleaned = saver("03-bw", (img > img_otsu)) dbg = DebugData() img_cleaned = morphology.binary_erosion(img_cleaned, morphology.disk(int(2*scale_factor))) img_cleaned = saver("04-erosion", img_cleaned, dbg=dbg) img_cleaned = morphology.remove_small_objects( img_cleaned, min_size=int(min_size*scale_factor), connectivity=2) img_cleaned = saver("05-remove", img_cleaned) cleaned_sum = np.sum(img_cleaned) print("img_cleaned size:",cleaned_sum) return img_cleaned, exposure_data
def get_mask(srcpath): """ Read the mask for a given filepath. It is assumed that the 4th band corresponds to a mask. If a 4th band does not exist, a square mask is generated with border pixels marked out. :param srcpath: """ with rio.drivers(): with rio.open(srcpath) as src: count = src.count if count < 4: mask = np.ones(src.shape, dtype=np.uint8) mask[0, :] = 0 mask[-1, :] = 0 mask[:, 0] = 0 mask[:, -1] = 0 else: mask = src.read(4).astype(np.bool) mask = binary_erosion(mask, disk(3)).astype(np.uint8) # height, width = src.shape # h2, w2 = height / 2, width / 2 # mask = np.zeros(src.shape, dtype=np.uint8) # r = 600 # mask[h2 - r: h2 + r + 1, w2 - r: w2 + r + 1] = disk(r) return mask
def binarize_canny(pic_source, sensitivity = 5.): ht = 5. + ((10 - sensitivity)/5.)*20. # print ht edges = canny_filter(pic_source, sigma = 3, high_threshold = ht, low_threshold = 2.) selem_morph = np.array([0,1,0,1,1,1,0,1,0], dtype=bool).reshape((3,3)) for i in (1,2): edges = binary_dilation(edges, selem_morph) # misc.imsave('/home/varnivey/Data/Biophys/Burnazyan/Experiments/fluor_calc/test/edges.jpg', edges) # binary = ndimage.binary_fill_holes(edges) labels = measure_label(edges) labelcount = np.bincount(labels.ravel()) bg = np.argmax(labelcount) edges[labels != bg] = 255 selem_med = np.ones((3,3), dtype = bool) binary = median_filter(edges, selem_med) for i in (1,2,3): binary = binary_erosion(edges, selem_morph) return edges
def get_segmented_lungs(im, plot=False): # Step 1: Convert into a binary image. binary = im < -400 # Step 2: Remove the blobs connected to the border of the image. cleared = clear_border(binary) # Step 3: Label the image. label_image = label(cleared) # Step 4: Keep the labels with 2 largest areas. areas = [r.area for r in regionprops(label_image)] areas.sort() if len(areas) > 2: for region in regionprops(label_image): if region.area < areas[-2]: for coordinates in region.coords: label_image[coordinates[0], coordinates[1]] = 0 binary = label_image > 0 # Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels. selem = disk(2) binary = binary_erosion(binary, selem) # Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall. selem = disk(10) # CHANGE BACK TO 10 binary = binary_closing(binary, selem) # Step 7: Fill in the small holes inside the binary mask of lungs. edges = roberts(binary) binary = ndi.binary_fill_holes(edges) # Step 8: Superimpose the binary mask on the input image. get_high_vals = binary == 0 im[get_high_vals] = -2000 return im, binary
def removeChessboard(img): # Get the major lines in the image edges, dilatedEdges, (h, theta, d) = findLines(img) # Create image with ones to fill inn lines lines = np.ones(img.shape[:2]) # Add lines to image as zeroes for _, angle, dist in zip(*hough_line_peaks(h, theta, d)): y0 = (dist - 0 * np.cos(angle)) / np.sin(angle) y1 = (dist - img.shape[1] * np.cos(angle)) / np.sin(angle) x, y = line(int(y1), 0, int(y0), img.shape[1] - 1) x = np.clip(x, 0, img.shape[0] - 1) y = np.clip(y, 0, img.shape[1] - 1) lines[x, y] = 0 # Remove border edges from image with all edges w = 4 edges = np.pad(edges[w:img.shape[0] - w, w:img.shape[1] - w], w, mode='constant') # Erode the lines bigger, such that they cover the original lines lines = binary_erosion(lines, square(13)) # Remove major lines and close shape paths removedChessboard = binary_closing(edges * lines, square(8)) return removedChessboard
def get_outline(im): """Return segmentation outline.""" binary_mask_im = im != 0 salem = disk(4) erosion_mask_im = binary_erosion(binary_mask_im, salem) outline_mask_im = np.logical_xor(binary_mask_im, erosion_mask_im) return im * outline_mask_im
def colors_peripheral_vs_central(image_roi, attrs={}, debug=False): image_roi, center = pad_for_rotation(image_roi) lesion_mask = image_roi[..., 3] goal = lesion_mask.sum() * 0.7 inner = lesion_mask.copy() while inner.sum() > goal: inner = binary_erosion(inner, disk(1)) outer = np.logical_and(lesion_mask, np.logical_not(inner)) if debug: print """\ === Colors Peripheral vs Central === lesion area: %d inner goal: %d inner area: %d outer area: %d """ % (lesion_mask.sum(), goal, inner.sum(), outer.sum()) if debug: plt.subplot(131) plt.imshow(lesion_mask) plt.subplot(132) plt.imshow(inner) plt.subplot(133) plt.imshow(outer) plt.show() outer = np.nonzero(outer) inner = np.nonzero(inner) image_lab = rgb2lab(image_roi[..., :3]) L, a, b = np.dsplit(image_lab, 3) delta_L = np.mean(L[outer]) - np.mean(L[inner]) delta_a = np.mean(a[outer]) - np.mean(a[inner]) delta_b = np.mean(b[outer]) - np.mean(b[inner]) density_L = ( np.histogram(L[outer], 100, (0.,100.), density=True)[0] * np.histogram(L[inner], 100, (0.,100.), density=True)[0] ).sum() density_a = ( np.histogram(a[outer], 254, (-127.,127.), density=True)[0] * np.histogram(a[inner], 254, (-127.,127.), density=True)[0] ).sum() density_b = ( np.histogram(b[outer], 254, (-127.,127.), density=True)[0] * np.histogram(b[inner], 254, (-127.,127.), density=True)[0] ).sum() attrs.update([ ('Colors PvsC mean difference L', delta_L), ('Colors PvsC mean difference a', delta_a), ('Colors PvsC mean difference b', delta_b), ('Colors PvsC density baysian L', density_L), ('Colors PvsC density baysian a', density_a), ('Colors PvsC density baysian b', density_b), ])
def seg_sect(self, img): img_canny = canny(img, sigma=self.sigma, low_threshold=self.low_threshold) img_dilate = binary_dilation(img_canny, square(3)) img_erode = binary_erosion(img_dilate, square(3)) img_fill = binary_fill_holes(img_erode) return img_fill
def mixing_region(filename): white = io.imread(filename) val = filter.threshold_otsu(white) light_mask = white > val regions = morphology.label(light_mask) index_large_region = np.argmax(np.bincount(regions.ravel())) fluid_mask = regions == index_large_region fluid_mask = morphology.binary_erosion(fluid_mask, selem=np.ones((3, 3))) return fluid_mask
def cells(image): img = Functions.global_otsu(image) s_elem = Functions.fig(Functions.fig_size) for i in range(Functions.iterations): img = binary_erosion(img, s_elem) for i in range(Functions.iterations): img = binary_dilation(img, s_elem) return Functions.watershed_separation(img, s_elem)
def erode(data, radius): """ Erode data using ball structuring element :param data: 2d or 3d array :param radius: radius of structuring element :return: data eroded """ from skimage.morphology import binary_erosion, ball selem = ball(radius) return binary_erosion(data, selem=selem, out=None)
def compute_perim_mask(self, mask, thick): """returns mask for perimeter needs cell mask """ # create mask eroded = morphology.binary_erosion(mask, np.ones((thick * 2 - 1, thick - 1))).astype(float) perim = mask - eroded return perim
def border_scores(image, center, major_axis, attrs={}, debug=False): eroded = binary_erosion(image[...,3], disk(4)) border = eroded - binary_erosion(eroded, disk(1)) border_mask = binary_dilation(border, disk(7)) rn = roberts_negative_diagonal(image[...,0], border_mask) rp = roberts_positive_diagonal(image[...,0], border_mask) gn = roberts_negative_diagonal(image[...,1], border_mask) gp = roberts_positive_diagonal(image[...,1], border_mask) bn = roberts_negative_diagonal(image[...,2], border_mask) bp = roberts_positive_diagonal(image[...,2], border_mask) gradient = np.sqrt(rn**2 + rp**2 + gn**2 + gp**2 + bn**2 + bp**2) border_scores = [ np.average(gradient, weights=section) * 255 for section in _make_partitions(8, border_mask, center, major_axis) if section.sum() > 0 ] attrs.update(('--Border Scores Section %d' % i, score) for i, score in enumerate(border_scores, 1)) attrs.update([ ('Border Scores Average', np.mean(border_scores)), ('Border Scores Stddev', np.std(border_scores)), ]) if debug: print "--- Border Scores ---" print " | ".join("%.3f" % score for score in border_scores) print plt.subplot(121) imgplot = plt.imshow((image[...,:3].T * border_mask.T).T) imgplot.set_interpolation('nearest') plt.subplot(122) imgplot = plt.imshow(gradient) imgplot.set_interpolation('nearest') plt.show() attrs['--Border Score'] = sum(score >= 10 for score in border_scores) return attrs
def get_contour(image): image_data = plt.imread(image) gimg = color.colorconv.rgb2grey(image_data) bwimg = gimg > 0 bwimg = binary_dilation(bwimg, None) bwimg = ndimage.binary_fill_holes(bwimg) bwimg = binary_erosion(bwimg) contours = [approximate_polygon(new_s, 0.9) for new_s in measure.find_contours(bwimg, 0.5)] return bwimg, contours
def binary_find_boundaries(image): if image.dtype != np.bool: raise ValueError('image must have dtype = \'bool\'') if image.ndim == 2: selem = disk(1) elif image.ndim == 3: selem = ball(1) else: raise ValueError('image must be 2D or 3D') eroded = binary_erosion(image, selem) return (image & (~eroded))
def unet_candidates(): cands = glob.glob("../data/predictions_epoch9_23_all/*.png") #df = pd.DataFrame(columns=['seriesuid','coordX','coordY','coordZ','class']) data = [] imname = "" origin = [] spacing = [] nrimages = 0 for name in tqdm(cands): #image = imread(name) image_t = imread(name) image_t = image_t.transpose() #Thresholding image_t[image_t<THRESHOLD] = 0 image_t[image_t>0] = 1 #erosion selem = morphology.disk(1) image_eroded = image_t image_eroded = morphology.binary_erosion(image_t,selem=selem) label_im, nb_labels = ndimage.label(image_eroded) imname3 = os.path.split(name)[1].replace('.png','') splitted = imname3.split("slice") slice = splitted[1] imname2 = splitted[0][:-1] centers = [] 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]]) if imname2 != imname: if os.path.isfile("../data/1_1_1mm_512_x_512_annotation_masks/spacings/{0}.pickle".format(imname2)): with open("../data/1_1_1mm_512_x_512_annotation_masks/spacings/{0}.pickle".format(imname2), 'rb') as handle: dic = pickle.load(handle) origin = dic["origin"] spacing = dic["spacing"] imname = imname2 nrimages +=1 for center in centers: coords = voxel_2_world([int(slice),center[1]+(512-324)*0.5,center[0]+(512-324)*0.5],origin,spacing) data.append([imname2,coords[2],coords[1],coords[0],'?']) #if nrimages == 5: # break df = pd.DataFrame(data,columns=CANDIDATES_COLUMNS) save_candidates("../data/candidates_unet_final_23.csv",df)
def process(filename, plot=False): # read in image filename imagepath = os.path.join(os.getcwd(), filename) orig_img = io.imread(filename,True,'pil') # binarize image img = orig_img > 0.9 # binary threshold # convert to grayscale (easier for viewing) img = rgb2gray(img) imshow(img) # use erosion to expland black areas in the document. This will # group together small text and make it easier to find contours # of signatures, which are usually separated from text eroded_img = binary_erosion(img,rectangle(30,10)) # get contours of eroded image contours, lengths = compute_contours(eroded_img) # compute X and Y gradients over the contours. We expect that signatures # will have have a constant gradient that is close to the length of # the contour. We take the sum of the X-gradient to remove contours # that are vertically biased c_grad_x = map(lambda x: np.gradient(x[:,1]), contours) c_grad_y = map(lambda x: np.gradient(x[:,0]), contours) stuffs = [] for i,(x,y) in enumerate(zip(c_grad_x,c_grad_y)): stuffs.append( (sum(map(abs, x)), len(x)) ) d = pd.DataFrame.from_records(stuffs) d['diff'] = abs(d[0] - d[1]) d = d[d['diff'] > d['diff'].mean()] contours = [contours[i] for i in d.index] # compute bounding boxes for resulting contours boxes = get_boundingboxes(contours) # given a box, does sobel on the bounding box of that block # computes contours within the subimage and returns them def process_block(box): mask = get_mask_from_boundingbox(img,box) sobel_img = sobel(img,mask) contours, lengths = compute_contours(sobel_img) return len(contours),contours,lengths # get all blocks blocks = [process_block(box) for box in boxes] # retrieve the blocks that have the fewest number of contours num_contours = pd.Series(block[0] for block in blocks) num_contours = num_contours[num_contours < num_contours.mean()] # plot only those contours ret_contours = [] for block in [blocks[i] for i in num_contours.index]: len_con,contours,lengths = block lengths = pd.Series(lengths) lengths = lengths[lengths > lengths.mean()] for i in lengths.index: contour = contours[i] ret_contours.append(contour) plt.plot(contour[:,1],contour[:,0]) return ret_contours
def erode(infile): """ use skimage.morphology to quickly erode binary mask""" img = nibabel.load(infile) dat = img.get_data().squeeze() kernel = np.zeros((3,3,3)) kernel[1,:,:] = 1 kernel[:,1,:] = 1 kernel[:,:,1] = 1 eroded = binary_erosion(dat, kernel) eroded = eroded.astype(int) newfile = filemanip.fname_presuffix(infile, 'e') newimg = nibabel.Nifti1Image(eroded, img.get_affine()) newimg.to_filename(newfile) return newfile
def create_mask(frame): """"Create a big mask that encompasses all the cells""" # detect ridges ridges = enhance_ridges(frame) # threshold ridge image thresh = filters.threshold_otsu(ridges) thresh_factor = 1.1 prominent_ridges = ridges > thresh_factor*thresh prominent_ridges = morphology.remove_small_objects(prominent_ridges, min_size=128) # the mask contains the prominent ridges mask = morphology.convex_hull_image(prominent_ridges) mask = morphology.binary_erosion(mask, disk(10)) return mask
def erode(infile): """ use skimage.morphology to quickly erode binary mask""" img = nibabel.load(infile) dat = img.get_data().squeeze() ## make kernel tmp = np.diag([0,1,0]) mid = np.zeros((3,3)) mid[1,:] = 1 mid[:,1] = 1 kernel = np.hstack((tmp, mid, tmp)) kernel.shape = (3,3,3) ## erode with kernel eroded = binary_erosion(dat, kernel) eroded = eroded.astype(int) newfile = filemanip.fname_presuffix(infile, 'e') newimg = nibabel.Nifti1Image(eroded, img.get_affine()) newimg.to_filename(newfile) return newfile
def erode(image, struct=None): """ Erode edges of white phase. :param image: data :type image: :py:class:`numpy.ndarray` :type struct: :py:class:`numpy.ndarray` :type struct: :py:class:`numpy.ndarray` :return: modified image data :rtype: :py:class:`numpy.ndarray` """ if not struct: struct = morphology.disk(1) i = morphology.binary_erosion(image, struct) return i > i.mean()
def setup_stress_field(mask, distribution="uniform", sigma_n=1, sigma_shear=0, sigma_gf=4, diameter_gf=4): mask = mask.astype(bool) sigma_x = np.zeros(mask.shape) sigma_y = np.zeros(mask.shape) sigma_xy = np.zeros(mask.shape) if distribution == "uniform": sigma_x[binary_erosion( mask )] = sigma_n # binary errosion because boundary effects of gradient sigma_y[binary_erosion(mask)] = sigma_n sigma_xy[binary_erosion(mask)] = sigma_shear if distribution == "gaussian_flattened_circle": center = regionprops(mask.astype(int))[0].centroid shape_length = regionprops(mask.astype(int))[0].equivalent_diameter circ = circle(center[0], center[1], radius=shape_length / diameter_gf) sigma_x[circ] = 1 sigma_y[circ] = 1 sigma_x = gaussian_filter(sigma_x, sigma=sigma_gf) sigma_y = gaussian_filter(sigma_y, sigma=sigma_gf) sigma_x[~mask] = 0 sigma_y[~mask] = 0 # normalizing to get sum on mean of stress of at each pixel to 1 sigma_x[mask] = (sigma_x[mask] / (np.sum(sigma_x[mask])) * np.sum(mask)) sigma_y[mask] = (sigma_y[mask] / (np.sum(sigma_y[mask])) * np.sum(mask)) # sigma_x[binary_erosion(mask)] = sigma_n # binary errosion because boundary effects of gradient # sigma_y[binary_erosion(mask)] = sigma_n if distribution == "gaussian_flattened_rectangle": sigma_x[binary_erosion(mask, iterations=diameter_gf)] = 1 sigma_y[binary_erosion(mask, iterations=diameter_gf)] = 1 sigma_x = gaussian_filter(sigma_x, sigma=sigma_gf) sigma_y = gaussian_filter(sigma_y, sigma=sigma_gf) sigma_x[~mask] = 0 sigma_y[~mask] = 0 # normalizing to get sum on mean of stress of at each pixel to 1 sigma_x[mask] = (sigma_x[mask] / (np.sum(sigma_x[mask])) * np.sum(mask)) sigma_y[mask] = (sigma_y[mask] / (np.sum(sigma_y[mask])) * np.sum(mask)) # sigma_x[binary_erosion(mask)] = sigma_n # binary errosion because boundary effects of gradient # sigma_y[binary_erosion(mask)] = sigma_n if distribution == "gaussian": center = regionprops(mask.astype(int))[0].centroid sigma_x[int(center[0]), int(center[1])] = 1 sigma_y[int(center[0]), int(center[1])] = 1 sigma_x = gaussian_filter(sigma_x, sigma=sigma_gf) sigma_y = gaussian_filter(sigma_y, sigma=sigma_gf) mask = mask.astype(bool) sigma_x[~mask] = 0 sigma_y[~mask] = 0 # normalizing to get sum on mean of stress of at each pixel to 1 sigma_x[mask] = (sigma_x[mask] / (np.sum(sigma_x[mask])) * np.sum(mask)) sigma_y[mask] = (sigma_y[mask] / (np.sum(sigma_y[mask])) * np.sum(mask)) # sigma_x[binary_erosion(mask)] = sigma_n # binary errosion because boundary effects of gradient # sigma_y[binary_erosion(mask)] = sigma_n stress_tensor = np.zeros((mask.shape[0], mask.shape[1], 2, 2)) stress_tensor[:, :, 0, 0] = sigma_x stress_tensor[:, :, 0, 1] = sigma_xy stress_tensor[:, :, 1, 0] = sigma_xy stress_tensor[:, :, 1, 1] = sigma_y return stress_tensor
def get_segmented_lungs(raw_im): ''' 对肺部CT图像实现实质 This funtion segments the lungs from the given 2D slice. :param raw_im: 输入原始图像 :return: binaty 二值图掩码 ,im 原始图像叠加二值图掩码后结果 ''' im = raw_im.copy() ''' 将2D Slice转为二值图 Step 1: Convert into a binary image. ''' binary = im < -567.5 # binary = im < -500 # thresh = threshold_otsu(binary) # binary = binary > thresh ''' 删除连接到图像边界的噪点。 Step 2: Remove the blobs connected to the border of the image. ''' cleared = clear_border(binary) ''' 标记图像 Step 3: Label the image. ''' label_image = label(cleared) ''' 保持标记有两个最大的区域 Step 4: Keep the labels with 2 largest areas. ''' areas = [r.area for r in regionprops(label_image)] areas.sort() if len(areas) > 2: for region in regionprops(label_image): if region.area < areas[-2]: for coordinates in region.coords: label_image[coordinates[0], coordinates[1]] = 0 binary = label_image > 0 ''' 半径为2 pixels,腐蚀操作。 Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels. ''' selem = disk(2) binary = binary_erosion(binary, selem) ''' 半径为10 pixels,闭合操作。 Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall. ''' selem = disk(7) binary = binary_closing(binary, selem) ''' 将二值图中的部分噪点填充。 Step 7: Fill in the small holes inside the binary mask of lungs. ''' edges = roberts(binary) binary = ndimage.binary_fill_holes(edges) ''' 在输入图像上叠加二进制掩码。 Step 8: Superimpose the binary mask on the input image. ''' get_high_vals = binary == 0 im[get_high_vals] = 0 return binary, im
def deepcell_transform(maskstack, dilation_radius=None, data_format=None): """ Transforms a label mask for a z stack edge, interior, and background # Arguments: maskstack: label masks of uniquely labeled instances dilation_radius: width to enlarge the edge feature of each instance # Returns: deepcell_stacks: masks of: [background_edge_feature, interior_edge_feature, interior_feature, background] """ if data_format is None: data_format = K.image_data_format() if data_format == 'channels_first': channel_axis = 1 else: channel_axis = len(maskstack.shape) - 1 maskstack = np.squeeze(maskstack, axis=channel_axis) # Detect the edges and interiors new_masks = np.zeros(maskstack.shape) edge_masks = np.zeros(maskstack.shape) strel = ball(1) if maskstack.ndim > 3 else disk(1) for cell_label in np.unique(maskstack): if cell_label != 0: for i in range(maskstack.shape[0]): # get the cell interior img = maskstack[i] == cell_label img = binary_erosion(img, strel) new_masks[i] += img interior_masks = np.multiply(new_masks, maskstack) edge_masks = (maskstack - interior_masks > 0).astype('int') interior_masks = (interior_masks > 0).astype('int') # dilate the background masks and subtract from all edges for background-edges dilated_background = np.zeros(maskstack.shape) for i in range(maskstack.shape[0]): background = (maskstack[i] == 0).astype('int') dilated_background[i] = binary_dilation(background, strel) background_edge_masks = (edge_masks - dilated_background > 0).astype('int') # edges that are not background-edges are interior-edges interior_edge_masks = (edge_masks - background_edge_masks > 0).astype('int') if dilation_radius: dil_strel = ball(dilation_radius) if maskstack.ndim > 3 else disk(dilation_radius) # Thicken cell edges to be more pronounced for i in range(edge_masks.shape[0]): interior_edge_masks[i] = binary_dilation(interior_edge_masks[i], selem=dil_strel) background_edge_masks[i] = binary_dilation(background_edge_masks[i], selem=dil_strel) # Thin the augmented edges by subtracting the interior features. interior_edge_masks = (interior_edge_masks - interior_masks > 0).astype('int') background_edge_masks = (background_edge_masks - interior_masks > 0).astype('int') background_masks = (1 - background_edge_masks - interior_edge_masks - interior_masks > 0) background_masks = background_masks.astype('int') all_stacks = [ background_edge_masks, interior_edge_masks, interior_masks, background_masks ] deepcell_stacks = np.stack(all_stacks, axis=channel_axis) return deepcell_stacks
def get_segmentation_mask(im, z=-1, plot=False, savefig=False): ''' This funtion segments the lungs from a given 2D slice. ''' if plot == True: f, plots = plt.subplots(8, 1, figsize=(5, 40)) ''' Step 1: Convert into a binary image. ''' #binary = im < 604 binary = im < -400 if plot == True: plots[0].axis('off') plots[0].imshow(binary, cmap=plt.cm.bone) ''' Step 2: Remove the blobs connected to the border of the image. ''' cleared = clear_border(binary) if plot == True: plots[1].axis('off') plots[1].imshow(cleared, cmap=plt.cm.bone) ''' Step 3: Label the image. ''' label_image = label(cleared) if plot == True: plots[2].axis('off') plots[2].imshow(label_image, cmap=plt.cm.bone) ''' Step 4: Keep the labels with 2 largest areas. ''' areas = [r.area for r in regionprops(label_image)] areas.sort() if len(areas) > 2: for region in regionprops(label_image): if region.area < areas[-2]: for coordinates in region.coords: label_image[coordinates[0], coordinates[1]] = 0 binary = label_image > 0 if plot == True: plots[3].axis('off') plots[3].imshow(binary, cmap=plt.cm.bone) ''' Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels. ''' selem = disk(2) binary = binary_erosion(binary, selem) if plot == True: plots[4].axis('off') plots[4].imshow(binary, cmap=plt.cm.bone) ''' Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall. ''' selem = disk(10) binary = binary_closing(binary, selem) if plot == True: plots[5].axis('off') plots[5].imshow(binary, cmap=plt.cm.bone) ''' Step 7: Fill in the small holes inside the binary mask of lungs. ''' edges = roberts(binary) binary = ndi.binary_fill_holes(edges) if plot == True: plots[6].axis('off') plots[6].imshow(binary, cmap=plt.cm.bone) if savefig: print 'test_' + str(z) + '.jpg' plt.savefig('test_' + str(z) + '.jpg') return binary
def estimate(image, expected_position=None, search_rect=None, search_rect_border=0.05, expected_pixels=(10, 200), optimal_size=90, visualize=False): downscale_factor = 1 # legacy stuff h, w = image.shape[0:2] if search_rect is not None: x1, y1, x2, y2 = search_rect[0], search_rect[1], search_rect[2], search_rect[3] if search_rect_border > 0: clip = np.clip bx = int(w * search_rect_border) by = int(h * search_rect_border) x1 = clip(x1 - bx, 0, w-2) y1 = clip(y1 - by, 0, h-2) x2 = clip(x2 + bx, x1, w-1) y2 = clip(y2 + by, y1, h-1) else: # full wheel: x1=440, x2=870, y1=440, y2=720 # wheel w=440, h=270 x1 = int(w * (480/1280)) x2 = int(w * (830/1280)) y1 = int(h * (520/720)) y2 = int(h * (720/720)) rect_h = y2 - y1 rect_w = x2 - x1 if expected_position is None: expected_position = ( int(w * (646/1280)), int(h * (684/720)) ) img_wheel = image[y1:y2+1, x1:x2+1, :] img_wheel_rs = img_wheel img_wheel_rsy = cv2.cvtColor(img_wheel_rs, cv2.COLOR_RGB2GRAY) expected_position_rs = ( int((expected_position[0]-x1) * downscale_factor), int((expected_position[1]-y1) * downscale_factor) ) #thresh_mask = filters.threshold_li(img_wheel_rsy) thresh_mask = filters.threshold_isodata(img_wheel_rsy) thresh = img_wheel_rsy > thresh_mask #40 #cv2.imshow("thresh", thresh.astype(np.uint8)*255) #cv2.waitKey(10) thresh = morphology.binary_dilation(thresh, morphology.square(3)) img_labeled, num_labels = morphology.label( thresh, background=0, connectivity=1, return_num=True ) segments = [] for label in range(1, num_labels+1): img_seg = (img_labeled == label) (yy, xx) = np.nonzero(img_seg) # size of correct segment is around 60 pixels without dilation and 90 with dilation # position is at around x=21, y=13 # (both numbers for screenshots after jpg-compression/decompression at 1/4 the original # size, i.e. 1280/4 x 720/4) if expected_pixels[0] <= len(yy) <= expected_pixels[1]: center_x = np.average(xx) center_y = np.average(yy) # euclidean distance to expected position # segments which's center is at the expected position get a 0 # segments which a further away get higher values dist_pos = 0.1 * math.sqrt((center_x - expected_position_rs[0]) ** 2 + (center_y - expected_position_rs[1])**2) # distance to optimal size (number of pixels) # segments that have the same number of pixels as the expected size # get a 0, segments with 50pecent more/less pixels get a 0 dist_size = np.clip( 1/(optimal_size*0.5) * abs(len(yy) - optimal_size), 0, 1 ) dist = dist_pos + dist_size segments.append({ "xx": xx, "yy": yy, "center_x": center_x, "center_y": center_y, "dist_pos": dist_pos, "dist_size": dist_size, "dist": dist, "img_seg": img_seg }) if len(segments) == 0: return (None, None) if visualize else None segments = sorted(segments, key=lambda d: d["dist"]) best_match = segments[0] xx = x1 + (best_match["xx"].astype(np.float32) * (1/downscale_factor)).astype(np.int32) yy = y1 + (best_match["yy"].astype(np.float32) * (1/downscale_factor)).astype(np.int32) image_segment = best_match["img_seg"] image_segment = morphology.binary_erosion(image_segment, morphology.square(3)) cx, cy = int(best_match["center_x"]), int(best_match["center_y"]) sy, sx = 10, 10 hx1 = np.clip(cx - sx, 0, image_segment.shape[1]) hx2 = np.clip(cx + sx + 1, 0, image_segment.shape[1]) hy1 = np.clip(cy - sy, 0, image_segment.shape[0]) hy2 = np.clip(cy + sy + 1, 0, image_segment.shape[0]) hough_segment = image_segment[hy1:hy2, hx1:hx2] h, theta, d = hough_line(hough_segment) if len(h) == 0: return (None, None) if visualize else None hspaces, angles, dists = hough_line_peaks(h, theta, d, num_peaks=1) if len(hspaces) == 0: return (None, None) if visualize else None hspace, angle, dist = hspaces[0], angles[0], dists[0] line_y0 = (dist - 0 * np.cos(angle)) / np.sin(angle) line_y1 = (dist - hough_segment.shape[1] * np.cos(angle)) / np.sin(angle) slope = (line_y1 - line_y0) / (hx2 - hx1) left_x = cx - 3 right_x = cx + 3 left_y = cy + (-3) * slope right_y = cy + 3 * slope #print("x1 %d x2 %d y1 %d y2 %d | cx %d cy %d | hx1 %d hx2 %d hy1 %d hy2 %d | line_y0 %.2f line_y1 %.2f | left_x %d right_x %d left_y %d right_y %d | hs %s | is %s" % ( # x1, x2, y1, y2, cx, cy, hx1, hx2, hy1, hy2, line_y0, line_y1, left_x, right_x, left_y, right_y, hough_segment.shape, image_segment.shape #)) #fig, ax = plt.subplots(1, 1, figsize=(5, 5)) #ax.imshow(image_segment, cmap=plt.cm.gray) #ax.plot([left_x, right_x], [left_y, right_y], "-r") #plt.show() best_match["min_x"] = int(np.min(xx)) best_match["max_x"] = int(np.max(xx)) best_match["min_y"] = int(np.min(yy)) best_match["max_y"] = int(np.max(yy)) best_match["center_x"] = x1 + (best_match["center_x"] * (1/downscale_factor)) best_match["center_y"] = y1 + (best_match["center_y"] * (1/downscale_factor)) best_match["left_x"] = x1 + (left_x * (1/downscale_factor)) best_match["right_x"] = x1 + (right_x * (1/downscale_factor)) best_match["left_y"] = y1 + (left_y * (1/downscale_factor)) best_match["right_y"] = y1 + (right_y * (1/downscale_factor)) if visualize: upf = 2 image_viz = ia.imresize_single_image(np.copy(image), (image.shape[0]*upf, image.shape[1]*upf)) image_viz = util.draw_point(image_viz, x=int(x1)*upf, y=int(y1)*upf, size=7, color=[255, 0, 0]) image_viz = util.draw_point(image_viz, x=(int(x2)-1)*upf, y=int(y1)*upf, size=7, color=[255, 0, 0]) image_viz = util.draw_point(image_viz, x=(int(x2)-1)*upf, y=(int(y2)-1)*upf, size=7, color=[255, 0, 0]) image_viz = util.draw_point(image_viz, x=int(x1)*upf, y=(int(y2)-1)*upf, size=7, color=[255, 0, 0]) image_viz = util.draw_point(image_viz, x=int(expected_position[0])*upf, y=int(expected_position[1])*upf, size=7, color=[0, 0, 255]) image_viz = util.draw_point(image_viz, x=best_match["min_x"]*upf, y=best_match["min_y"]*upf, size=7, color=[128, 0, 0]) image_viz = util.draw_point(image_viz, x=(best_match["max_x"]-1)*upf, y=best_match["min_y"]*upf, size=7, color=[128, 0, 0]) image_viz = util.draw_point(image_viz, x=(best_match["max_x"]-1)*upf, y=(best_match["max_y"]-1)*upf, size=7, color=[128, 0, 0]) image_viz = util.draw_point(image_viz, x=best_match["min_x"]*upf, y=(best_match["max_y"]-1)*upf, size=7, color=[128, 0, 0]) image_viz = util.draw_point(image_viz, x=int(best_match["center_x"])*upf, y=int(best_match["center_y"])*upf, size=7, color=[0, 0, 128]) image_viz = util.draw_point(image_viz, x=int(best_match["left_x"])*upf, y=int(best_match["left_y"])*upf, size=7, color=[0, 255, 0]) image_viz = util.draw_point(image_viz, x=int(best_match["right_x"])*upf, y=int(best_match["right_y"])*upf, size=7, color=[0, 128, 0]) return best_match, image_viz else: return best_match
def find_peaks_by_snr(image, center, mask=None, gaussian_sigma=1., min_gradient=0., min_distance=1, merge_flat_peaks=False, max_peaks=500, min_snr=0., min_pixels=2, max_pixels=10, refine_mode='mean', snr_mode='rings', signal_radius=1, bg_inner_radius=2, bg_outer_radius=3, crop_size=7, bg_ratio=0.7, signal_ratio=0.2, signal_thres=5., label_pixels=False): peaks_dict = {} if mask is not None: raw_image = image * mask else: raw_image = image.copy() if gaussian_sigma >= 0: image = gaussian_filter(image.astype(np.float32), gaussian_sigma) grad = np.gradient(image.astype(np.float32)) grad_mag = np.sqrt(grad[0]**2. + grad[1]**2.) if mask is None: labels = None else: labels = binary_erosion(mask, disk(2)).astype(np.int) raw_peaks = peak_local_max(grad_mag, exclude_border=5, min_distance=min_distance, threshold_abs=min_gradient, num_peaks=max_peaks, labels=labels) raw_peaks = np.reshape(raw_peaks, (-1, 2)) if merge_flat_peaks: # do hierarchy clustering to remove flat peaks link = hierarchy.linkage(raw_peaks, method='single') r = hierarchy.cut_tree(link, height=min_distance) clusters = [] for i in np.unique(r): clusters.append(raw_peaks[r[:, 0] == i].mean(axis=0)) raw_peaks = np.array(clusters).reshape(-1, 2) peaks_dict['raw'] = raw_peaks if len(raw_peaks) == 0: return peaks_dict valid_peaks = np.reshape(raw_peaks, (-1, 2)) peaks_dict['valid'] = valid_peaks # refine peak location opt_peaks = refine_peaks(raw_image, valid_peaks, mode=refine_mode) peaks_dict['opt'] = opt_peaks snr_info = calc_snr( raw_image, opt_peaks, mode=snr_mode, signal_radius=signal_radius, bg_inner_radius=bg_inner_radius, bg_outer_radius=bg_outer_radius, crop_size=crop_size, bg_ratio=bg_ratio, signal_ratio=signal_ratio, signal_thres=signal_thres, label_pixels=label_pixels, ) strong_ids = np.where((snr_info['snr'] >= min_snr) * (snr_info['signal pixel num'] >= min_pixels) * (snr_info['signal pixel num'] <= max_pixels))[0] strong_peaks = opt_peaks[strong_ids] peaks_dict['strong'] = strong_peaks radius = np.linalg.norm(strong_peaks - center, axis=1) peaks_dict['info'] = { 'pos': strong_peaks, 'snr': snr_info['snr'][strong_ids], 'total intensity': snr_info['total intensity'][strong_ids], 'signal values': snr_info['signal values'][strong_ids], 'background values': snr_info['background values'][strong_ids], 'noise values': snr_info['noise values'][strong_ids], 'signal pixel num': snr_info['signal pixel num'][strong_ids], 'background pixel num': snr_info['background pixel num'][strong_ids], 'radius': radius, } return peaks_dict
counter += 1 else: if table_height < counter: table_height = counter i_max = i counter = 0 table_weight = 0 canny_edge_map = binary_closing(canny(matchimg, sigma=2.5), selem=np.ones((4, 4))) # поставим маркеры фона и объекта markers = np.zeros_like(matchimg) markers[0:10, 0:10] = 1 # маркеры фона markers[binary_erosion(canny_edge_map) > 0] = 2 # маркеры объекта - точки, находящиеся заведомо внутри sobel_gradient = sobel(matchimg) matchimg_region_segmentation = watershed(sobel_gradient, markers) ax[0].imshow(matchimg_region_segmentation) ax[1].imshow( label2rgb(matchimg_region_segmentation, image=matchimg, bg_label=-1)) ax[2].imshow(mask) table_weight = 0 # Рассмотрим полосу в месте, где найдем высота и найдем максимальную ширину, # она и будет являться шириной стола
def get_segmented_lungs(im, plot=False): # im: numpy array of 2D ''' This funtion segments the lungs from the given 2D slice. ''' if plot == True: f, plots = plt.subplots(8, 1, figsize=(5, 40)) ''' Step 1: Convert into a binary image. ''' binary = im < 604 # numpy array if plot == True: plots[0].axis('off') plots[0].imshow(binary, cmap=plt.cm.bone) ''' Step 2: Remove the blobs connected to the border of the image. ''' cleared = clear_border(binary) if plot == True: plots[1].axis('off') plots[1].imshow(cleared, cmap=plt.cm.bone) ''' Step 3: Label the image. ''' label_image = label(cleared) if plot == True: plots[2].axis('off') plots[2].imshow(label_image, cmap=plt.cm.bone) ''' Step 4: Keep the labels with 2 largest areas. ''' areas = [r.area for r in regionprops(label_image)] areas.sort() if len(areas) > 2: for region in regionprops(label_image): if region.area < areas[-2]: for coordinates in region.coords: label_image[coordinates[0], coordinates[1]] = 0 binary = label_image > 0 if plot == True: plots[3].axis('off') plots[3].imshow(binary, cmap=plt.cm.bone) ''' Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels. ''' selem = disk(2) binary = binary_erosion(binary, selem) if plot == True: plots[4].axis('off') plots[4].imshow(binary, cmap=plt.cm.bone) ''' Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall. ''' selem = disk(10) binary = binary_closing(binary, selem) if plot == True: plots[5].axis('off') plots[5].imshow(binary, cmap=plt.cm.bone) ''' Step 7: Fill in the small holes inside the binary mask of lungs. ''' edges = roberts(binary) binary = ndi.binary_fill_holes(edges) if plot == True: plots[6].axis('off') plots[6].imshow(binary, cmap=plt.cm.bone) ''' Step 8: Superimpose the binary mask on the input image. ''' get_high_vals = binary == 0 im[get_high_vals] = 0 if plot == True: plots[7].axis('off') plots[7].imshow(im, cmap=plt.cm.bone) return im # numpy array
def generate(self, annot_dict): ''' Create masks from annotation dictionary Args: annot_dict (dictionary): dictionary with annotations Returns: mask_dict (dictionary): dictionary with masks ''' # Get dimensions of image and created masks of same size # This we need to save somewhere (e.g. as part of the geojson file?) # Filled masks and edge mask for polygons mask_fill = np.zeros(self.image_size, dtype=np.uint8) mask_edge = np.zeros(self.image_size, dtype=np.uint8) rr_all = [] cc_all = [] if self.save_indiv is True: mask_edge_indiv = np.zeros( (self.image_size[0], self.image_size[1], len(annot_dict)), dtype=np.bool) mask_fill_indiv = np.zeros( (self.image_size[0], self.image_size[1], len(annot_dict)), dtype=np.bool) # Image used to draw lines - for edge mask for freelines #im_freeline = Image.new('1', self.image_size, color=0) im_freeline = Image.new('1', (self.image_size[1], self.image_size[0]), color=0) draw = ImageDraw.Draw(im_freeline) # Loop over all roi i_roi = 0 for roi_key, roi in annot_dict.items(): roi_pos = roi['pos'] # Check region type # freeline - line if roi['type'] == 'freeline' or roi['type'] == 'LineString': # Loop over all pairs of points to draw the line for ind in range(roi_pos.shape[0] - 1): line_pos = ((roi_pos[ind, 1], roi_pos[ind, 0], roi_pos[ind + 1, 1], roi_pos[ind + 1, 0])) draw.line(line_pos, fill=1, width=self.erose_size) # freehand - polygon elif roi['type'] == 'freehand' or roi['type'] == 'polygon' or roi[ 'type'] == 'polyline' or roi['type'] == 'Polygon': # Draw polygon rr, cc = skimage_draw.polygon(roi_pos[:, 0], roi_pos[:, 1]) # Make sure it's not outside rr[rr < 0] = 0 rr[rr > self.image_size[0] - 1] = self.image_size[0] - 1 cc[cc < 0] = 0 cc[cc > self.image_size[0] - 1] = self.image_size[0] - 1 # Test if this region has already been added if any(np.array_equal(rr, rr_test) for rr_test in rr_all) and any( np.array_equal(cc, cc_test) for cc_test in cc_all): # print('Region #{} has already been used'.format(i + # 1)) continue rr_all.append(rr) cc_all.append(cc) # Generate mask mask_fill_roi = np.zeros(self.image_size, dtype=np.uint8) mask_fill_roi[rr, cc] = 1 # Erode to get cell edge - both arrays are boolean to be used as # index arrays later mask_fill_roi_erode = morphology.binary_erosion( mask_fill_roi, np.ones((self.erose_size, self.erose_size))) mask_edge_roi = ( mask_fill_roi.astype('int') - mask_fill_roi_erode.astype('int')).astype('bool') # Save array for mask and edge mask_fill[mask_fill_roi_erode] = 1 mask_edge[mask_edge_roi] = 1 if self.save_indiv is True: mask_edge_indiv[:, :, i_roi] = mask_edge_roi.astype('bool') mask_fill_indiv[:, :, i_roi] = mask_fill_roi_erode.astype('bool') i_roi = i_roi + 1 else: roi_type = roi['type'] raise NotImplementedError( f'Mask for roi type "{roi_type}" can not be created') del draw # Convert mask from free-lines to numpy array mask_edge_freeline = np.asarray(im_freeline) mask_edge_freeline = mask_edge_freeline.astype('bool') # Post-processing of fill and edge mask - if defined mask_dict = {} if np.any(mask_fill): # (1) remove edges , (2) remove small objects mask_fill = mask_fill & ~mask_edge mask_fill = morphology.remove_small_objects( mask_fill.astype('bool'), self.obj_size_rem) # For edge - consider also freeline edge mask mask_edge = mask_edge.astype('bool') mask_edge = np.logical_or(mask_edge, mask_edge_freeline) # Assign to dictionary for return mask_dict['edge'] = mask_edge mask_dict['fill'] = mask_fill.astype('bool') if self.save_indiv is True: mask_dict['edge_indiv'] = mask_edge_indiv mask_dict['fill_indiv'] = mask_fill_indiv else: mask_dict['edge_indiv'] = np.zeros(self.image_size + (1, ), dtype=np.uint8) mask_dict['fill_indiv'] = np.zeros(self.image_size + (1, ), dtype=np.uint8) # Only edge mask present elif np.any(mask_edge_freeline): mask_dict['edge'] = mask_edge_freeline mask_dict['fill'] = mask_fill.astype('bool') mask_dict['edge_indiv'] = np.zeros(self.image_size + (1, ), dtype=np.uint8) mask_dict['fill_indiv'] = np.zeros(self.image_size + (1, ), dtype=np.uint8) else: raise Exception('No mask has been created.') return mask_dict
def erode(self, size=1): """Erode the blob""" mask = self.getMask() eroded_mask = binary_erosion(mask, square(size)) self.updateUsingMask(self.bbox, eroded_mask)
def time_erosion(self, shape, footprint, radius, *args): morphology.binary_erosion(self.image, self.footprint)
def process(image): #show_images([image]) image = rgb2gray(image) if np.max(image) <= 1: image = image*255 image = image.astype('uint8') y,x = image.shape newX = x + int(x/16) newY = y + int(x/16) tempIm = np.zeros([newY,newX], dtype='uint8') tempIm[int(x/16):newY, int(x/16):newX] = np.copy(image) ################################################################# outIm = np.zeros([newY,newX], dtype='uint8') adabtiveThreshold(tempIm, outIm, newX, newY) newIm = np.copy(outIm[int(x/16):newY, int(x/16):newX]) newY, newX = newIm.shape ############################################################### #show_images([newIm]) wind = np.ones(shape=(7,7)) im = median(newIm) im2 = binary_dilation(im,wind) im2 = binary_erosion(im2,wind) im2 = im2.astype('uint8') im2 = im2*255 #show_images([im2]) z = horizontalProjection(im2[int(0.15*im2.shape[0]):int(0.6*im2.shape[0]),:]) cut = z.index(np.max(z)) cut = cut + int(0.15*im2.shape[0]) segIm = np.copy(im2[cut:im.shape[0],:]) segY, segX = segIm.shape #show_images([segIm]) #========================= Removing borders using vertical and horizontal projections =============== borders = horizontalProjection(segIm[int(0.9*segY):segY,:]) for i in range(len(borders)): if borders[i] >= int(0.2*segX): segIm[int(0.9*segY)+i,:] = 0 borders = horizontalProjection(segIm[0:int(0.1*segY),:]) for i in range(len(borders)): if borders[i] >= int(0.2*segX): segIm[i,:] = 0 borders = verticalProjection(segIm[:,0:int(0.03*segX)]) for i in range(len(borders)): if borders[i] >= int(0.2*segY): segIm[:,i] = 0 borders = verticalProjection(segIm[:,int(0.97*segX):segX]) for i in range(len(borders)): if borders[i] >= int(0.2*segY): segIm[:,int(0.97*segX)+i] = 0 borders = verticalProjection(segIm[:,int(0.49*segX):int(0.52*segX)]) for i in range(len(borders)): if borders[i] >= int(0.3*segY): segIm[:,int(0.49*segX)+i] = 0 #([segIm]) #================================================================================================== segImNumbers = np.copy(segIm[0:segY,0:int(0.5*segX)]) segImLetters = np.copy(segIm[0:segY,int(0.5*segX):segX]) segYN, segXN = segImNumbers.shape segYL, segXL = segImLetters.shape xnums = slice_digits(segImNumbers) xletrs =slice_digits(segImLetters) return xnums,xletrs
def cubefit_gen(cube, ncomp=2, paraname=None, modname=None, chisqname=None, guesses=None, errmap11name=None, multicore=None, mask_function=None, snr_min=3.0, linename="oneone", momedgetrim=True, saveguess=False, **kwargs): ''' Perform n velocity component fit on the GAS ammonia 1-1 data. (This should be the function to call for all future codes if it has been proven to be reliable) # note: the method can probably be renamed to cubefit() Parameters ---------- cube : str The file name of the ammonia 1-1 cube or a SpectralCube object ncomp : int The number of components one wish to fit. Default is 2 paraname: str The output file name of the Returns ------- pcube : 'pyspeckit.cubes.SpectralCube.Cube' Pyspeckit cube object containing both the fit and the original data cube ''' if hasattr(cube, 'spectral_axis'): pcube = pyspeckit.Cube(cube=cube) else: cubename = cube cube = SpectralCube.read(cubename) pcube = pyspeckit.Cube(filename=cubename) pcube.unit = "K" # the following check on rest-frequency may not be necessarily for GAS, but better be safe than sorry # note: this assume the data cube has the right units if cube._wcs.wcs.restfrq == np.nan: # Specify the rest frequency not present cube = cube.with_spectral_unit(u.Hz, rest_value=freq_dict[linename] * u.Hz) cube = cube.with_spectral_unit(u.km / u.s, velocity_convention='radio') if pcube.wcs.wcs.restfrq == np.nan: # Specify the rest frequency not present pcube.xarr.refX = freq_dict[linename] * u.Hz pcube.xarr.velocity_convention = 'radio' # always register the fitter just in case different lines are used fitter = ammv.nh3_multi_v_model_generator(n_comp=ncomp, linenames=[linename]) pcube.specfit.Registry.add_fitter('nh3_multi_v', fitter, fitter.npars) print "number of parameters is {0}".format(fitter.npars) print "the line to fit is {0}".format(linename) # Specify a width for the expected velocity range in the data #v_peak_hwidth = 3.0 # km/s (should be sufficient for GAS Orion, but may not be enough for KEYSTONE) v_peak_hwidth = 4.0 # km/s (should be sufficient for GAS Orion, but may not be enough for KEYSTONE) if errmap11name is not None: errmap11 = fits.getdata(errmap11name) else: # a quick way to estimate RMS as long as the noise dominates the spectrum by channels mask_finite = np.isfinite(cube._data) errmap11 = mad_std(cube._data[mask_finite], axis=0) print "median rms: {0}".format(np.nanmedian(errmap11)) snr = cube.filled_data[:].value / errmap11 peaksnr = np.nanmax(snr, axis=0) #the snr map will inetiabley be noisy, so a little smoothing kernel = Gaussian2DKernel(1) peaksnr = convolve(peaksnr, kernel) # trim the edges by 3 pixels to guess the location of the peak emission footprint_mask = np.any(np.isfinite(cube._data), axis=0) if np.logical_and(footprint_mask.size > 1000, momedgetrim): print "triming the edges to make moment maps" footprint_mask = binary_erosion(footprint_mask, disk(3)) # the following function is copied directly from GAS def default_masking(snr, snr_min=5.0): planemask = (snr > snr_min) if planemask.size > 100: planemask = remove_small_objects(planemask, min_size=40) planemask = opening(planemask, disk(1)) return (planemask) if 'maskmap' in kwargs: planemask = kwargs['maskmap'] elif mask_function is None: planemask = default_masking(peaksnr, snr_min=snr_min) else: planemask = mask_function(peaksnr, snr_min=snr_min) print "planemask size: {0}, shape: {1}".format(planemask[planemask].size, planemask.shape) # masking mask = np.isfinite(cube._data) * planemask * footprint_mask print "mask size: {0}, shape: {1}".format(mask[mask].size, mask.shape) maskcube = cube.with_mask(mask.astype(bool)) maskcube = maskcube.with_spectral_unit(u.km / u.s, velocity_convention='radio') if guesses is not None: v_guess = guesses[::4] v_guess[v_guess == 0] = np.nan else: v_guess = np.nan if np.isfinite(v_guess).sum() > 0: v_guess = v_guess[np.isfinite(v_guess)] v_median = np.median(v_guess) print "The median of the user provided velocities is: {0}".format( v_median) m0, m1, m2 = main_hf_moments(maskcube, window_hwidth=v_peak_hwidth, v_atpeak=v_median) else: m0, m1, m2 = main_hf_moments(maskcube, window_hwidth=v_peak_hwidth) v_median = np.median(m1[np.isfinite(m1)]) print "median velocity: {0}".format(v_median) if False: # save the moment maps for diagnostic purposes hdr_new = copy.deepcopy(pcube.header) hdr_new['CDELT3'] = 1 hdr_new['CTYPE3'] = 'FITPAR' hdr_new['CRVAL3'] = 0 hdr_new['CRPIX3'] = 1 savename = "{0}_moments.fits".format( os.path.splitext(paraname)[0], "parameter_maps") fitcubefile = fits.PrimaryHDU(data=np.array([m0, m1, m2]), header=hdr_new) fitcubefile.writeto(savename, overwrite=True) # remove the nana values to allow np.nanargmax(m0) to operate smoothly m0[np.isnan( m0 )] = 0.0 # I'm not sure if this is a good way to get around the sum vs nansum issue # define acceptable v range based on the provided or determined median velocity vmax = v_median + v_peak_hwidth vmin = v_median - v_peak_hwidth # find the location of the peak signal (to determine the first pixel to fit if nearest neighbour method is used) peakloc = np.nanargmax(m0) ymax, xmax = np.unravel_index(peakloc, m0.shape) # set the fit parameter limits (consistent with GAS DR1) Texmin = 3.0 # K; a more reasonable lower limit (5 K T_kin, 1e3 cm^-3 density, 1e13 cm^-2 column, 3km/s sigma) Texmax = 40 # K; DR1 T_k for Orion A is < 35 K. T_k = 40 at 1e5 cm^-3, 1e15 cm^-2, and 0.1 km/s yields Tex = 37K sigmin = 0.07 # km/s sigmax = 2.5 # km/s; for Larson's law, a 10pc cloud has sigma = 2.6 km/s taumax = 100.0 # a reasonable upper limit for GAS data. At 10K and 1e5 cm^-3 & 3e15 cm^-2 -> 70 taumin = 0.2 # note: at 1e3 cm^-3, 1e13 cm^-2, 1 km/s linewidth, 40 K -> 0.15 eps = 0.001 # a small perturbation that can be used in guesses # get the guesses based on moment maps # tex and tau guesses are chosen to reflect low density, diffusive gas that are likley to have low SNR gg = moment_guesses(m1, m2, ncomp, sigmin=sigmin, moment0=m0) if guesses is None: guesses = gg else: # fill in the blanks with moment guesses guesses[guesses == 0] = np.nan gmask = np.isfinite(guesses) guesses[~gmask] = gg[~gmask] # fill in the failed sigma guesses with moment guesses gmask = guesses[1::4] < sigmin guesses[1::4][gmask] = gg[1::4][gmask] print "user provided guesses accepted" # The guesses should be fine in the first case, but just in case, make sure the guesses are confined within the # appropriate limits guesses[::4][guesses[::4] > vmax] = vmax guesses[::4][guesses[::4] < vmin] = vmin guesses[1::4][guesses[1::4] > sigmax] = sigmax guesses[1::4][guesses[1::4] < sigmin] = sigmin + eps guesses[2::4][guesses[2::4] > Texmax] = Texmax guesses[2::4][guesses[2::4] < Texmin] = Texmin guesses[3::4][guesses[3::4] > taumax] = taumax guesses[3::4][guesses[3::4] < taumin] = taumin if saveguess: # save the guesses for diagnostic purposes hdr_new = copy.deepcopy(pcube.header) hdr_new['CDELT3'] = 1 hdr_new['CTYPE3'] = 'FITPAR' hdr_new['CRVAL3'] = 0 hdr_new['CRPIX3'] = 1 savedir = "{0}/{1}".format(path.dirname(paraname), "guesses") try: os.makedirs(savedir) except OSError as e: if e.errno != errno.EEXIST: raise savename = "{0}_guesses.fits".format( path.splitext(paraname)[0], "parameter_maps") savename = "{0}/{1}".format(savedir, path.basename(savename)) fitcubefile = fits.PrimaryHDU(data=guesses, header=hdr_new) fitcubefile.writeto(savename, overwrite=True) # set some of the fiteach() inputs to that used in GAS DR1 reduction if not 'integral' in kwargs: kwargs['integral'] = False if not 'verbose_level' in kwargs: kwargs['verbose_level'] = 3 if not 'signal_cut' in kwargs: kwargs['signal_cut'] = 2 # Now fit the cube. (Note: the function inputs are consistent with GAS DR1 whenever possible) print('start fit') # use SNR masking if not provided if not 'maskmap' in kwargs: print "mask mask!" kwargs['maskmap'] = planemask * footprint_mask if np.sum(kwargs['maskmap']) < 1: print("[WARNING]: maskmap has no pixel, no fitting will be performed") return pcube elif np.sum(np.isfinite(guesses)) < 1: print("[WARNING]: guesses has no pixel, no fitting will be performed") return pcube pcube.fiteach(fittype='nh3_multi_v', guesses=guesses, start_from_point=(xmax, ymax), use_neighbor_as_guess=False, limitedmax=[True, True, True, True] * ncomp, maxpars=[vmax, sigmax, Texmax, taumax] * ncomp, limitedmin=[True, True, True, True] * ncomp, minpars=[vmin, sigmin, Texmin, taumin] * ncomp, multicore=multicore, **kwargs) if paraname != None: save_pcube(pcube, paraname, ncomp=ncomp) if modname != None: model = SpectralCube(pcube.get_modelcube(), pcube.wcs, header=cube.header) model.write(modname, overwrite=True) if chisqname != None: chisq = get_chisq(cube, pcube.get_modelcube(), expand=20) chisqfile = fits.PrimaryHDU(data=chisq, header=cube.wcs.celestial.to_header()) chisqfile.writeto(chisqname, overwrite=True) return pcube
for clf_type in clf_types: min_error = 1000 opt_no = None y_true_train = 440 y_true_test = 400 start_training_time = time.time() mask_predicted_ = calculate_mask_predicted( clf_type=clf_type, clf=clf, bands=data_train[date][y_true_train], mask=mask_train[date][y_true_train], min_plant_size=min_plant_size) for erosion_iterations in range(0, 10): mask_predicted_ = binary_erosion(mask_predicted_) for _ in range(erosion_iterations): mask_predicted_ = binary_erosion(mask_predicted_) mask_predicted_ = remove_small_objects( mask_predicted_, min_size=min_plant_size[date]) labels, num = label(mask_predicted_, return_num=True) Y_predicted = num error = (y_true_train - Y_predicted) if np.abs(error) < min_error: min_error = np.abs(error) error_with_sign = error opt_no = erosion_iterations labels_opt = labels mask_predicted_opt = mask_predicted_ erosion_opt_iterations[date][clf_type] = opt_no end_training_time = time.time()
def standard_measures(mask, pixelsize_tract=1, pixelsize_og=1, mean_normal_list=None, fields=None): u_b, v_b, fx_b, fy_b, fx_f, fy_f, mask_fm, stress_tensor_f, stress_tensor_b = [ fields[x] for x in [ "u_b", "v_b", "fx_b", "fy_b", "fx_f", "fy_f", "mask_fm", "stress_tensor_f", "stress_tensor_b" ] ] mask = mask.astype(bool) mask_fm = mask_fm.astype(bool) cv_f, cv_b, cont_energy_b, cont_energy_f, contractile_force_b, contractile_force_f, \ mean_normal_stress_b, mean_normal_stress_f, mean_shear_b, mean_shear_f, avg_normal_stress, rel_av_norm_stress,max_shear_b,max_shear_f = [ None for i in range(14)] # suppress is equivalent to try and expect...pass with suppress(TypeError, NameError): shear_f = stress_tensor_f[:, :, 0, 1] / ( pixelsize_tract) # shear component of the stress tensor # max_shear_stress with suppress(TypeError, NameError): max_shear_f = np.sqrt(( (stress_tensor_f[:, :, 0, 0] - stress_tensor_f[:, :, 1, 1]) / 2)**2 + stress_tensor_f[:, :, 0, 1]**2) / pixelsize_tract max_shear_f = np.mean(max_shear_f[binary_erosion(mask)]) with suppress(TypeError, NameError): mean_normal_stress_f = ( (stress_tensor_f[:, :, 0, 0] + stress_tensor_f[:, :, 1, 1]) / 2) / (pixelsize_tract) mean_normal_stress_f = np.mean(mean_normal_stress_f[binary_erosion( mask)]) # mask alone is one tick to big? with suppress(TypeError, NameError): mean_shear_f = np.mean(np.abs(shear_f[binary_erosion(mask)])) # line tension # forces with suppress(TypeError, NameError): energy_points_f = strain_energy_points( u_b, v_b, fx_f, fy_f, pixelsize_og, pixelsize_tract) # contractile energy at any point # needs interpolation of mask possibley with suppress(TypeError, NameError): cont_energy_f = np.sum(energy_points_f[mask_fm]) with suppress(TypeError, NameError): contractile_force_f, proj_x, proj_y, center = contractillity( fx_f, fy_f, pixelsize_tract, mask_fm) # shear component of the stress tensor with suppress(TypeError, NameError): shear_b = stress_tensor_b[:, :, 0, 1] / (pixelsize_tract) # max_shear_stress with suppress(TypeError, NameError): max_shear_b = np.sqrt(( (stress_tensor_b[:, :, 0, 0] - stress_tensor_b[:, :, 1, 1]) / 2)**2 + stress_tensor_b[:, :, 0, 1]**2) / pixelsize_tract max_shear_b = np.mean(max_shear_b[binary_erosion(mask)]) with suppress(TypeError, NameError): mean_normal_stress_b = ( (stress_tensor_b[:, :, 0, 0] + stress_tensor_b[:, :, 1, 1]) / 2) / (pixelsize_tract) mean_normal_stress_b = np.mean( mean_normal_stress_b[binary_erosion(mask)]) with suppress(TypeError, NameError): mean_shear_b = np.mean(np.abs(shear_b[binary_erosion(mask)])) # line tension # forces with suppress(TypeError, NameError): energy_points_b = strain_energy_points( u_b, v_b, fx_b, fy_b, pixelsize_og, pixelsize_tract) # contractile energy at any point # needs interpolation of mask possibley with suppress(TypeError, NameError): cont_energy_b = np.sum(energy_points_b[mask_fm]) with suppress(TypeError, NameError): contractile_force_b, proj_x, proj_y, center = contractillity( fx_b, fy_b, pixelsize_tract, mask_fm) with suppress(TypeError, NameError): cv_f = coefficient_of_variation( binary_erosion(mask), ((stress_tensor_f[:, :, 0, 0] + stress_tensor_f[:, :, 1, 1]) / 2) / (pixelsize_tract), 0) with suppress(TypeError, NameError): cv_b = coefficient_of_variation( binary_erosion(mask), ((stress_tensor_b[:, :, 0, 0] + stress_tensor_b[:, :, 1, 1]) / 2) / (pixelsize_tract), 0) with suppress(TypeError, NameError): avg_normal_stress_be = [ np.nanmean(ms[mask]) for ms in mean_normal_list ] with suppress(TypeError, NameError): rel_av_norm_stress = [ x / mean_normal_stress_b for x in avg_normal_stress_be ] measures = { "mask_fm": mask_fm, "mask": mask, "cv_f": cv_f, "cv_b": cv_b, "cont_energy_b": cont_energy_b, "cont_energy_f": cont_energy_f, "contractile_force_b": contractile_force_b, "contractile_force_f": contractile_force_f, "mean_normal_stress_b": mean_normal_stress_b, "mean_normal_stress_f": mean_normal_stress_f, "mean_shear_b": mean_shear_b, "mean_shear_f": mean_shear_f, "max_shear_f": max_shear_f, "max_shear_b": max_shear_b, "avg_normal_stress_be": avg_normal_stress_be, "rel_av_norm_stress": rel_av_norm_stress } return measures
def s2_pre_processing(s2_dir, temp_angle=False, s2_angle_dir='/home/users/marcyin/acix/s2_angle/'): s2_dir = os.path.abspath(s2_dir) scihub = [] aws = [] logger = create_logger() logger.propagate = False for (dirpath, dirnames, filenames) in os.walk(s2_dir): if len(filenames) > 0: temp = [dirpath + '/' + i for i in filenames] for j in temp: if ('MTD' in j) & ('TL' in j) & ('xml' in j): scihub.append(j) if 'metadata.xml' in j: aws.append(j) s2_tiles = [] for metafile in scihub + aws: if 'metadata.xml' in j: with open(metafile) as f: for i in f.readlines(): if 'TILE_ID' in i: tile = i.split('</')[0].split('>')[-1] else: tile = metafile.split('/')[-4] top_dir = os.path.dirname(metafile) log_file = top_dir + '/SIAC_S2.log' if os.path.exists(log_file): os.remove(log_file) logger.info('Preprocessing for %s' % tile) logger.info('Doing per pixel angle resampling.') bands = [ 'B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08', 'B8A', 'B09', 'B10', 'B11', 'B12' ] # if len(glob(top_dir + '/ANG_DATA/*.tif')) == 14: # sun_ang_name = top_dir + '/ANG_DATA/SAA_SZA.tif' # view_angs = glob(top_dir + '/ANG_DATA/VAA_VZA_B??.tif') # toa_refs = glob(top_dir + '/IMG_DATA/*B??.jp2') # view_ang_names = sorted(view_angs, key = lambda fname: bands.index(fname.split('_')[-1].split('.tif')[0])) # toa_refs = sorted(toa_refs, key = lambda toa_ref: bands.index('B' + toa_ref.split('B')[-1][:2])) # cloud_name = top_dir + '/cloud.tif' # else: # sun_ang_name, view_ang_names, toa_refs, cloud_name = resample_s2_angles(metafile) sun_ang_name, view_ang_names, toa_refs, cloud_name = resample_s2_angles( metafile, temp_angle, s2_angle_dir) cloud_bands = np.array(toa_refs)[[0, 1, 3, 4, 7, 8, 9, 10, 11, 12]] logger.info('Getting cloud mask.') if not os.path.exists(cloud_name): cloud = do_cloud(cloud_bands, cloud_name) else: cloud = gdal.Open(cloud_name).ReadAsArray() / 100. cloud_mask = (cloud > 0.4) & (cloud != 2.56 ) # 0.4 is the sentinel hub default clean_pixel = ( (cloud != 2.56).sum() - cloud_mask.sum()) / cloud_mask.size * 100. valid_pixel = (cloud != 2.56).sum() / cloud_mask.size * 100. logger.info('Valid pixel percentage: %.02f' % (valid_pixel)) logger.info('Clean pixel percentage: %.02f' % (clean_pixel)) cloud_mask = binary_dilation(binary_erosion(cloud_mask, disk(2)), disk(3)) | (cloud < 0) s2_tiles.append([ sun_ang_name, view_ang_names, toa_refs, cloud_name, cloud_mask, metafile ]) handlers = logger.handlers[:] for handler in handlers: handler.close() logger.removeHandler(handler) return s2_tiles
def anim_traj( df, tif, show_image=True, show_scalebar=True, pixel_size=None, scalebar_pos='upper right', scalebar_fontsize='large', scalebar_length=0.3, scalebar_height=0.02, scalebar_boxcolor=(1, 1, 1), scalebar_boxcolor_alpha=0, cb_fontsize='large', show_colorbar=True, cb_min=None, cb_max=None, cb_major_ticker=None, cb_minor_ticker=None, cb_pos='right', cb_tick_loc='right', plot_r=False, show_traj_num=False, fontname='Arial', show_tail=True, tail_length=50, show_boundary=False, boundary_masks=None, dpi=150, ): """ Animate blob in the tif video. Pseudo code ---------- 1. If df is empty, return. 2. Initialize fig, ax, and xlim, ylim based on df. 3. Add scale bar. 4. Animate blobs. Parameters ---------- df : DataFrame DataFrame containing 'x', 'y', 'frame'. tif : Numpy array tif stack in format of 3d numpy array. pixel_size : None or float If None, no scalebar. If float, add scalebar with specified pixel size in um. scalebar_color : tuple RGB or RGBA tuple to define the scalebar color scalebar_pos : string position string. ('upper right'...) scalebar_length : float scalebar length relative to ax scalebar_height : float scalebar height relative to ax scalebar_boxcolor : tuple RGB or RGBA tuple to define the scalebar background box color scalebar_boxcolor_alpha : float Define the transparency of the background box color cb_fontsize : string or integer Define the colorbar label text size. eg. 'large', 'x-large', 10, 40... cb_min, cb_max: float [cb_min, cb_max] is the color bar range. cb_major_ticker, cb_minor_ticker: float Major and minor ticker setting for the color bar. cb_pos : string append_axes position string. ('right', 'top'...) cb_tick_loc : string colorbar tick position string. ('right', 'top'...) show_colorbar : bool If False, only return colormap and df, no colorbar added. show_image : bool if True, show animation of top of image. if False, only show blobs without image. tail_length : int how many frames will the traj last. dpi : int dpi setting for plt.subplots(). Returns ------- 3d numpy array. Examples -------- anim_tif = anim_traj(df, tif, pixel_size=0.163, show_image=True) imsave('anim-result.tif', anim_tif) """ # """ # ~~~~~~~~~~~Check if df is empty~~~~~~~~~~~~ # """ if df.empty: print('df is empty. No traj to animate!') return anim_tif = [] for i in range(len(tif)): print("Animate frame %d" % i) curr_df = df[df['frame'] == i] # """ # ~~~~~~~~Initialize fig, ax, and xlim, ylim based on df~~~~~~~~ # """ fig, ax = plt.subplots(figsize=(8, 6), dpi=dpi) ax.set_xticks([]) ax.set_yticks([]) if not show_image: x_range = (df['y'].max() - df['y'].min()) y_range = (df['x'].max() - df['x'].min()) ax.set_xlim(df['y'].min() - 0.1 * x_range, df['y'].max() + 0.1 * x_range) ax.set_ylim(df['x'].max() + 0.1 * y_range, df['x'].min() - 0.1 * y_range) else: ax.imshow(tif[i], cmap='gray', aspect='equal') ax.set_xlim(0, tif[0].shape[1]) ax.set_ylim(0, tif[0].shape[0]) for spine in ['top', 'bottom', 'left', 'right']: ax.spines[spine].set_visible(False) # """ # ~~~~~~~~Add scale bar~~~~~~~~ # """ if show_scalebar and pixel_size: add_scalebar( ax, units='um', sb_color=(0.5, 0.5, 0.5), fontname='Arial', pixel_size=pixel_size, sb_pos=scalebar_pos, fontsize=scalebar_fontsize, length_fraction=scalebar_length, height_fraction=scalebar_height, box_color=scalebar_boxcolor, box_alpha=scalebar_boxcolor_alpha, ) # """ # ~~~~~~~~customized the colorbar, then add it~~~~~~~~ # """ if 'D' in df: df, colormap = add_outside_colorbar( ax, df, data_col='D', cb_colormap='coolwarm', label_font_size=cb_fontsize, cb_min=cb_min, cb_max=cb_max, cb_major_ticker=cb_major_ticker, cb_minor_ticker=cb_minor_ticker, show_colorbar=show_colorbar, label_str=r'D (nm$^2$/s)', cb_pos=cb_pos, cb_tick_loc=cb_tick_loc, ) else: df, colormap = add_outside_colorbar( ax, df, data_col='particle', cb_colormap='jet', label_font_size=cb_fontsize, cb_min=cb_min, cb_max=cb_max, cb_major_ticker=cb_major_ticker, cb_minor_ticker=cb_minor_ticker, show_colorbar=show_colorbar, label_str='particle', cb_pos=cb_pos, cb_tick_loc=cb_tick_loc, ) # """ # ~~~~~~~~Add traj num~~~~~~~~ # """ if show_traj_num: particles = curr_df.particle.unique() ax.text(0.95, 0.00, """ Total trajectory number: %d """ % (len(particles)), horizontalalignment='right', verticalalignment='bottom', fontsize=12, color=(0.5, 0.5, 0.5, 0.5), transform=ax.transAxes, weight='bold', fontname=fontname) # """ # ~~~~~~~~Animate curr blob~~~~~~~~ # Backup code for color coded blob animation: # for ind in curr_df.index: # partcle_color = colormap(curr_df.loc[ind, 'D_norm']) # y, x, r = curr_df.loc[ind, 'x'], curr_df.loc[ind, 'y'], curr_df.loc[ind, 'r'] # ax.scatter(x, y, # s=5, # marker='^', # c=[partcle_color]) # if False: # c = plt.Circle((x,y), r, color=partcle_color, # linewidth=1, fill=False) # ax.add_patch(c) # """ anno_blob(ax, curr_df, marker='^', markersize=3, plot_r=plot_r, color=(0, 0, 1)) # """ # ~~~~~~~~Animate particle tail~~~~~~~~ # """ if show_tail: particles = curr_df.particle.unique() for particle_num in particles: traj = df[df.particle == particle_num] traj = traj[traj['frame'].isin(range(i - tail_length, i + 1))] traj = traj.sort_values(by='frame') # """ # ~~~~~~~~Animate cilia global trajectory if exists~~~~~~~~ # """ if 'x_global' in df.columns and 'y_global' in df.columns: ax.plot(traj['y_global'], traj['x_global'], '-', linewidth=0.5, color=(0, 1, 0)) if 'D_norm' in traj: ax.plot(traj['y'], traj['x'], linewidth=0.5, color=colormap(traj['D_norm'].mean())) else: ax.plot(traj['y'], traj['x'], linewidth=0.5, color=colormap(traj['particle_norm'].mean())) # """ # ~~~~~~~~Animate boundary~~~~~~~~ # """ if show_boundary: curr_mask = boundary_masks[i] selem = disk(1) bdr_pixels = curr_mask - binary_erosion(curr_mask, selem) bdr_coords = np.nonzero(bdr_pixels) ax.plot(bdr_coords[1], bdr_coords[0], 'o', markersize=1, linewidth=0.5, color=(0, 1, 0, 1)) # """ # ~~~~~~~~save curr figure~~~~~~~~ # """ curr_plt_array = plot_end(fig, pltshow=False) anim_tif.append(curr_plt_array) anim_tif = np.array(anim_tif) return anim_tif
thresh_img = np.where(image < 0, 1.0, 0.) regions = regionprops(thresh_img.astype(int)) for region in regions: if region.area > maxAllowedArea: prediction = unet_predict([image], predict_fn) prediction[prediction < THRESHOLD] = 0 prediction[prediction > 0] = 1 prediction = prediction.reshape(324, 324) # localize the center of nodule if np.amax(prediction) > 0: centers = [] 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))
import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as mp from skimage.filter.rank import entropy,otsu from skimage.filter import threshold_otsu from skimage.morphology import square,rectangle,label,closing,disk,binary_erosion,opening from skimage.color import label2rgb,rgb2gray from skimage.segmentation import clear_border from skimage.measure import regionprops from skimage import io i=rgb2gray(io.imread('z.jpg')) t=threshold_otsu(i) i=i>t z=binary_erosion(1-i,square(3)) i=1-z i=entropy(i,rectangle(10,1)) t=threshold_otsu(i) c=i>t c=closing(c,rectangle(4,28)) b=c.copy() clear_border(b) l=label(b) z=np.logical_xor(c,b) l[z]=-1 iol=label2rgb(l,image=i) fig,ax=plt.subplots(ncols=1,nrows=1,figsize=(6,6)) ax.imshow(iol) for region in regionprops(l,['Area','BoundingBox']): if region['Area']<3500: continue minr,minc,maxr,maxc=region['BoundingBox']
def erosao(img, est): out = skm.binary_erosion(img, est) return out
def main(): opt = TestOptions() args = opt.initialize() if not os.path.exists(args.save): os.makedirs(args.save) model = CreateSSLModel(args) cudnn.enabled = True cudnn.benchmark = True model.train() model.cuda() targetloader = CreateTrgDataSSLLoader(args) #predicted_label = np.zeros((len(targetloader), 1634, 1634)) predicted_label = np.zeros((len(targetloader), 2056, 2124)) #predicted_prob = np.zeros((len(targetloader), 1634, 1634)) predicted_prob = np.zeros((len(targetloader), 2056, 2124)) image_name = [] for index, batch in enumerate(targetloader): if index % 10 == 0: print('%d processd' % index) image, _, name = batch image = Variable(image).cuda() _, output, _, _ = model(image, ssl=True) output = nn.functional.softmax(output / args.alpha, dim=1) #output = nn.functional.upsample(output, (1634, 1634), mode='bilinear', align_corners=True).cpu().data[0].numpy() output = nn.functional.upsample( output, (2056, 2124), mode='bilinear', align_corners=True).cpu().data[0].numpy() output = output.transpose(1, 2, 0) label, prob = np.argmax(output, axis=2), np.max(output, axis=2) cup_mask = get_bool(label, 0) disc_mask = get_bool(label, 0) + get_bool(label, 1) disc_mask = disc_mask.astype(np.uint8) cup_mask = cup_mask.astype(np.uint8) for i in range(5): disc_mask = scipy.signal.medfilt2d(disc_mask, 19) cup_mask = scipy.signal.medfilt2d(cup_mask, 19) disc_mask = morphology.binary_erosion(disc_mask, morphology.diamond(7)).astype( np.uint8) # return 0,1 cup_mask = morphology.binary_erosion(cup_mask, morphology.diamond(7)).astype( np.uint8) # return 0,1 disc_mask = get_largest_fillhole(disc_mask) cup_mask = get_largest_fillhole(cup_mask) disc_mask = morphology.binary_dilation(disc_mask, morphology.diamond(7)).astype( np.uint8) # return 0,1 cup_mask = morphology.binary_dilation(cup_mask, morphology.diamond(7)).astype( np.uint8) # return 0,1 disc_mask = get_largest_fillhole(disc_mask).astype( np.uint8) # return 0,1 cup_mask = get_largest_fillhole(cup_mask).astype(np.uint8) label = disc_mask + cup_mask predicted_label[index] = label.copy() predicted_prob[index] = prob.copy() image_name.append(name[0]) thres = [] for i in range(3): x = predicted_prob[predicted_label == i] if len(x) == 0: thres.append(0) continue x = np.sort(x) #print(len(x)) print(i, x) print(np.sum(x < 0.5), '/', len(x), np.sum(x < 0.5) / len(x)) #thres.append(x[np.int(np.round(len(x) *int(args.p[i])))]) thres.append(0.5) thres = np.array(thres) print(thres) # thres[thres > 0.6] = 0.6 color_labels = {0: 255, 1: 128, 2: 0} #import pdb;pdb.set_trace() for index in range(len(targetloader)): name = image_name[index] label = predicted_label[index] # label_min:0 label_max=2 #print(label) prob = predicted_prob[index] # prob_min:0.5 prob_max=1.0 #print(prob) for i, color in color_labels.items(): label[label == i] = color #print(thres[i]) label[(prob > thres[i]) * (label == i)] = color output = np.asarray(label, dtype=np.uint8) output = Image.fromarray(output.astype(np.uint8)) #name = name.split('.')[0] + '.png' name = name.split('_')[0] + '.bmp' output.save('%s/%s' % (args.save, name)) disc_dice, cup_dice = calculate_dice(args.gt_dir, args.save, args.devkit_dir) print('===> disc_dice:' + str(round(disc_dice, 3)) + '\t' + 'cup_dice:' + str(round(cup_dice, 3)))
def _generate_binary_masks(annot_dict, shape, erose_size=5, obj_size_rem=500, save_indiv=False): # Get dimensions of image and created masks of same size # This we need to save somewhere (e.g. as part of the geojson file?) # Filled masks and edge mask for polygons mask_fill = np.zeros(shape, dtype=np.uint8) mask_edge = np.zeros(shape, dtype=np.uint8) mask_labels = np.zeros(shape, dtype=np.uint16) rr_all = [] cc_all = [] if save_indiv is True: mask_edge_indiv = np.zeros( (shape[0], shape[1], len(annot_dict)), dtype=np.bool ) mask_fill_indiv = np.zeros( (shape[0], shape[1], len(annot_dict)), dtype=np.bool ) # Image used to draw lines - for edge mask for freelines im_freeline = Image.new("1", (shape[1], shape[0]), color=0) draw = ImageDraw.Draw(im_freeline) # Loop over all roi i_roi = 0 for roi_key, roi in annot_dict.items(): roi_pos = roi["pos"] # Check region type # freeline - line if roi["type"] == "freeline" or roi["type"] == "LineString": # Loop over all pairs of points to draw the line for ind in range(roi_pos.shape[0] - 1): line_pos = ( roi_pos[ind, 1], roi_pos[ind, 0], roi_pos[ind + 1, 1], roi_pos[ind + 1, 0], ) draw.line(line_pos, fill=1, width=erose_size) # freehand - polygon elif ( roi["type"] == "freehand" or roi["type"] == "polygon" or roi["type"] == "polyline" or roi["type"] == "Polygon" ): # Draw polygon rr, cc = skimage_draw.polygon( [shape[0] - r for r in roi_pos[:, 1]], roi_pos[:, 0] ) # Make sure it's not outside rr[rr < 0] = 0 rr[rr > shape[0] - 1] = shape[0] - 1 cc[cc < 0] = 0 cc[cc > shape[1] - 1] = shape[1] - 1 # Test if this region has already been added if any(np.array_equal(rr, rr_test) for rr_test in rr_all) and any( np.array_equal(cc, cc_test) for cc_test in cc_all ): # print('Region #{} has already been used'.format(i + # 1)) continue rr_all.append(rr) cc_all.append(cc) # Generate mask mask_fill_roi = np.zeros(shape, dtype=np.uint8) mask_fill_roi[rr, cc] = 1 # Erode to get cell edge - both arrays are boolean to be used as # index arrays later mask_fill_roi_erode = morphology.binary_erosion( mask_fill_roi, np.ones((erose_size, erose_size)) ) mask_edge_roi = ( mask_fill_roi.astype("int") - mask_fill_roi_erode.astype("int") ).astype("bool") # Save array for mask and edge mask_fill[mask_fill_roi > 0] = 1 mask_edge[mask_edge_roi] = 1 mask_labels[mask_fill_roi > 0] = i_roi + 1 if save_indiv is True: mask_edge_indiv[:, :, i_roi] = mask_edge_roi.astype("bool") mask_fill_indiv[:, :, i_roi] = mask_fill_roi_erode.astype("bool") i_roi = i_roi + 1 else: roi_type = roi["type"] raise NotImplementedError( f'Mask for roi type "{roi_type}" can not be created' ) del draw # Convert mask from free-lines to numpy array mask_edge_freeline = np.asarray(im_freeline) mask_edge_freeline = mask_edge_freeline.astype("bool") # Post-processing of fill and edge mask - if defined mask_dict = {} if np.any(mask_fill): # (1) remove edges , (2) remove small objects mask_fill = mask_fill & ~mask_edge mask_fill = morphology.remove_small_objects( mask_fill.astype("bool"), obj_size_rem ) # For edge - consider also freeline edge mask mask_edge = mask_edge.astype("bool") mask_edge = np.logical_or(mask_edge, mask_edge_freeline) # Assign to dictionary for return mask_dict["edge"] = mask_edge mask_dict["fill"] = mask_fill.astype("bool") mask_dict["labels"] = mask_labels.astype("uint16") if save_indiv is True: mask_dict["edge_indiv"] = mask_edge_indiv mask_dict["fill_indiv"] = mask_fill_indiv else: mask_dict["edge_indiv"] = np.zeros(shape + (1,), dtype=np.uint8) mask_dict["fill_indiv"] = np.zeros(shape + (1,), dtype=np.uint8) # Only edge mask present elif np.any(mask_edge_freeline): mask_dict["edge"] = mask_edge_freeline mask_dict["fill"] = mask_fill.astype("bool") mask_dict["labels"] = mask_labels.astype("uint16") mask_dict["edge_indiv"] = np.zeros(shape + (1,), dtype=np.uint8) mask_dict["fill_indiv"] = np.zeros(shape + (1,), dtype=np.uint8) else: raise Exception("No mask has been created.") return mask_dict
def getSquareCoords(imgArr, imgSize=(1024, 768), erosR=7, openR=10, bordW=80, boardDim=(8,8)): # calculate threshold using otsu and apply intensityTh = threshold_otsu(imgArr) imgThArr = (imgArr < intensityTh) #Image.fromarray(255*imgThArr.astype(np.uint8)).show() # morphologically erode then open binary images imgMorphArr = binary_opening(binary_erosion(imgThArr, selem=square(erosR)), selem=square(openR)) #Image.fromarray(255*imgMorphArr.astype(np.uint8)).show() # remove border regions imgClearArr = clear_border(imgMorphArr, buffer_size=bordW) #Image.fromarray(255*imgClearArr.astype(np.uint8)).show() # apply connected-component labelling imgLabArr = label(imgClearArr) #Image.fromarray(55*(imgLabArr>0)+200*imgLabArr/np.max(imgLabArr).astype(np.uint8)).show() # remove regions of size x: median(regionSize)/2 < x < 2*median(regionSize) ---- (option: then reapply connected-component labelling?) regionStatsFull = regionprops(imgLabArr, coordinates="xy") regionStats = np.array([[region.label, region.area, region.centroid[0], region.centroid[1], region.extent] for region in regionStatsFull]) for region in range(len(regionStats)): if regionStats[region, 1] < np.median(regionStats, axis=0)[1]/2 or regionStats[region, 1] > np.median(regionStats, axis=0)[1]*2: imgLabArr = imgLabArr * (imgLabArr != region+1) regionStats = regionStats[(regionStats[:, 1] >= np.median(regionStats, axis=0)[1]/2) & (regionStats[:, 1] < np.median(regionStats, axis=0)[1]*2)] #Image.fromarray(55*(imgLabArr>0)+imgLabArr*200/np.max(imgLabArr).astype(np.uint8)).show() # calculate how much to rotate image by angleList = [] regionRowSort = regionStats[np.argsort(regionStats[:, 2])] regionRowSort = np.array([region for region in regionRowSort if region[4] >= 0.75]) rowGapTh = np.max(regionRowSort[1:, 2]-regionRowSort[0:-1, 2])/2 regionRowGroup = np.concatenate((np.zeros(1),np.cumsum((regionRowSort[1:, 2]-regionRowSort[0:-1, 2]) > rowGapTh)), axis=None) for rowGroup in range(int(np.max(regionRowGroup)+1)): if sum(regionRowGroup == rowGroup) > 1: A = np.array([[regionRowSort[region,3], 1] for region in np.arange(regionRowGroup.size)[regionRowGroup==rowGroup]]) y = regionRowSort[np.arange(regionRowGroup.size)[regionRowGroup == rowGroup], 2] m, c = np.linalg.lstsq(A, y - np.mean(y), rcond=None)[0] angleList.append(np.arctan(m)) regionColSort = regionStats[np.argsort(regionStats[:, 3])] regionColSort = np.array([region for region in regionColSort if region[4] >= 0.75]) colGapTh = np.max(regionColSort[1:, 3]-regionColSort[0:-1, 3])/2 regionColGroup = np.concatenate((np.zeros(1),np.cumsum((regionColSort[1:, 3]-regionColSort[0:-1, 3]) > colGapTh)), axis=None) for colGroup in range(int(np.max(regionColGroup)+1)): if sum(regionColGroup == colGroup) > 1: A = np.array([[regionColSort[region,3], 1] for region in np.arange(regionColGroup.size)[regionColGroup==colGroup]]) y = regionColSort[np.arange(regionColGroup.size)[regionColGroup == colGroup], 2] m, c = np.linalg.lstsq(A, y - np.mean(y), rcond=None)[0] angleList.append(np.arctan(m)-np.pi/2) rotateAngle = np.median(angleList)*180/np.pi #Image.fromarray(55*(imgLabArr>0)+imgLabArr*200/np.max(imgLabArr).astype(np.uint8)).rotate(angle=rotateAngle, fillcolor=0).show() # find minimums of row sums and column sums imgLabArr = np.array(Image.fromarray(imgLabArr*255/np.max(imgLabArr).astype(np.uint8)).rotate(angle=rotateAngle, fillcolor=0))>0 imgCS = np.reshape(np.sum(imgLabArr > 0, axis=0), (np.shape(imgLabArr)[1])) imgRS = np.reshape(np.sum(imgLabArr > 0, axis=1), (np.shape(imgLabArr)[0])) pECS = np.convolve(imgCS < threshold_otsu(imgCS), np.asarray([1/2, 1/2])) pERS = np.convolve(imgRS < threshold_otsu(imgRS), np.asarray([1/2, 1/2])) pEIndCS = np.asarray([i for i in range(imgSize[0]-1) if pECS[i + 1] == 1/2]) pEIndRS = np.asarray([i for i in range(imgSize[1]-1) if pERS[i + 1] == 1/2]) imgVL = np.asarray([pEIndCS[0]-erosR/2]+[(pEIndCS[2*i-1]+pEIndCS[2*i])/2 for i in range(1, int(len(pEIndCS)/2))]+[pEIndCS[-1]+erosR/2]) imgHL = np.asarray([pEIndRS[0]-erosR/2]+[(pEIndRS[2*i-1]+pEIndRS[2*i])/2 for i in range(1, int(len(pEIndRS)/2))]+[pEIndRS[-1]+erosR/2]) imgVL_Diff = imgVL[1:]-imgVL[0:-1] imgHL_Diff = imgHL[1:]-imgHL[0:-1] if imgHL_Diff.shape[0] != boardDim[0]: imgHL = imgHL[0] + np.median(imgHL_Diff)*np.arange(boardDim[0]+1) elif np.sum(np.abs(imgHL_Diff - np.median(imgHL_Diff)) > 0.2*np.median(imgHL_Diff)) > 0: imgHL = ((boardDim[0]*np.median(imgHL_Diff) + 3*imgHL[0] - imgHL[-1])/2) + np.median(imgHL_Diff)*np.arange(boardDim[0]+1) if imgVL_Diff.shape[0] != boardDim[1]: imgVL = imgVL[0] + np.median(imgVL_Diff)*np.arange(boardDim[1]+1) #imgVL[5:] += 0.01*np.median(imgVL_Diff) # to account for centre hinge elif np.sum(np.abs(imgVL_Diff - np.median(imgVL_Diff)) > 0.2*np.median(imgVL_Diff)) > 0: imgVL = (((boardDim[1]*np.median(imgVL_Diff) + 3*imgVL[0] - imgVL[-1])/2) + np.median(imgVL_Diff)*np.arange(boardDim[1]+1)) # return imgHL and imgVL return rotateAngle, imgVL.astype(int), imgHL.astype(int)
def get_segmented_lungs(img_dir, plot=False, min_lung_area=3000, padding_num=0): """ :param img_dir: Input image path :param plot: Whether to show pictures or not :param min_lung_area: The minimum possible area of a lung (as a threshold) :param padding_num: Interception needs padding size :return: True or False (img is useful or not) """ src_img = cv2.imread(img_dir) img = Image.open(img_dir) img = np.array(img)[:, :, 0] img = img.astype(np.int16) img = img * 3 img -= 1000 im = img.copy() ''' This funtion segments the lungs from the given 2D slice. ''' if plot == True: f, plots = plt.subplots(8, 1, figsize=(5, 40)) ''' Step 1: Convert into a binary image. ''' binary = im < -600 if plot == True: plots[0].axis('off') plots[0].imshow(binary, cmap=plt.cm.bone) ''' Step 2: Remove the blobs connected to the border of the image. ''' cleared = clear_border(binary) if plot == True: plots[1].axis('off') plots[1].imshow(cleared, cmap=plt.cm.bone) ''' Step 3: Label the image. ''' label_image = label(cleared) if plot == True: plots[2].axis('off') plots[2].imshow(label_image, cmap=plt.cm.bone) ''' Step 4: Keep the labels with 2 largest areas. ''' areas = [r.area for r in regionprops(label_image)] areas.sort() if len(areas) > 2: for region in regionprops(label_image): if region.area < areas[-2] or region.area < min_lung_area: for coordinates in region.coords: label_image[coordinates[0], coordinates[1]] = 0 binary = label_image > 0 if plot == True: plots[3].axis('off') plots[3].imshow(binary, cmap=plt.cm.bone) ''' Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels. ''' selem = disk(2) binary = binary_erosion(binary, selem) if plot == True: plots[4].axis('off') plots[4].imshow(binary, cmap=plt.cm.bone) ''' Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall. ''' selem = disk(10) binary = binary_closing(binary, selem) if plot == True: plots[5].axis('off') plots[5].imshow(binary, cmap=plt.cm.bone) ''' Step 7: Fill in the small holes inside the binary mask of lungs. ''' edges = roberts(binary) binary = ndi.binary_fill_holes(edges) if plot == True: plots[6].axis('off') plots[6].imshow(binary, cmap=plt.cm.bone) ''' Step 8: Superimpose the binary mask on the input image. ''' get_high_vals = binary == 0 im[get_high_vals] = 0 if plot == True: plots[7].axis('off') plots[7].imshow(im, cmap=plt.cm.bone) mask = binary.astype(int) mask_img = np.zeros(src_img.shape, dtype=src_img.dtype) mask_img[mask == 1] = [255, 255, 0] if plot == True: plt.figure(figsize=(12, 12)) plt.imshow(mask_img) plt.show() if mask_img.mean() < 7: return (False, [], [], []) else: # Find the smallest effective rectangle surrounding the lungs gray = cv2.cvtColor(mask_img, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) label_img = np.zeros(src_img.shape) cv2.drawContours(label_img, contours, -1, (255, 255, 0), thickness=cv2.FILLED) minx, miny, maxx, maxy = src_img.shape[1], src_img.shape[0], 0, 0 for c in contours: if cv2.contourArea(c) > min_lung_area: temp_minx = np.min(c[:, 0, 0]) temp_miny = np.min(c[:, 0, 1]) temp_maxx = np.max(c[:, 0, 0]) temp_maxy = np.max(c[:, 0, 1]) if temp_minx < minx: minx = temp_minx if temp_miny < miny: miny = temp_miny if temp_maxx > maxx: maxx = temp_maxx if temp_maxy > maxy: maxy = temp_maxy crop_img = src_img[miny - padding_num:maxy + padding_num, minx - padding_num:maxx + padding_num] crop_mask = mask[miny - padding_num:maxy + padding_num, minx - padding_num:maxx + padding_num] crop_copy = crop_img.copy() crop_img[crop_mask == 0] = [0, 0 , 0] if plot == True: plt.figure(figsize=(9, 9)) plt.imshow(crop_img, cmap='gray') plt.show() # fill crop area crop_mask = np.stack([crop_mask] * 3, 2) background = entity_filling(crop_img, crop_mask) filled_crop_img = np.where(crop_mask == 1, crop_img, background) filled_crop_img = np.array(filled_crop_img, dtype=np.int16) return (True, filled_crop_img, crop_img, crop_copy)
rr, cc = line(x - 10, y - 8, x + 10, y + 8) Iout[rr, cc, :] = [1, 0, 0] rr, cc = line(x + 10, y - 8, x - 10, y + 8) Iout[rr, cc, :] = [1, 0, 0] return (Iout) A = io.imread(imageLoadingFolder + "\digits_binary_inv.png") A2 = np.where(A < A.max() / 8, 1, 0) #direct cut out of letter x from A2 F1 = A2[0:40, 60:90] F1_miss = np.where(F2 == True, 0, 1) F2 = binary_erosion(A2[0:40, 60:90]) F2_miss = np.where( binary_dilation(binary_dilation(binary_dilation(F2))) == True, 0, 1) #closing on cutout # F2 = medial_axis(closing(F1/np.max(F1))) # H, _ = np.histogram(A/A.max()*256, bins = 256, range = (-0.5,255.5)) fdim = [25, 8] fig = plt.figure(figsize=(fdim[0], fdim[1]), constrained_layout=True) # gs = fig.add_gridspec(fdim[0], fdim[1]) # plt.subplot(gs[0:8,0:4]) #fig_d[0], fig_d[1], 1) # plotImage(gca(), A2, 'Binary Image', gray=True)
def read_and_process_directory(base_directory, norm_window, min_hole_size, min_cell_size, extrema_blur, peak_sep, formatted_titles, channel_list): # process all .tif files in a passed directory and returns results dataframe (.csv) # set up paths time_stamp = dt.now().strftime('%Y_%m_%d_%H_%M_%S') save_path = '_extracted_data_%s' % time_stamp save_path = os.path.join(base_directory, save_path) print('base: ' + base_directory) print('save: ' + save_path) print('channel_list: ', channel_list) os.mkdir(save_path) # get paths for images in base directory image_list = glob.glob(os.path.join(base_directory, '*.TIF')) # '.TIF' or '.tif' image_list = image_list + glob.glob(os.path.join(base_directory, '*.tif')) # initialize results dataframe results_df = pd.DataFrame() # iteratively read in images by filenames for i, img_path in enumerate(image_list): img = plt.imread(img_path) name = os.path.basename(img_path) print('\n') print(name) print('img ' + str(i + 1) + ' of ' + str(len(image_list))) img, labeled_cells, cell_props, n_chan = process_image( img, norm_window, min_hole_size, min_cell_size, extrema_blur, peak_sep, name, save_path) # save all cell quant in results dataframe img_df = pd.DataFrame() for count, key in enumerate(cell_props.keys()): channel_data = cell_props[key] if np.logical_and( len(np.shape(img)) > 2, str(count) in channel_list): if count < n_chan: bg = filters.threshold_local(img[:, :, count], norm_window) for c, cell in enumerate(channel_data): if c % 10 == 0: pct_done = ((c + (len(channel_data) * count)) / len(channel_data)) pct_done = np.round( (pct_done / len(cell_props.keys())) * 100, decimals=3) print('img ' + str(pct_done) + '% complete ' + '(channel ' + str(count + 1) + ' of ' + str(len(cell_props.keys())) + ', cell ' + str(c + 1) + ' of ' + str(len(channel_data)) + ')') if count == 0: if formatted_titles: img_df = img_df.append( { '_image_name': name, '_img_cell_#': c, '_clone': name[14:17], '_moi': float(name[18:20]), '_days_post_inf': float(name[22:24]), 'area_ch' + str(count): channel_data[c]['area'], 'log_area_ch' + str(count): np.log10(channel_data[c]['area']), 'max_ch' + str(count): channel_data[c]['max_intensity'], 'min_ch' + str(count): channel_data[c]['min_intensity'], 'mean_ch' + str(count): channel_data[c]['mean_intensity'], 'extent_ch' + str(count): channel_data[c]['extent'], 'eccentricity_ch' + str(count): channel_data[c]['eccentricity'], 'perimeter_ch' + str(count): channel_data[c]['perimeter'], 'major_axis_ch' + str(count): channel_data[c]['major_axis_length'], 'minor_axis_ch' + str(count): channel_data[c]['minor_axis_length'] }, ignore_index=True) else: img_df = img_df.append( { '_image_name': name, '_img_cell_#': c, 'area_ch' + str(count): channel_data[c]['area'], 'log_area_ch' + str(count): np.log10(channel_data[c]['area']), 'max_ch' + str(count): channel_data[c]['max_intensity'], 'min_ch' + str(count): channel_data[c]['min_intensity'], 'mean_ch' + str(count): channel_data[c]['mean_intensity'], 'extent_ch' + str(count): channel_data[c]['extent'], 'eccentricity_ch' + str(count): channel_data[c]['eccentricity'], 'perimeter_ch' + str(count): channel_data[c]['perimeter'], 'major_axis_ch' + str(count): channel_data[c]['major_axis_length'], 'minor_axis_ch' + str(count): channel_data[c]['minor_axis_length'] }, ignore_index=True) img_df['log_area_ch' + str(count)] = img_df['log_area_ch' + str(count)].replace(0, 0.01) else: img_df.loc[img_df.index[c], 'area_ch' + str(count)] = channel_data[c]['area'] img_df.loc[img_df.index[c], 'log_area_ch' + str(count)] = np.log10(channel_data[c]['area']) img_df.loc[img_df.index[c], 'max_ch' + str(count)] = channel_data[c]['max_intensity'] img_df.loc[img_df.index[c], 'min_ch' + str(count)] = channel_data[c]['min_intensity'] img_df.loc[img_df.index[c], 'mean_ch' + str(count)] = channel_data[c]['mean_intensity'] img_df.loc[img_df.index[c], 'extent_ch' + str(count)] = channel_data[c]['extent'] img_df.loc[img_df.index[c], 'eccentricity_ch' + str(count)] = channel_data[c]['eccentricity'] img_df.loc[img_df.index[c], 'perimeter_ch' + str(count)] = channel_data[c]['perimeter'] img_df.loc[ img_df.index[c], 'major_axis_ch' + str(count)] = channel_data[c]['major_axis_length'] img_df.loc[ img_df.index[c], 'minor_axis_ch' + str(count)] = channel_data[c]['minor_axis_length'] img_df['log_area_ch' + str(count)] = img_df['log_area_ch' + str(count)].replace(0, 0.01) ### new -- for channel-specific detailed regionprop data to add to img_df if str(count) in channel_list: if np.logical_and(count < n_chan, len(np.shape(img)) > 2): cleaned_channel = img[:, :, count] / bg cleaned_channel = filters.gaussian(cleaned_channel, sigma=2) ch_otsu = filters.threshold_otsu(cleaned_channel) ch_feat_mask = morphology.binary_erosion( cleaned_channel > ch_otsu) ch_feat_mask = morphology.remove_small_objects( ch_feat_mask, 2) cell_ch_labels = measure.label( (labeled_cells == c) * ch_feat_mask) cell_ch_props = measure.regionprops( cell_ch_labels, img[:, :, count]) ch_feat_areas = np.array( [r.area for r in cell_ch_props]) ch_feat_means = np.array( [r.mean_intensity for r in cell_ch_props]) ch_feat_maxes = np.array( [r.max_intensity for r in cell_ch_props]) ch_feat_mins = np.array( [r.min_intensity for r in cell_ch_props]) img_df.loc[img_df.index[c], 'num_features_ch' + str(count)] = len(cell_ch_props) if len(cell_ch_props) > 0: img_df.loc[img_df.index[c], 'log_num_features_ch' + str(count)] = np.log10( len(cell_ch_props)) else: img_df.loc[img_df.index[c], 'log_num_features_ch' + str(count)] = 0.01 img_df.loc[img_df.index[c], 'avg_feature_area_ch' + str(count)] = np.mean(ch_feat_areas) img_df.loc[img_df.index[c], 'log_avg_feature_area_ch' + str(count)] = np.log10( np.mean(ch_feat_areas)) img_df.loc[img_df.index[c], 'median_feature_area_ch' + str(count)] = np.median(ch_feat_areas) img_df.loc[img_df.index[c], 'avg_feature_int_ch' + str(count)] = np.mean(ch_feat_means) img_df.loc[img_df.index[c], 'avg_feature_max_ch' + str(count)] = np.mean(ch_feat_maxes) img_df.loc[img_df.index[c], 'avg_feature_min_ch' + str(count)] = np.mean(ch_feat_mins) img_df.loc[img_df.index[c], 'feature_coverage_%_ch' + str(count)] = np.sum( ch_feat_mask * (labeled_cells == c)) / np.sum( labeled_cells == c) img_df.fillna(0, inplace=True) try: c except: print('no cells detected') else: if count == len(cell_props.keys()) - 1: pct_done = 100.00 print('img ' + str(pct_done) + '% complete ' + '(channel ' + str(count + 1) + ' of ' + str(len(cell_props.keys())) + ', cell ' + str(c + 1) + ' of ' + str(len(channel_data)) + ')') if np.logical_and(count < n_chan, len(np.shape(img)) > 2): if str(count) in channel_list: img_df['log_avg_feature_area_ch' + str(count)] = img_df['log_avg_feature_area_ch' + str(count)].replace( 0, 0.01) img_df['log_num_features_ch' + str(count)] = img_df['log_num_features_ch' + str(count)].replace( 0, 0.01) results_df = pd.concat([results_df, img_df]) results_df.fillna(0, inplace=True) results_df.to_csv(save_path + '/' + '_cell_datasheet.csv') return results_df, save_path, n_chan
def pixelwise_transform(mask, dilation_radius=None, data_format=None, separate_edge_classes=False): """Transforms a label mask for a z stack edge, interior, and background Args: mask (tensor): tensor of labels dilation_radius (int): width to enlarge the edge feature of each instance data_format (str): 'channels_first' or 'channels_last' separate_edge_classes (bool): Whether to separate the cell edge class into 2 distinct cell-cell edge and cell-background edge classes. Returns: numpy.array: one-hot encoded tensor of masks: if not separate_edge_classes: [cell_edge, cell_interior, background] otherwise: [bg_cell_edge, cell_cell_edge, cell_interior, background] """ if data_format is None: data_format = K.image_data_format() if data_format == 'channels_first': channel_axis = 0 else: channel_axis = -1 # Detect the edges and interiors new_mask = np.zeros(mask.shape) strel = ball(1) if mask.ndim > 2 else disk(1) for cell_label in np.unique(mask): if cell_label != 0: # get the cell interior img = mask == cell_label img = binary_erosion(img, strel) new_mask += img interior = np.multiply(new_mask, mask) edge = (mask - interior > 0).astype('int') interior = (interior > 0).astype('int') if not separate_edge_classes: if dilation_radius: dil_strel = ball(dilation_radius) if mask.ndim > 2 else disk(dilation_radius) # Thicken cell edges to be more pronounced edge = binary_dilation(edge, selem=dil_strel) # Thin the augmented edges by subtracting the interior features. edge = (edge - interior > 0).astype('int') background = (1 - edge - interior > 0) background = background.astype('int') all_stacks = [ edge, interior, background ] return np.stack(all_stacks, axis=channel_axis) # dilate the background masks and subtract from all edges for background-edges background = (mask == 0).astype('int') dilated_background = binary_dilation(background, strel) background_edge = (edge - dilated_background > 0).astype('int') # edges that are not background-edges are interior-edges interior_edge = (edge - background_edge > 0).astype('int') if dilation_radius: dil_strel = ball(dilation_radius) if mask.ndim > 2 else disk(dilation_radius) # Thicken cell edges to be more pronounced interior_edge = binary_dilation(interior_edge, selem=dil_strel) background_edge = binary_dilation(background_edge, selem=dil_strel) # Thin the augmented edges by subtracting the interior features. interior_edge = (interior_edge - interior > 0).astype('int') background_edge = (background_edge - interior > 0).astype('int') background = (1 - background_edge - interior_edge - interior > 0) background = background.astype('int') all_stacks = [ background_edge, interior_edge, interior, background ] return np.stack(all_stacks, axis=channel_axis)
import numpy as np import matplotlib.pyplot as plt import imageio import libreria as lib from skimage.color import rgb2lab from skimage.morphology import binary_closing, binary_erosion from os import scandir, getcwd from os.path import abspath def ls(ruta=getcwd()): return [arch.name for arch in scandir(ruta) if arch.is_file()] cad = 'C:/Users/nineil/Desktop/Jeffri/USP/Procesamiento de Imagenes/Proyecto_PI/DataSegmentada/Opcional/plagaT/' A = ls(cad) for i in A: print(i) C = cad + i I = imageio.imread(C) imglab = rgb2lab(I) # Conversão de RGB a lab imglab = (imglab + [0, 128, 128]) / [100, 255, 255] # Normalizaçã0 imglab = imglab[:, :, 1] # Canal a* mask = binary_erosion(binary_closing(imglab > 0.49, np.ones( (3, 3)))) # operaçiões morfologicas R = lib.segmenta(I, mask) D = 'C:/Users/nineil/Desktop/Jeffri/USP/Procesamiento de Imagenes/Proyecto_PI/DataSegmentada/Experimento/T/' + i imageio.imwrite(D, R)
#####background normalization mode = stats.mode(norobot, axis=None)[0][0] for l in range(data_train.shape[1]): for j in range(data_train.shape[2]): norobot[l, j] = min(1., norobot[l, j] / mode) ##invert the image, we will need this image for the classification norobot_inv = util.invert(norobot) #####Remove dark bg and line in the middle and find regions #Threshold norobot_line = norobot[:] > 0.8 #Dilate the dark regions (i.e. erode the image) norobot_line = morphology.binary_erosion(norobot_line, morphology.square(10)) norobot_bin = norobot[:] > 0.8 #Find regions labels_line = measure.label(util.invert(norobot_line)) regions_line = measure.regionprops(labels_line) #Remove the biggest areas, i.e. line, borders labels_toremove = [] for i, region in enumerate(regions_line): if (region.area > 2000): labels_toremove.append(i + 1) for lab in labels_toremove: for lin in range(len(labels_line)): for col in range(len(labels_line[lin])): if (labels_line[lin, col] == lab):
def save_img(org_img, mask_path, data_save_path, img_name, prob_map, err_coord, crop_coord, DiscROI_size, org_img_size, threshold=0.5, pt=False): path = os.path.join(data_save_path, img_name) path0 = os.path.join(data_save_path+'/visulization/', img_name.split('.')[0]+'.png') if not os.path.exists(os.path.dirname(path0)): os.makedirs(os.path.dirname(path0)) disc_map = resize(prob_map[:, :, 0], (DiscROI_size, DiscROI_size)) cup_map = resize(prob_map[:, :, 1], (DiscROI_size, DiscROI_size)) if pt: disc_map = cv2.linearPolar(rotate(disc_map, 90), (DiscROI_size/2, DiscROI_size/2), DiscROI_size/2, cv2.WARP_FILL_OUTLIERS + cv2.WARP_INVERSE_MAP) cup_map = cv2.linearPolar(rotate(cup_map, 90), (DiscROI_size/2, DiscROI_size/2), DiscROI_size/2, cv2.WARP_FILL_OUTLIERS + cv2.WARP_INVERSE_MAP) mask_path = os.path.join(mask_path, img_name.split('.')[0]+'.bmp') if os.path.exists(mask_path): fig, (ax1,ax2,ax3, ax4) = plt.subplots(nrows=1, ncols=4) # create figure & 1 axis else: fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3) # ax0, ax1, ax2 = axes.ravel() ax1.imshow(org_img) ax2.imshow(org_img) ax3.imshow(org_img) ax1.set_xticks([]) ax1.set_yticks([]) ax1.set_title('initial image', fontsize=4, color='b') # plt.figure(dpi=600) #import pdb;pdb.set_trace() disc_mask = (disc_map > threshold) # return binary mask cup_mask = (cup_map > threshold) disc_mask = disc_mask.astype(np.uint8) cup_mask = cup_mask.astype(np.uint8) contours_disc = measure.find_contours(disc_mask, 0.5) contours_cup = measure.find_contours(cup_mask, 0.5) for n, contour in enumerate(contours_disc): ax2.plot(contour[:, 1] + crop_coord[2] - err_coord[2], contour[:, 0] + crop_coord[0] - err_coord[0], 'b', linewidth=0.2) for n, contour in enumerate(contours_cup): ax2.plot(contour[:, 1] + crop_coord[2] - err_coord[2], contour[:, 0] + crop_coord[0] - err_coord[0], 'g', linewidth=0.2) for i in range(5): disc_mask = scipy.signal.medfilt2d(disc_mask, 7) cup_mask = scipy.signal.medfilt2d(cup_mask, 7) disc_mask = morphology.binary_erosion(disc_mask, morphology.diamond(7)).astype(np.uint8) # return 0,1 cup_mask = morphology.binary_erosion(cup_mask, morphology.diamond(7)).astype(np.uint8) # return 0,1 disc_mask = get_largest_fillhole(disc_mask) cup_mask = get_largest_fillhole(cup_mask) disc_mask = morphology.binary_dilation(disc_mask, morphology.diamond(7)).astype(np.uint8) # return 0,1 cup_mask = morphology.binary_dilation(cup_mask, morphology.diamond(7)).astype(np.uint8) # return 0,1 disc_mask = get_largest_fillhole(disc_mask).astype(np.uint8) # return 0,1 cup_mask = get_largest_fillhole(cup_mask).astype(np.uint8) ROI_result = disc_mask + cup_mask ROI_result[ROI_result < 1] = 255 ROI_result[ROI_result < 2] = 128 ROI_result[ROI_result < 3] = 0 Img_result = np.zeros((org_img_size[0], org_img_size[1], 3), dtype=int) + 255 Img_result[crop_coord[0]:crop_coord[1], crop_coord[2]:crop_coord[3], 0] = ROI_result[err_coord[0]:err_coord[1], err_coord[2]:err_coord[3]] # for submit cv2.imwrite(path, Img_result[:, :, 0]) contours_disc = measure.find_contours(disc_mask, 0.5) contours_cup = measure.find_contours(cup_mask, 0.5) for n, contour in enumerate(contours_disc): ax3.plot(contour[:, 1] + crop_coord[2] - err_coord[2], contour[:, 0] + crop_coord[0] - err_coord[0], 'b', linewidth=0.2) for n, contour in enumerate(contours_cup): ax3.plot(contour[:, 1] + crop_coord[2] - err_coord[2], contour[:, 0] + crop_coord[0] - err_coord[0], 'g', linewidth=0.2) ax2.set_xticks([]) ax2.set_yticks([]) ax2.set_title('raw image', fontsize=4, color='b') ax3.set_xticks([]) ax3.set_yticks([]) ax3.set_title('smooth image', fontsize=4, color='b') if os.path.exists(mask_path): ax4.imshow(org_img) mask = np.asarray(image.load_img(mask_path)) disc_mask, cup_mask = transfer_mask2maps(mask) print('onon3') contours_disc = measure.find_contours(disc_mask, 0.5) contours_cup = measure.find_contours(cup_mask, 0.5) for n, contour in enumerate(contours_disc): ax4.plot(contour[:, 1], contour[:, 0], 'b', linewidth=0.2) for n, contour in enumerate(contours_cup): ax4.plot(contour[:, 1], contour[:, 0], 'g', linewidth=0.2) ax4.set_xticks([]) ax4.set_yticks([]) ax4.set_title('ground truth', fontsize=4, color='b') fig.savefig(path0, dpi=600, bbox_inches='tight') # save the figure to file plt.close(fig) else: fig.savefig(path0, dpi=600, bbox_inches='tight') # save the figure to file plt.close(fig)