def segment_cells(frame, mask=None): """ Compute the initial segmentation based on ridge detection + watershed. This works reasonably well, but is not robust enough to use by itself. """ blurred = filters.gaussian_filter(frame, 2) ridges = enhance_ridges(frame) # threshold ridge image thresh = filters.threshold_otsu(ridges) thresh_factor = 0.6 prominent_ridges = ridges > thresh_factor*thresh prominent_ridges = morphology.remove_small_objects(prominent_ridges, min_size=256) prominent_ridges = morphology.binary_closing(prominent_ridges) prominent_ridges = morphology.binary_dilation(prominent_ridges) # skeletonize ridge_skeleton = morphology.medial_axis(prominent_ridges) ridge_skeleton = morphology.binary_dilation(ridge_skeleton) ridge_skeleton *= mask ridge_skeleton -= mask # label cell_label_im = measure.label(ridge_skeleton) # morphological closing to fill in the cracks for cell_num in range(1, cell_label_im.max()+1): cell_mask = cell_label_im==cell_num cell_mask = morphology.binary_closing(cell_mask, disk(3)) cell_label_im[cell_mask] = cell_num return cell_label_im
def tissue_region_from_rgb(_img, _min_area=150, _g_th=None): """ TISSUE_REGION_FROM_RGB detects the region(s) of the image containing the tissue. The original image is supposed to represent a haematoxylin-eosin -stained pathology slide. The main purpose of this function is to detect the parts of a large image which most probably contain tissue material, and to discard the background. Usage: tissue_mask = tissue_from_rgb(img, _min_area=150, _g_th=None) Args: img (numpy.ndarray): the original image in RGB color space _min_area (int, default: 150): any object with an area smaller than the indicated value, will be discarded _g_th (int, default: None): the processing is done on the GREEN channel and all pixels below _g_th are considered candidates for "tissue pixels". If no value is given to _g_th, one is computed by K-Means clustering (K=2), and is returned. Returns: numpy.ndarray: a binary image containing the mask of the regions considered to represent tissue fragments int: threshold used for GREEN channel """ if _g_th is None: # Apply vector quantization to remove the "white" background - work in the # green channel: vq = MiniBatchKMeans(n_clusters=2) _g_th = int(np.round(0.95 * np.max(vq.fit(_G(_img).reshape((-1,1))) .cluster_centers_.squeeze()))) mask = _G(_img) < _g_th skm.binary_closing(mask, skm.disk(3), out=mask) mask = img_as_bool(mask) mask = skm.remove_small_objects(mask, min_size=_min_area, in_place=True) # Some hand-picked rules: # -at least 5% H and E # -at most 25% background # for a region to be considered tissue h, e, b = rgb2he2(_img) mask &= (h > np.percentile(h, 5)) | (e > np.percentile(e, 5)) mask &= (b < np.percentile(b, 50)) # at most at 50% of "other components" mask = mh.close_holes(mask) return img_as_bool(mask), _g_th
def closing3D(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_closing(data[i, :, :], selem) elif sliceId == 2: for i in range(data.shape[2]): data[:, :, i] = skimor.binary_closing(data[:, :, i], selem) else: data = scindimor.binary_closing(data, selem) return data
def segment_lung_mask(image, fill_lung_structures=True): LUNG_HU_VAL = -320 # not actually binary, but 1 and 2. # 0 is treated as background, which we do not want binary_image = np.array(image < LUNG_HU_VAL, dtype=np.int8) labels = measure.label(binary_image, connectivity=2) # Pick the pixel in the very corner to determine which label is air. # Improvement: Pick multiple background labels from around the patient # More resistant to "trays" on which the patient lays cutting the air # around the person in half background_label = labels[0, 0, 0] # Fill the air around the person binary_image[labels == background_label] = 0 # Method of filling the lung structures (that is superior to something like # morphological closing) if fill_lung_structures: l_max = largest_label_volume(labels, bg=0) if l_max is not None: # This slice contains some lung mask = np.zeros_like(binary_image) mask[labels == l_max] = 1 # Remove other air pockets insid of body mask = morphology.binary_closing(mask) return mask
def test9(self): fig, ax = plt.subplots() plt.imshow(self.mask) plt.show() shape = self.mask.shape for y in range(20, shape[0], 20): for x in range(20, shape[1], 20): if self.mask[y][x] == True: continue print(y, x) slice = self.prepareSliceForDot(y, x) lengthsArray = self.convertSliceDotsToLenths(y, x, slice) if self.calculateVariationForLengthsArray( lengthsArray) > self.VARIATION_LIMIT_1: continue derivativeArray = self.prepareDerivativeArray(lengthsArray) new_lengths_array, new_derivative_array = self.process_dot_border( y, x, slice, lengthsArray, derivativeArray) self.drawBorderInMask(y, x, new_lengths_array, slice) fig, ax = plt.subplots() plt.imshow(self.mask) plt.show() self.mask = binary_closing(self.mask, square(25)) self.mask = remove_small_objects(self.mask) fig, ax = plt.subplots() plt.imshow(self.mask) io.imsave('data/output/mask_with_borders_1.jpg', img_as_ubyte(self.mask)) plt.close('all')
def merge_and_save(label_file_name, expected_file_name): try: label_image = io.imread(label_file_name, as_grey=True) merged_image = label_image < 2.0/255.0 merged_image = binary_fill_holes(merged_image) selem = disk(7) for i in range(20): components, number_of_components = label(merged_image) if number_of_components < 2: break merged_image = binary_closing(merged_image, selem=selem) merged_image = binary_fill_holes(merged_image) if i > 10 : merged_image = remove_small_objects(merged_image, min_size=10) try: expected_image = io.imread(expected_file_name, as_grey=True) merged_image = merged_image | (expected_image != 0) except IOError: pass with warnings.catch_warnings(): warnings.simplefilter("ignore") io.imsave(expected_file_name, img_as_ubyte(merged_image)) except IOError: pass
def nucleiBinarySplit(mask, thr): mask00 = ndi.binary_fill_holes(mask) maskConv = convex_hull_image(mask00) maskB = tinyDottsRemove(maskConv - mask) notConv = np.sum(maskB) / np.sum(mask00) if (notConv < thr): return mask00 nn = np.max(label(maskB)) if nn > 1: while (np.max(label(maskB)) == nn): maskB = binary_closing(binary_dilation(maskB, selem=disk(1)), selem=disk(2)) pass maskC = binary_dilation(skeletonize(maskB), selem=disk(1)) maskD = tinyDottsRemove(binary_erosion( imgToMask(binary_dilation(maskConv, selem=disk(1)) + (-1) * maskC), selem=disk(1)), minimum=10) maskE = binary_opening(maskD, selem=disk(1)) #maskE = imgToMask(maskD - maskConv) #maskF = ndi.binary_fill_holes(maskE) markers = ndi.label(maskE)[0] markers[np.where(mask00 == 0)] = 0 labels = watershed(-mask, markers, mask=mask) return labels
def closing(gray_img, kernel=None): """Wrapper for scikit-image closing functions. Opening can remove small dark spots (i.e. pepper). Inputs: gray_img = input image (grayscale or binary) kernel = optional neighborhood, expressed as an array of 1s and 0s. If None, use cross-shaped structuring element. :param gray_img: ndarray :param kernel = ndarray :return filtered_img: ndarray """ params.device += 1 # Make sure the image is binary/grayscale if len(np.shape(gray_img)) != 2: fatal_error("Input image must be grayscale or binary") # If image is binary use the faster method if len(np.unique(gray_img)) == 2: bool_img = morphology.binary_closing(image=gray_img, selem=kernel) filtered_img = np.copy(bool_img.astype(np.uint8) * 255) # Otherwise use method appropriate for grayscale images else: filtered_img = morphology.closing(gray_img, kernel) if params.debug == 'print': print_image(filtered_img, os.path.join(params.debug_outdir, str(params.device) + '_opening' + '.png')) elif params.debug == 'plot': plot_image(filtered_img, cmap='gray') return filtered_img
def repair(self, mask): """Apply binary closure using selection elements specified in the class constructor. OR the results together. Parameters ---------- mask : ndarray 2D rejection mask for spectrograph images. Returns ------- repaired_mask : ndarray 2D spectrograph cosmic ray mask with binary closure applied. """ # Convert mask to binary. bmask = np.zeros(mask.shape, dtype=mask.dtype) bmask[mask > 0] = 1 # Apply binary closure using each selection element. OR results. bc = np.zeros(mask.shape, dtype=mask.dtype) for se in self.selems: bc = bc | binary_closing(bmask, selem=se.se) return bc
def compute_hull_mask(faces, vertices, scale=config.HULL_SCALE, remove_holes=True, closing=False): transformed = vertices.copy() transformed[:, 0] -= vertices[:, 0].min() transformed[:, 2] -= vertices[:, 2].min() transformed *= scale xmin = vertices[:, 0].min() zmin = vertices[:, 2].min() xmax = vertices[:, 0].max() zmax = vertices[:, 2].max() width = int( math.ceil(vertices[:, 0].max() - vertices[:, 0].min()) * scale) + 1 height = int( math.ceil(vertices[:, 2].max() - vertices[:, 2].min()) * scale) + 1 im = Image.new('L', (width, height)) draw = ImageDraw.Draw(im) for face in faces: p = [(int(transformed[i, 0]), int(transformed[i, 2])) for i in face] draw.polygon(p, fill='#fff') im = np.array(im) == 255 if closing: imsave(os.path.join(config.IMAGE_SAVE_DIR, 'test.png'), im) im = morphology.binary_closing(im, morphology.square(40)) imsave(os.path.join(config.IMAGE_SAVE_DIR, 'test2.png'), im) if remove_holes and len(np.unique(im) >= 2): im = morphology.remove_small_holes(im, min_size=scale**2) return im.T, xmin, zmin, xmax, zmax
def remove_noise_from_segmented_lungs(segmented_ct_scan): selem = ball(2) binary = binary_closing(segmented_ct_scan, selem) label_scan = label(binary) areas = [r.area for r in regionprops(label_scan)] areas.sort() for r in regionprops(label_scan): max_x, max_y, max_z = 0, 0, 0 min_x, min_y, min_z = 1000, 1000, 1000 for c in r.coords: max_z = max(c[0], max_z) max_y = max(c[1], max_y) max_x = max(c[2], max_x) min_z = min(c[0], min_z) min_y = min(c[1], min_y) min_x = min(c[2], min_x) if (min_z == max_z or min_y == max_y or min_x == max_x or r.area > areas[-3]): for c in r.coords: segmented_ct_scan[c[0], c[1], c[2]] = 0 else: index = (max((max_x - min_x), (max_y - min_y), (max_z - min_z))) / (min((max_x - min_x), (max_y - min_y) , (max_z - min_z)))
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 refine_aseg(aseg, ball_size=4): """ First step to reconcile ANTs' and FreeSurfer's brain masks. Here, the ``aseg.mgz`` mask from FreeSurfer is refined in two steps, using binary morphological operations: 1. With a binary closing operation the sulci are included into the mask. This results in a smoother brain mask that does not exclude deep, wide sulci. 2. Fill any holes (typically, there could be a hole next to the pineal gland and the corpora quadrigemina if the great cerebral brain is segmented out). """ # Read aseg data bmask = aseg.copy() bmask[bmask > 0] = 1 bmask = bmask.astype(np.uint8) # Morphological operations selem = sim.ball(ball_size) newmask = sim.binary_closing(bmask, selem) newmask = binary_fill_holes(newmask.astype(np.uint8), selem).astype(np.uint8) return newmask.astype(np.uint8)
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 compute_binary_mask_lasseck(spectrogram, threshold): # normalize to [0, 1) norm_spectrogram = normalize(spectrogram) # median clipping binary_image = median_clipping(norm_spectrogram, threshold) # closing binary image (dilation followed by erosion) binary_image = morphology.binary_closing(binary_image, selem=np.ones((4, 4))) # dialate binary image binary_image = morphology.binary_dilation(binary_image, selem=np.ones((4, 4))) # apply median filter binary_image = filters.median(binary_image, selem=np.ones((2, 2))) # remove small objects binary_image = morphology.remove_small_objects(binary_image, min_size=32, connectivity=1) mask = np.array([np.max(col) for col in binary_image.T]) mask = smooth_mask(mask) return mask
def extend_mask_2d(imagemask, disk_size=4, iterations=15): padding = disk_size * iterations mask = np.zeros(shape=np.array(imagemask.shape)+2*padding, dtype=bool) mask[padding:imagemask.shape[0]+padding, padding:imagemask.shape[1]+padding][imagemask==1] = 1 struct = disk(disk_size) mask = binary_closing(mask, structure=struct, iterations=iterations) return mask[padding:imagemask.shape[0]+padding, padding:imagemask.shape[1]+padding]
def morphological_transform(roi: DenseROI, shape: Tuple[int, int]) -> Union[DenseROI, None]: """performs a closing followed by an opening to clean up pixelated appearance of ROIs Parameters ---------- roi: DenseROI roi to transform shape: Tuple[int, int] The frame shape of the movie from which ROIs were extracted in order of: (height, width). Returns ------- roi: DenseROI transformed roi or None if empty after transform """ mask = full_mask_constructor(roi['mask_matrix'], roi['x'], roi['y'], shape) structuring_element = disk(radius=1) mask = binary_closing(mask, selem=structuring_element) mask = binary_opening(mask, selem=structuring_element) new_roi = roi_from_full_mask(roi, mask) return new_roi
def morphology(binarized): if morph_method == 'legacy': morph = binary_dilation(binarized, disk(1)) morph = binary_erosion(morph, disk(morph_disk)) elif morph_method == 'instamatic': morph = remove_small_objects(binarized, min_size=4 * 4, connectivity=0) # remove noise morph = binary_closing(morph, disk(morph_disk)) # dilation + erosion morph = binary_erosion(morph, disk(morph_disk)) # erosion if remove_carbon_lacing: morph = remove_small_objects(morph, min_size=8 * 8, connectivity=0) morph = remove_small_holes(morph, min_size=32 * 32, connectivity=0) morph = binary_dilation(morph, disk(morph_disk)) # dilation elif (morph_method is None) or (morph_method == 'none'): morph = binarized else: raise ValueError( 'Unknown morphology method {}.Choose legacy or instamatic.' .format(morph_method)) return morph
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 fill_raster_holes(self, array, thresh, ndval): """ Fills in holes and gaps in an array of 1s and NoData :param array: 2-D array of 1s and NoData :param thresh: hole size (cells) below which should be filled :param ndval: NoData value :return: 2-D array like input array but with holes filled """ binary = np.zeros_like(array, dtype=bool) for j in range(0, array.shape[0] - 1): for i in range(0, array.shape[1] - 1): if array[j, i] == 1: binary[j, i] = 1 b = mo.remove_small_holes(binary, thresh, 1) c = mo.binary_closing(b, selem=np.ones((7, 7))) d = mo.remove_small_holes(c, 500, 1) out_array = np.full(d.shape, ndval, dtype=np.float32) for j in range(0, d.shape[0] - 1): for i in range(0, d.shape[1] - 1): if d[j, i] is True: out_array[j, i] = 1. return out_array
def close(B): neiDia = 20 # neighborhood square side # expanding image C = [0] * (2 * neiDia + len(B[0])) C = [C] * (2 * neiDia + len(B)) C = np.array(C) C[neiDia:-neiDia, neiDia:-neiDia] = B[:, :] # creating a 2d array of ones ones = [1] * neiDia ones = [ones] * neiDia C = binary_closing(C, ones) # returning to original size C = C[neiDia:-neiDia, neiDia:-neiDia] if showProcess: viewer = ImageViewer(C) viewer.show() if writeProcessImages: folder = str(runParameters.stepNumber) + "_closing"; if not os.path.exists(folder): os.makedirs(folder) io.imsave(folder + "/" + str(imageNumber) + ".png", C*255) runParameters.stepNumber += 1 return C
def morp(arr, selema=diamond(8), selemb=diamond(4)): """Apply the morphology transformation over the image array.""" # res = morphology.binary_(arr, selem=selema) # res = morphology.binary_opening(arr, selem=selema) res = morphology.binary_dilation(arr, selem=selemb) res = morphology.binary_closing(res, selem=selema) return res
def binaryPostProcessing(BinaryImage, removeArea): BinaryImage[BinaryImage > 0] = 1 ###9s # Img_BW = pymorph.binary(BinaryImage) # Img_BW = pymorph.areaopen(Img_BW, removeArea) # Img_BW = pymorph.areaclose(Img_BW, 50) # Img_BW = np.uint8(Img_BW) ###2.5 s # Img_BW = np.uint8(BinaryImage) # Img_BW = ITK_LabelImage(Img_BW, removeArea) # Img_BW[Img_BW >0] = 1 Img_BW = BinaryImage.copy() BinaryImage_Label = measure.label(Img_BW) for i, region in enumerate(measure.regionprops(BinaryImage_Label)): if region.area < removeArea: Img_BW[BinaryImage_Label == i + 1] = 0 else: pass Img_BW = morphology.binary_closing(Img_BW, morphology.disk(3)) Img_BW = remove_small_holes(Img_BW, 50) Img_BW = np.uint8(Img_BW) return Img_BW
def segm_2d(image, spacing=1.0): """This funtion segments the lungs from the given 2D slice.""" # Step 1: Convert into a binary image. binary = image < -400 # Step 2: Remove the blobs connected to the border of the image. cleared = segmentation.clear_border(binary) # Step 3: Label the image. label_image = measure.label(cleared) # Step 4: Keep the labels with 2 largest areas. areas = [r.area for r in measure.regionprops(label_image)] areas.sort() if len(areas) > 2: for region in measure.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 # seperating the lung nodules attached to the blood vessels. selem = morphology.disk(2.0 / spacing) binary = morphology.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 = morphology.disk(10.0 / spacing) binary = morphology.binary_closing(binary, selem) # Step 7: Fill in the small holes inside the binary mask of lungs. edges = filters.roberts(binary) binary = ndimage.binary_fill_holes(edges) return binary
def get_compactness(self, labels): nlabels = labels.max() + 1 # nlabels = len(np.unique(labels)) - 1 eccs = np.zeros(nlabels) for lab in range(nlabels): obj = labels == lab if labels.ndim == 2: strel = np.ones((3, 3), dtype=np.bool) obj_c = skimor.binary_closing(obj, strel) if obj_c.sum() >= obj.sum(): obj = obj_c else: strel = np.ones((3, 3, 3), dtype=np.bool) obj_c = tools.closing3D(obj, strel) if obj_c.sum() >= obj.sum(): obj = obj_c if labels.ndim == 2: ecc = skimea.regionprops(obj)[0]['eccentricity'] else: ecc = tools.get_zunics_compatness(obj) # if np.isnan(ecc): # ecc = 0 eccs[lab] = ecc return eccs
def getSegmentFeatures(segment): side = segment.shape[0] segment[0, 0] = 0 smooth_seg = binary_fill_holes(segment) smooth_seg = binary_closing(smooth_seg, disk(side // 60)) dist_map = distance_transform_edt(smooth_seg) skel = skeletonize(smooth_seg) sG = skelgraph.SkelGraph(skel) sG.trim(side // 12) skel = sG.mask num_endpoints = sG.get_num_endpoints() length = skel.sum() width_map = skel * dist_map mean_width = width_map.sum() / length std_width = (((width_map)**2).sum() / length - mean_width**2)**0.5 elongation = length * length / segment.sum() features = [ mean_width / side, std_width / side, elongation / side, num_endpoints ] return features
def download(name_file): img = imread(name_file) img_gray = rgb2gray(img) binary_img = binary_closing(canny(img_gray, sigma=2), selem=np.ones((6, 6))) # 1.5;2 img_segment = binary_fill_holes(binary_img) mask_img = binary_opening(img_segment, selem=np.ones((40, 40))) # 16;25 plt.imshow(img) # plt.imshow(label2rgb(mask_img, image=img_gray)) # Поиск контуров contours_img = find_contours(mask_img, level=0.8) # Отображение (слишком громоздко при запуске на всем датасете, поэтому закомментировано) # fig, ax = plt.subplots() # ax.imshow(mask_img, cmap=plt.cm.gray) # for contour in contours_img: # ax.plot(contour[:, 1], contour[:, 0], linewidth=2) plt.show() return contours_img, mask_img
def get_segmented_lungs(im): # Convert into a binary image. binary = im < 604 # Remove the blobs connected to the border of the image cleared = clear_border(binary) # Label the image label_image = label(cleared) # 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 # Closure operation with disk of radius 12 selem = disk(2) binary = binary_erosion(binary, selem) selem = disk(10) binary = binary_closing(binary, selem) # Fill in the small holes inside the lungs edges = roberts(binary) binary = ndi.binary_fill_holes(edges) # Superimpose the mask on the input image get_high_vals = binary == 0 im[get_high_vals] = 0 return im
def clean_mask_v2(m, c): # threshold m_b = m > threshold_otsu(m) c_b = c > threshold_otsu(c) # combine contours and masks and fill the cells m_ = np.where(m_b | c_b, 1, 0) m_ = ndi.binary_fill_holes(m_) # close what wasn't closed before area, radius = mean_blob_size(m_b) struct_size = int(1.25 * radius) struct_el = morph.disk(struct_size) m_padded = pad_mask(m_, pad=struct_size) m_padded = morph.binary_closing(m_padded, selem=struct_el) m_ = crop_mask(m_padded, crop=struct_size) # open to cut the real cells from the artifacts area, radius = mean_blob_size(m_b) struct_size = int(0.75 * radius) struct_el = morph.disk(struct_size) m_ = np.where(c_b & (~m_b), 0, m_) m_padded = pad_mask(m_, pad=struct_size) m_padded = morph.binary_opening(m_padded, selem=struct_el) m_ = crop_mask(m_padded, crop=struct_size) # join the connected cells with what we had at the beginning m_ = np.where(m_b | m_, 1, 0) m_ = ndi.binary_fill_holes(m_) # drop all the cells that weren't present at least in 25% of area in the initial mask m_ = drop_artifacts(m_, m_b, min_coverage=0.25) return m_
def calculate_oct_roi_mask(img, tresh=1e-10): """ Calculate the interesting region MASK of the image using entropy :param img: :param tresh: entropy cutoff threshold :return: mask of the interesting region (MASK = 1 interesting) """ if img.ndim == 2: im_slice = skimage.img_as_float(img.astype(np.float32) / 128. - 1.) elif img.ndim == 3: im_slice = skimage.img_as_float(img[:, :, 1].astype(np.float32) / 128. - 1.) assert img.ndim in {2, 3} im_slice_ = entropy(im_slice, disk(11)) im_slice_ = im_slice_ / (np.max(im_slice_) + 1e-16) im_slice_ = np.asarray(im_slice_ > tresh, dtype=np.int8) selem = disk(35) im_slice_ = binary_closing(im_slice_, selem=selem) im_slice_ = convex_hull_image(im_slice_) plt.imshow(im_slice, cmap='gray') plt.imshow(im_slice_, cmap='jet', alpha=0.5) plt.pause(.1) return im_slice_
def fill_minor_holes(img, closing_kernel=disk(10), dilation_kernel=disk(10)): """ Run simple heuristic to fill small holes in tissue. It's 3 morphological operation applied in order: 1. binary_closing: used to connect tissue edges 2. binary dilation: makes tissue edges bolder (holes smaller) 3. binary_fill_holes: fill in small holes In effect this algorithm identifies a "tissue convex hull". Parameters ---------- img : an binary image as a numpy array closing_kernel : image kernel used for closing dilation_kernel : image kernel used for dilation Returns ------- numpy.ndarray : transformed binary image of the same size """ img = binary_closing(img, closing_kernel) # connects edges img = binary_dilation(img, dilation_kernel) # make tissue bolder img = binary_fill_holes(img) # fills in holes return img
def tissue_mask_generation(img_rgb, rgb_min=50): """ This function is used to generate tissue masks works for patches too i guess input : image : type : numpy.array : BGR format usually ex i """ img_rgb = np.array(img_rgb) background_r = img_rgb[:, :, 0] > threshold_otsu(img_rgb[:, :, 0]) background_g = img_rgb[:, :, 1] > threshold_otsu(img_rgb[:, :, 1]) background_b = img_rgb[:, :, 2] > threshold_otsu(img_rgb[:, :, 2]) tissue_rgb = np.logical_not(background_r & background_g & background_b) del background_b, background_g, background_r min_r = img_rgb[:, :, 0] > rgb_min min_g = img_rgb[:, :, 1] > rgb_min min_b = img_rgb[:, :, 2] > rgb_min tissue_mask = tissue_rgb & min_r & min_g & min_b del min_r, min_g, min_b close_kernel = np.ones((7, 7), dtype=np.uint8) image_close = binary_closing(np.array(tissue_mask), close_kernel) tissue_mask = binary_fill_holes(image_close) del image_close, close_kernel #Apply median filter tissue_mask = median(tissue_mask, disk(7)) tissue_mask = np.array(tissue_mask).astype(np.uint8) tissue_mask = tissue_mask > 0 return tissue_mask
def count_ships(path, seg, date_mask): struct = disk(2) seg = binary_closing(seg, struct).astype(np.bool) im = imread(path) im = rgba2rgb(im) grayscale = rgb2gray(im) thresh = threshold_yen(grayscale) yen = grayscale > thresh eroded = binary_erosion(seg, struct).astype(np.bool) grayscale = grayscale > 0.6 grayscale[(eroded == 0) | (date_mask == 1) | (yen == 0)] = 0 grayscale[date_mask == 1] = 0 grayscale = binary_fill_holes(grayscale) grayscale = clear_border(grayscale) l = label(grayscale) for region in regionprops(l): if region.area > 100 or region.extent < 0.2: grayscale = flood_fill(grayscale, tuple(region.coords[0, :]), 0) label_image, num = label(grayscale, return_num=True) return num, grayscale
def label_particles_edge(im, sigma=2, closing_size=0, **extra_args): """ Segment image using Canny edge-finding filter. parameters ---------- im : image in which to find particles sigma : size of the Canny filter closing_size : size of the closing filter returns ------- labels : an image array of uniquely labeled segments """ from skimage.morphology import square, binary_closing, skeletonize if skimage_version < StrictVersion('0.11'): from skimage.filter import canny else: from skimage.filters import canny edges = canny(im, sigma=sigma) if closing_size > 0: edges = binary_closing(edges, square(closing_size)) edges = skeletonize(edges) labels = sklabel(edges) print "found {} segments".format(labels.max()) # in ma.array mask, False is True, and vice versa labels = np.ma.array(labels, mask=edges == 0) return labels
def needles2tips(needles, mri, number_of_slices=3): """ This function accepts a list of volumes (each volumes containing a needle) and returns a single volume containing just the tips. Here there are a plenty of attempts of removing untrusted data. """ tips = np.zeros_like(mri).astype(np.int32) #print(tips.shape) for needle in needles: needle = needle.astype(np.int32) #print("MIN %f, MAX %f" % (needle.min(), needle.max())) if np.sum(needle) < (np.shape(needle)[0] * np.shape(needle)[1] * np.shape(needle)[2]): #print("Valid needle") needle = binary_closing(needle, selem=np.ones((3,3,3))) needle[needle!=0]=1 #print(" after closing: MIN %f, MAX %f " % (needle.min(), needle.max())) for z in range(np.shape(mri)[0]-1, 0, -1): if 200 > np.sum(needle[z,:,:]) > 0.5 and z-number_of_slices-1 >= 0: #print(" valid slice %d" % z) tmp = deepcopy(needle) tmp[:z-number_of_slices-1,:,:] = 0 tips[tmp!=0] = 1 del(tmp) break tips[tips!=0]=1 return tips.astype(np.int32)
def segment_roi(roi): # step 1. phase congruency (edge detection) Mm = phasecong_Mm(roi) # step 2. hysteresis thresholding (of edges) B = hysthresh(Mm,HT_T1,HT_T2) # step 3. trim pixels off border B[B[:,1]==0,0]=0 B[B[:,-2]==0,-1]=0 B[0,B[1,:]==0]=0 B[-1,B[-2,:]==0]=0 # step 4. threshold to find dark areas dark = dark_threshold(roi, DARK_THRESHOLD_ADJUSTMENT) # step 5. add dark areas back to blob B = B | dark # step 6. binary closing B = binary_closing(B,SE3) # step 7. binary dilation B = binary_dilation(B,SE2) # step 8. thinning B = bwmorph_thin(B,3) # step 9. fill holes B = binary_fill_holes(B) # step 10. remove blobs smaller than BLOB_MIN B = remove_small_objects(B,BLOB_MIN,connectivity=2) # done. return B
def fill_gaps(image, closing_radius=0, min_hole_size=0, median_radius=0.6): """ This function closes small gaps between and within objects and smooths edges. It is a 'finishing' step before skeletonization, and improves the quality of the skeleton by removing gaps and minimizing bumps. It also enables removing close, parallel objects such as appear under the microscope as a single, long, clear object with sharp, parallel edges. These spurrious objects would otherwise pass earlier filters but are, in fact, spurrious. The function itself is a wrapper for `skimage.morphology.binary_closing`, `skimage.morphology.remove_small_holes`, and `skimage.filters.median` on a binary image. Parameters ---------- image : ndarray Binary image of candidate objects closing_radius : ndarray Binary structure to perform binary closing. Defaults to 0 (skips). min_hole_size : int Holes with areas smaller than this (in pixels) are removed. Defaults to 0 (skips). median_radius : ndarray Binary structure to use for a median filter. Defaults at 0.6, giving square connectivity of 1 (manhattan = 1). 0 to skip. Returns ------- ndarray : Binary image of candidate objects. """ closing_structure = _disk(closing_radius) median_structure = _disk(median_radius) out = morphology.binary_closing(image, closing_structure) out = morphology.remove_small_holes(out, min_size=min_hole_size) out = filters.median(out, selem=median_structure) return(out)
def main(): # read image input_path, output_path = _get_args() input_img = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE) img = _img2bin(input_img) # text processing phase img = _preprocess(img) img = binary_closing(img, selem=cfg.POS_CLOSING_SELEM) stats = _connected_components(img) ratios = _calc_ratios(img, stats) blobs_img = _draw(_bin2img(img), stats, ratios=ratios) cv2.imwrite(os.path.join(output_path, 'blobs_img.png'), blobs_img) text_stats = _apply_thr(stats, ratios) text_blobs_img = _draw(input_img, text_stats) cv2.imwrite(os.path.join(output_path, 'text_blobs_img.png'), text_blobs_img) # segmentating words words = _process_words(_img2bin(input_img)) cv2.imwrite(os.path.join(output_path, 'words_img.png'), _bin2img(words)) words_stats = _connected_components(words) text_mask = _stats2mask(text_stats, img.shape) words_mask = _stats2mask(words_stats, img.shape) & text_mask words_stats = _connected_components(words_mask) words_blobs_img = _draw(input_img, words_stats) cv2.imwrite(os.path.join(output_path, 'words_blobs_img.png'), words_blobs_img) print('number of lines: %d' % len(text_stats)) print('number of words: %d' % len(words_stats))
def image_filter(img): img2 = img.copy(); img2[img2 < 30] = 100; img2 = exp.smooth_image(img2, sigma = 1.0); #plt.figure(6); plt.clf(); #plt.imshow(img2); # threshold image and take zero smaller components.. th = img2 < 92; th2 = morph.binary_closing(th, morph.diamond(1)) label = meas.label(th2, background=0) #plt.imshow(mask) bs = meas.regionprops(label+1); area = np.array([prop.area for prop in bs]); if len(area) > 0: mask = np.logical_and(label > -1, label != np.argsort(area)[-1]); img2[mask] = 100; img2[:2,:] = 100; img2[-2:,:] = 100; img2[:,:2] = 100; img2[:,-2:] = 100; #plt.figure(6); plt.clf(); #plt.subplot(1,2,1); #plt.imshow(img2, vmin = 84, vmax = 92, cmap = plt.cm.gray) #plt.subplot(1,2,2); #plt.imshow(img2); return img2;
def segment_watershed(seg, centers, post_morph=False): """ perform watershed segmentation on input imsegm and optionally run some postprocessing using morphological operations :param ndarray seg: input image / segmentation :param [[int, int]] centers: position of centres / seeds :param bool post_morph: apply morphological postprocessing :return ndarray, [[int, int]]: resulting segmentation, updated centres """ logging.debug('segment: watershed...') seg_binary = (seg > 0) seg_binary = ndimage.morphology.binary_fill_holes(seg_binary) # thr_area = int(0.05 * np.sum(seg_binary)) # seg_binary = morphology.remove_small_holes(seg_binary, min_size=thr_area) distance = ndimage.distance_transform_edt(seg_binary) markers = np.zeros_like(seg) for i, pos in enumerate(centers): markers[int(pos[0]), int(pos[1])] = i + 1 segm = morphology.watershed(-distance, markers, mask=seg_binary) # if morphological postprocessing was not selected, ends here if not post_morph: return segm, centers, None segm_clean = np.zeros_like(segm) for lb in range(1, np.max(segm) + 1): seg_lb = (segm == lb) # some morphology operartion for cleaning seg_lb = morphology.binary_closing(seg_lb, selem=morphology.disk(5)) seg_lb = ndimage.morphology.binary_fill_holes(seg_lb) # thr_area = int(0.15 * np.sum(seg_lb)) # seg_lb = morphology.remove_small_holes(seg_lb, min_size=thr_area) seg_lb = morphology.binary_opening(seg_lb, selem=morphology.disk(15)) segm_clean[seg_lb] = lb return segm_clean, centers, None
def otsu(difference, closing=True): thresh = threshold_otsu(difference) print(f'Otsu threshold: {thresh}') result = difference > thresh if closing: result = morphology.binary_closing(result, np.ones((5, 5))) return result
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_segmented_lungs(im, plot=False): cleared = clear_border(im) label_image = measure.label(cleared) areas = [r.area for r in measure.regionprops(label_image)] areas.sort() #print areas if len(areas) > 2: for region in measure.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 = morphology.disk(2) binary = morphology.binary_erosion(binary, selem) selem = morphology.disk(15) binary = morphology.binary_closing(binary, selem) edges = filters.roberts(binary) binary = binary_fill_holes(edges) get_high_vals = binary == 0 im[get_high_vals] = 0 return im
def mask_numpy_array(channel1, channel2, thresh_o = 20): channel2_Otsu = threshold_otsu(channel2) channel2_thresh = channel2 > ((channel2_Otsu*thresh_o)/100) channel2_thresh = binary_closing(channel2_thresh, square(5)) channel1_channel2_masked = ma.masked_array(channel1, mask=~channel2_thresh) channel1_channel2 = channel1_channel2_masked.filled(0) return channel1_channel2, channel2_thresh
def get_rois(im_array, markers): """Return the regions of interest.""" salem = disk(3) im = get_thresholded_image(im_array) im = remove_small_objects(im, min_size=50) im = binary_closing(im, salem) im = watershed(-im_array, markers, mask=im) return im
def outlineSmoothing(image, radius=1): """Smooth outlines of foreground object using morphological operations.""" struct = median(disk(radius), disk(1)) label_image = binary_closing(image, struct) label_image = binary_opening(label_image, struct) return label_image.astype(image.dtype)
def ProcessImage(im, targetDim = 250, doDenoiseOpening = True): #Resize to specified pixels max edge size scaling = 1. if im.shape[0] > im.shape[1]: if im.shape[0] != targetDim: scaling = float(targetDim) / im.shape[0] im = misc.imresize(im, (targetDim, int(round(im.shape[1] * scaling)))) else: if im.shape[1] != targetDim: scaling = float(targetDim) / im.shape[1] im = misc.imresize(im, (int(round(im.shape[0] * scaling)), targetDim)) #print "scaling", scaling greyim = 0.2126 * im[:,:,0] + 0.7152 * im[:,:,1] + 0.0722 * im[:,:,2] #Highlight number plate imnorm = np.array(greyim, dtype=np.uint8) se = np.ones((3, 30), dtype=np.uint8) opim = morph.opening(imnorm, se) diff = greyim - opim + 128. misc.imsave("diff.png", diff) #Binarize image vals = diff.copy() vals = vals.reshape((vals.size)) meanVal = vals.mean() stdVal = vals.std() threshold = meanVal + stdVal #print "Threshold", threshold binIm = diff > threshold misc.imsave("threshold.png", binIm) #print vals.shape #plt.plot(vals) #plt.show() #Denoise diamond = morph.diamond(2) if doDenoiseOpening: currentIm = morph.binary_opening(binIm, diamond) else: currentIm = binIm denoiseIm2 = morph.binary_closing(currentIm, np.ones((3, 13))) #print "currentIm", currentIm.min(), currentIm.max(), currentIm.mean() #print "denoiseIm2", denoiseIm2.min(), denoiseIm2.max(), currentIm.mean() #misc.imsave("denoised1.png", currentIm * 255) #misc.imsave("denoised2.png", denoiseIm2 * 255) #Number candidate regions #print "Numbering regions" numberedRegions, maxRegionNum = morph.label(denoiseIm2, 4, 0, return_num = True) return numberedRegions, scaling
def rotate_blob(blob, theta): """rotate a blob and smooth out rotation artifacts""" blob = rotate(blob,-1*theta,resize=True) blob = binary_closing(blob,SE3) blob = binary_dilation(blob,SE2) # note that H Sosik's version does one iteration # of thinning but 3 is closer to area-preserving blob = bwmorph_thin(blob,3) return blob
def close_holes(image, salem=None, name='close_holes'): if salem is None: salem = disk(3) closed = binary_closing(image.image_array, salem) ia = ImageArray(closed, name) ia.history = image.history + [name] return ia
def crop_by_saliency(saliency_map, closing_size=11, border=50): binary_image = threshold(saliency_map) selem = np.ones((closing_size, closing_size)) binary_image = binary_closing(binary_image, selem) labels = label(binary_image) roi = max(regionprops(labels), key=attrgetter('filled_area')) border = 50 return (slice(roi.bbox[0] - border, roi.bbox[2] + 2 * border), slice(roi.bbox[1] - border, roi.bbox[3] + 2 * border))
def morphological_clean_sp(image, segments, diameter=4): # remove small / thin segments by morphological closing + watershed # extract boundaries boundary = boundaries.find_boundaries(segments) closed = morphology.binary_closing(boundary, np.ones((diameter, diameter))) # extract regions labels = morphology.label(closed, neighbors=4, background=1) # watershed to get rid of boundaries # interestingly we can't use gPb here. It is to sharp. edge_image = sobel(rgb2gray(image)) result = morphology.watershed(edge_image, labels + 1) # we want them to start at zero! return result - 1
def extract_properties(image, closing_size=2): selem = morphology.disk(radius=closing_size) thresholded = image > filters.threshold_otsu(image) closed = morphology.binary_closing(thresholded, selem) regions = ndi.label(closed)[0] propnames = ['area', 'convex_area', 'eccentricity', 'euler_number', 'extent', 'min_intensity', 'mean_intensity', 'max_intensity', 'minor_axis_length', 'major_axis_length'] props = measure.regionprops(regions, image) data_table = [] for obj in props: data_point = [getattr(obj, p) for p in propnames] data_table.append(data_point) return propnames, np.array(data_table), props
def noise_removal(img, radius_1=1, radius_2=2, median_iterations=3): """ Cleans a binary image by separating loosely connected objects, eliminating small objects, and finally smoothing edges of the remaining objects. The method is ``binary_opening``, ``binary_closing``, and two rounds of ``median_filter``. Parameters ---------- img : array a boolean ndarray radius_1 : int Radius of disk structuring element for opening and closing. Default = 1, which gives 3x3 square connectivity (manhattan distance = 1). Can also supply own boolean array. structure_2 : int Radius of disk structuring element for smoothing with a median filter. Default = 2, which gives a is euclidean distance < 2*sqrt(2). Can also supply own boolean array. Returns ------- A boolean ndarray of the same dimensions as ``img``. See Also -------- In ``scipy.ndimage``, see ``skimage.morphology.binary_opening``, ``skimage.morphology.binary_closing``, and ``skimage.filters.median`` """ if len(np.array([radius_1]).shape) == 1: ELEMENT_1 = _disk(radius=radius_1) else: ELEMENT_1 = structure_1 if len(np.array([radius_2]).shape) == 1: ELEMENT_2 = _disk(radius=radius_2) else: ELEMENT_2 = structure_2 out = morphology.binary_opening(img, selem=ELEMENT_1) out = morphology.binary_closing(out, selem=ELEMENT_1) i = 0 while i < median_iterations: out = filters.median(out, selem=ELEMENT_2) i += 1 return(out)
def remove_small_ccomponents(base_label_image, size_closing=2, hist_thres=1000): # the number and lettering are a pain for a number of methods # we tried to get rid of it # to this end, we extract all markings, compute connected components, # compute the number of pixels in each components, and remove the components # with few pixels from scipy import ndimage as ndi from skimage.morphology import binary_closing, binary_opening, binary_dilation from skimage.morphology import disk from skimage.restoration import denoise_bilateral from skimage import measure from skimage.morphology import label import matplotlib.pyplot as plt import numpy as np #dilate then retract using morph math to consolidate noisy results #binclos = binary_dilation(jac_inverted) binclos = binary_closing(base_label_image,disk(size_closing)).astype(float) #binclos = binary_opening(binclos,disk(1)) #bil = denoise_bilateral(binclos, sigma_color=0.05, sigma_spatial=5, multichannel=False) #find the connected components markers, n_label = label(binclos, connectivity=1, background=0, return_num=True) #plt.imshow(markers,vmin=-1, vmax=1) hist, bins = np.histogram(markers, bins=n_label) r_bins = bins[0:n_label] print('hom much hist bins are we going to keep? : ',np.sum(hist>hist_thres) ) bins_to_remove = r_bins[hist<hist_thres] #np.append(bins_to_remove) to_remove_mask = np.in1d(markers, bins_to_remove.astype(int)) np.sum(to_remove_mask==True) to_remove_mask_resh = np.reshape(to_remove_mask, markers.shape) filtered_jac_inverted = np.copy(base_label_image) filtered_jac_inverted[to_remove_mask_resh == True] = 0 return filtered_jac_inverted, to_remove_mask_resh
def _run_interface(self, runtime): in_files = self.inputs.in_files if self.inputs.enhance_t2: in_files = [_enhance_t2_contrast(f, newpath=runtime.cwd) for f in in_files] masknii = compute_epi_mask( in_files, lower_cutoff=self.inputs.lower_cutoff, upper_cutoff=self.inputs.upper_cutoff, connected=self.inputs.connected, opening=self.inputs.opening, exclude_zeros=self.inputs.exclude_zeros, ensure_finite=self.inputs.ensure_finite, target_affine=self.inputs.target_affine, target_shape=self.inputs.target_shape ) if self.inputs.closing: closed = sim.binary_closing(masknii.get_data().astype( np.uint8), sim.ball(1)).astype(np.uint8) masknii = masknii.__class__(closed, masknii.affine, masknii.header) if self.inputs.fill_holes: filled = binary_fill_holes(masknii.get_data().astype( np.uint8), sim.ball(6)).astype(np.uint8) masknii = masknii.__class__(filled, masknii.affine, masknii.header) if self.inputs.no_sanitize: in_file = self.inputs.in_files if isinstance(in_file, list): in_file = in_file[0] nii = nb.load(in_file) qform, code = nii.get_qform(coded=True) masknii.set_qform(qform, int(code)) sform, code = nii.get_sform(coded=True) masknii.set_sform(sform, int(code)) self._results['out_mask'] = fname_presuffix( self.inputs.in_files[0], suffix='_mask', newpath=runtime.cwd) masknii.to_filename(self._results['out_mask']) return runtime
def estimate_ympp(self, line_img): """This implemenation of estimation meter-per-pixel on y axis is very hard-coded and image dependent. Actually I am not aware of a general way of doing it. """ # warp line_img by the estimated perspective transform warped_img = self.binary_transform(line_img) # close the gaps in image, focus on the right part that # has the dotted line segments right_lane_img = binary_closing(warped_img, selem=disk(5)) right_lane_img = right_lane_img[:,1000:] # find the regions, find the length of dot-lane segment # as the max-axis-length of the larget region regions = regionprops(label(right_lane_img)) max_len = max([r.major_axis_length for r in regions]) # that segment is 3 meters in reality y_mpp = 3 / max_len return y_mpp
def split(name): img = plt.imread(name) img = img[205:495,255:980] binary = np.logical_and(img[:,:,2] > 0.8,img[:,:,0] < 0.5) binary = binary_closing(binary) binary_index = binary[:212,:] binary_news = binary[212:,:] img = img[:,600:] binary = img[:,:,2] < 0.9 digit_index = binary[10:200,50:116] digit_news = binary[243:278,80:116] c = 30 d = 12 digit_index_list = [digit_index[i*c:i*c+d,:] for i in range(7)] digit_news_list = [digit_news[:11,:],digit_news[25:,:]] return binary_index,binary_news,digit_index_list,digit_news_list
def remove_small_ccomponents(base_label_image, size_closing=2, hist_thres=1000): # the number and lettering are a pain for a number of methods # we tried to extract it from skimage.morphology import binary_closing from skimage.morphology import disk from skimage.morphology import label import numpy as np import cv2 base_label_image_f = cv2.bilateralFilter( (base_label_image).astype(np.uint8), d=5, sigmaColor=0.05, sigmaSpace=5) # dilate then retract using morph math to consolidate noisy results # binclos = binary_dilation(jac_inverted) binclos = binary_closing(base_label_image_f, disk(size_closing)).astype(float) # find the connected components markers, n_label = label(binclos, connectivity=1, background=0, return_num=True) # plt.imshow(markers,vmin=-1, vmax=1) hist, bins = np.histogram(markers, bins=n_label) r_bins = bins[0:n_label] print('hom much hist bins are we going to keep? : ', np.sum(hist > hist_thres)) bins_to_remove = r_bins[hist < hist_thres] # np.append(bins_to_remove) to_remove_mask = np.in1d(markers, bins_to_remove.astype(int)) np.sum(to_remove_mask is True) to_remove_mask_resh = np.reshape(to_remove_mask, markers.shape) filtered_jac_inverted = np.copy(base_label_image) filtered_jac_inverted[to_remove_mask_resh == 1] = 0 return filtered_jac_inverted, to_remove_mask_resh