def add_hysteresis_threshold(self, low=20, high=150): """ Adds attribute binary_hyst from CspyStack.cropped if available, otherwise uses raw stack. See https://scikit-image.org/docs/dev/auto_examples/filters/plot_hysteresis.html Pixels above the high theshold are considered to be a particle, pixels between low and high values are only considered part of a particle if they touch another particle that was designated as a particle. :param low: lowest pixel value to be considered as part of a potential particle :param high: pixel values higher than this threshold area always considered a particle :return: nothing """ if self.cropped is None: if len(self.shape) == 3: binary = [] for i in tqdm(range(len(self)), desc='Applying hysteresis threshold to CspyStack.binary_hyst', leave=True): binary.append(filters.apply_hysteresis_threshold(self[i], low=low, high=high)) self.binary_hyst = CspyStack(binary) elif len(self.shape) == 2: print('Applying hysteresis threshold to CspyStack.binary_hyst') self.binary_hyst = CspyStack(filters.apply_hysteresis_threshold(self, low=low, high=high)) else: raise Exception('TypeError: shape of images not correct. Is stack greyscale?') else: if len(self.shape) == 3: binary = [] for i in tqdm(range(len(self)), desc='Applying hysteresis threshold to CspyStack.binary_hyst', leave=True): binary.append(filters.apply_hysteresis_threshold(self.cropped[i], low=low, high=high)) self.binary_hyst = CspyStack(binary) elif len(self.shape) == 2: print('Applying hysteresis threshold to CspyStack.binary_hyst') self.binary_hyst = CspyStack(filters.apply_hysteresis_threshold(self.cropped, low=low, high=high)) else: raise Exception('TypeError: shape of images not correct. Is stack greyscale?')
def hystMemb(img, roi_center, roi_size=30, noise_size=20, low_diff=40, gen_high=0.8, sigma=3): """ Function for membrane region detection with hysteresis threshold algorithm. Outdide edge - >= 2sd noise Inside edge - >= cytoplasm mean intensity Require hystLow function for lower hysteresis threshold calculations. img - imput z-stack frame; roi_center - list of int [x, y], coordinates of center of the cytoplasmic ROI for cytoplasm mean intensity calculation; roi_size - int, cutoplasmic ROI side size in px (ROI is a square area); noise_size - int, size in px of region for noise sd calculation (square area witf start in 0,0 coordinates); sd_low - float, hysteresis algorithm lower threshold for outside cell edge detection, > 2sd of noise (percentage of maximum frame intensity); mean_low - float, hysteresis algorithm lower threshold for inside cell edge detection, > cytoplasmic ROI mean intensity (percentage of maximum frame intensity); gen_high - float, general upper threshold for hysteresis algorithm (percentage of maximum frame intensity); sigma - int, sd for gaussian filter. Returts membrane region boolean mask for input frame. """ img = backCon(img, dim=2) img_gauss = filters.gaussian(img, sigma=sigma) noise_sd = np.std(img[:noise_size, :noise_size]) logging.info('Frame noise SD={:.3f}'.format(noise_sd)) roi_mean = np.mean(img[roi_center[0] - roi_size//2:roi_center[0] + roi_size//2, \ roi_center[1] - roi_size//2:roi_center[1] + roi_size//2]) # cutoplasmic ROI mean celculation logging.info('Cytoplasm ROI mean intensity {:.3f}'.format(roi_mean)) low_val = hystLow(img, img_gauss, sd=noise_sd, mean=roi_mean, diff=low_diff, gen_high=gen_high) mask_2sd = filters.apply_hysteresis_threshold( img_gauss, low=low_val['2sd'] * np.max(img_gauss), high=gen_high * np.max(img_gauss)) mask_roi_mean = filters.apply_hysteresis_threshold( img_gauss, low=low_val['mean'] * np.max(img_gauss), high=gen_high * np.max(img_gauss)) # filling external space and create cytoplasmic mask mask_cytoplasm = mask_roi_mean + segmentation.flood(mask_roi_mean, (0, 0)) return mask_2sd, mask_roi_mean, ma.masked_where(~mask_cytoplasm, mask_2sd)
def run(img, **args): if len(img.shape) > 2 and img.shape[2] == 4: img = color.rgba2rgb(img) if len(img.shape) == 2: img = color.gray2rgb(img) img = apply_hysteresis_threshold(color.rgb2gray(img), **args) return to_base64(img)
def detect_edges(self, filename=None): """Edge filter an image using the Canny algorithm.""" if filename is None: filename = './output/phough_transform' low = self.canny_threshold[0] * (self.img.max() - self.img.min()) high = self.canny_threshold[1] * (self.img.max() - self.img.min()) if self.canny_edges == 'horizontal': print('Running One-Way Horizontal Edge Detector') magnitude = sobel_h(self.img).clip(min=0) elif self.canny_edges == 'vertical': print('Running One-Way Vertical Edge Detector') magnitude = sobel_v(self.img).clip(min=0) else: print('Running One-Way Multidirectional Edge Detector') magnitude = sobel(self.img).clip(min=0) self.edges = apply_hysteresis_threshold(magnitude, low, high) if self.show_figures: io.imshow(self.edges) plt.show(block=False) if self.save_figures: io.imsave(filename + '.tif', util.img_as_ubyte(self.edges))
def hyst_tresh_filter( folder ): # iterate through folders, assembling feature, label, and classname data objects class_id = 0 features = [] labels = np.array([]) classnames = [] for root, dirs, filenames in os.walk(folder): for d in sorted(dirs): #print("Reading data from", d) classnames.append( d) # use the folder name as the class name for this label files = os.listdir(os.path.join(root, d)) for f in files: imgFile = os.path.join(root, d, f) # Load the image file img = plt.imread(imgFile) img = cv2.resize( img, (128, 128)) # Resizing all the images to insure proper reading hyst_treshold = apply_hysteresis_threshold(img, 1.5, 2.5) features.append(hyst_treshold.ravel()) labels = np.append( labels, class_id) # Add it to the numpy array of labels class_id += 1 features = np.array( features) # Convert the list of features into a numpy array return features, labels, classnames
def hysteresis_threshold(img: PIL.Image.Image, low: int = 50, high: int = 100) -> PIL.Image.Image: """Apply two-level (hysteresis) threshold to an image. Parameters ---------- img : PIL.Image.Image Input image low : int, optional low threshold. Default is 50. high : int, optional high threshold. Default is 100. Returns ------- PIL.Image.Image Image with the hysteresis threshold applied """ # TODO: warning grayscale input image (skimage doc) if low is None or high is None: raise ValueError("thresholds cannot be None") hyst = sk_filters.apply_hysteresis_threshold(np.array(img), low, high) img_out = apply_mask_image(img, hyst) return img_out
def __low_calc(self, img, gauss, threshold_value): """ Lower threshold calculations for hysteresis detection functions. """ mask_img = ma.masked_greater_equal(img, threshold_value) # # fixed-value masked image saving, for debuging only # plt.figure() # ax0 = plt.subplot() # img0 = ax0.imshow(mask_img) # plt.savefig(f'mask_{int(threshold_value)}.png') low = self.low_init diff = np.size(img) while diff > self.mask_diff: mask_hyst = filters.apply_hysteresis_threshold( gauss, low=low * np.max(gauss), high=self.high * np.max(gauss)) diff = np.sum(ma.masked_where(~mask_hyst, mask_img) > 0) if all([diff < self.mask_diff, low == self.low_init]): logging.fatal('Initial lower threshold is too low!') break low += 0.01 if low >= self.high: logging.fatal('LOW=HIGH, thresholding failed!') break logging.debug(f'Lower threshold {round(low, 2)}') # # final masks difference, for debuging only # plt.figure() # ax0 = plt.subplot() # img0 = ax0.imshow(ma.masked_where(~mask_hyst, mask_img)) # plt.savefig(f'mask_low_{int(threshold_value)}.png') return low
def detector(self): """ Create detector instance for specific record. """ trun = lambda k, sd: ( ((k - 1) / 2) - 0.5 ) / sd # calculate truncate value for Gaussian fliter according to sigma value and kernel size self.truncate = trun(self.kernel_size, self.sigma) self.gauss = filters.gaussian(self.img, sigma=self.sigma, truncate=self.truncate) self.detection_mask = filters.apply_hysteresis_threshold( self.gauss, low=self.low_detection * np.max(self.gauss), high=self.high * np.max(self.gauss)) self.cells_labels, self.cells_num = ndi.label(self.detection_mask) if self.cells_num == 0: logging.warning( f'Cells DOESN`T detected! You should try increase low_detection' ) raise ValueError cells_center_float = ndi.center_of_mass(self.cells_labels, self.cells_labels, range(1, self.cells_num + 1)) self.cells_center = [[int(x) for x in i] for i in cells_center_float] self.cells_center_dict = dict( zip(range(1, self.cells_num + 1), self.cells_center)) logging.info( f'Detected {self.cells_num} cell(s) with center of mass coord. {self.cells_center_dict}' )
def make_consistent_data(data4D, aperture_size, voltage, real_calib_pm, transpose=True, flip=True): if transpose: data4D = np.transpose(data4D,(2,3,0,1)) if flip: data4D = flip_corrector(data4D) data_size = np.asarray(np.shape(data4D),dtype=int) Mean_Ronchigram = np.mean(data4D,axis=(2,3)) upper_thresh = skf.threshold_otsu(Mean_Ronchigram) lower_thresh = (-1)*(skf.threshold_otsu(-Mean_Ronchigram)) canny_ronchi = skf.apply_hysteresis_threshold(Mean_Ronchigram, lower_thresh, upper_thresh) rad_image = canny_ronchi.astype(int) regions = measure.regionprops(rad_image) bubble = regions[0] y_center, x_center = bubble.centroid radius = bubble.major_axis_length / 2. def cost(params): x0, y0, r = params coords = draw.circle(y0, x0, r, shape=image.shape) template = np.zeros_like(image) template[coords] = 1 return -np.sum(template == image) x_center, y_center, radius = optimize.fmin(cost, (x_center, y_center, radius)) fourier_calibration_pm = (aperture_size/(1000*wavelength_pm(voltage)))/radius _,fourier_pixel = get_probe(aperture_size,voltage,data_size[2],data_size[3],real_calib_pm) sampling_ratio = fourier_calibration_pm/fourier_pixel resized_data = sample_4D(data4D,sampling_ratio) return resized_data
def extract_skel_bowler_hat(im, no, si, low, high): bowled_hat = bowler_hat(-im, no, si) transformed = 255 * bowled_hat hyst = filters.apply_hysteresis_threshold(transformed, low, high) kernel = np.ones((3, 3), np.uint8) dilation = cv.dilate(hyst.astype(np.uint8) * 255, kernel, iterations=1) for i in range(3): dilation = cv.erode(dilation.astype(np.uint8) * 255, kernel, iterations=1) dilation = cv.dilate(dilation.astype(np.uint8) * 255, kernel, iterations=1) dilated = dilation > 0 nb_components, output, stats, centroids = cv.connectedComponentsWithStats( dilated.astype(np.uint8), connectivity=8) # connectedComponentswithStats yields every seperated component with information on each of them, such as size # the following part is just taking out the background which is also considered a component, but most of the time we don't want that. sizes = stats[1:, -1] nb_components = nb_components - 1 # minimum size of particles we want to keep (number of pixels) # here, it's a fixed value, but you can set it as you want, eg the mean of the sizes or whatever min_size = 4000 # your answer image img2 = np.zeros((dilated.shape)) # for every component in the image, you keep it only if it's above min_size for i in range(0, nb_components): if sizes[i] >= min_size: img2[output == i + 1] = 1 return img2
def occlusion_removal(img,threshold=20,SE_radius=13,minArea=50000): # Remove Dark Hair Occlusions in Dermatoscopic Images via LUV Color Space luv = cv2.cvtColor(img, cv2.COLOR_RGB2Luv) # Morphological Closing via Spherical SE kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(SE_radius,SE_radius)) closing = cv2.morphologyEx(luv, cv2.MORPH_CLOSE, kernel) # Generate Masks via Hysteresis Thresholding Difference Image in L Channel diffc = closing[:,:,0]-luv[:,:,0] maskc = (skifilters.apply_hysteresis_threshold(diffc,threshold,80)).astype(np.uint8)*255 # Remove Side Components label_im, nb_labels = ndimage.label(maskc) sizes = ndimage.sum(maskc, label_im, range(nb_labels + 1)) temp_mask = sizes > minArea maskc = (temp_mask[label_im]*255).astype(np.uint8) mask_3dc = maskc[:,:,None] * np.ones(3,dtype=np.uint8)[None, None, :] basec = cv2.bitwise_not(maskc) base_3dc = basec[:,:,None] * np.ones(3,dtype=np.uint8)[None, None, :] # Restitch Preprocessed Image preimagec = ((base_3dc/255)*luv).astype(np.uint8) postimagec = ((mask_3dc/255)*closing).astype(np.uint8) fullc = preimagec + postimagec outputc = cv2.cvtColor(fullc, cv2.COLOR_Luv2RGB) return outputc, maskc
def hysteresis_threshold_mask(img: PIL.Image.Image, low: int = 50, high: int = 100) -> np.ndarray: """Mask an image using hysteresis threshold Compute the Hysteresis threshold on the complement of a greyscale image, and return boolean mask based on pixels above this threshold. Parameters ---------- img : PIL.Image.Image Input image. low : int, optional low threshold. Default is 50. high : int, optional high threshold. Default is 100. Returns ------- np.ndarray Boolean NumPy array where True represents a pixel above Otsu threshold. """ if low is None or high is None: raise ValueError("thresholds cannot be None") gs = PIL.ImageOps.grayscale(img) comp = invert(gs) hyst_mask = sk_filters.apply_hysteresis_threshold(np.array(comp), low, high) return hyst_mask
def test_apply_filters_functionality(self): cm = plt.get_cmap('gray') kw = {'cmap': cm, 'interpolation': 'none', 'origin': 'upper'} im = cv2.imread('ms_25_short.png', 0) angles = np.arange(0, 155, 25) scales = [16.8, 22.5] orient, _, response = MultiSkewExtractor.filter_document( im, scales, angles) print(response[99:119, 99:119]) print("\norient:{}\n\n".format(orient[99:119, 99:119])) response = np.double(response) m, s = _mean_std(response, int(math.ceil(22.5) * 2 + 1)) print("\nmean:{}\n\n".format(m[99:119, 99:119])) print("\nstd:{}\n\n".format(s[99:119, 99:119])) high = 22 low = 8 thresh_niblack2 = np.divide((response - m), s) * 20 # plt.subplot(1, 3, 3) # plt.imshow(thresh_niblack2, **kw) # plt.title('thresh_niblack2') lines = apply_hysteresis_threshold(thresh_niblack2, low, high) print("\nlines:{}\n\n".format(lines[99:119, 99:119])) # plt.subplot(1, 3, 1) # plt.imshow(response, **kw) # plt.title('response') plt.subplot(1, 1, 1) plt.imshow(lines, **kw) plt.title('lines') plt.show() print("done")
def hysteresis_threshold(image): fig, ax = plt.subplots(nrows=2, ncols=2) image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) edges = filters.sobel(image) low = 0.1 high = 0.35 lowt = (edges > low).astype(int) hight = (edges > high).astype(int) hyst = filters.apply_hysteresis_threshold(edges, low, high) ax[0, 0].imshow(image, cmap='gray') ax[0, 0].set_title('Original image') ax[0, 1].imshow(edges, cmap='magma') ax[0, 1].set_title('Sobel edges') ax[1, 0].imshow(lowt, cmap='magma') ax[1, 0].set_title('Low threshold') ax[1, 1].imshow(hight + hyst, cmap='magma') ax[1, 1].set_title('Hysteresis threshold') for a in ax.ravel(): a.axis('off') plt.tight_layout() plt.show()
def hysteresis(image): high = filters.threshold_yen(image) low = high * 0.9 hight = (image > high).astype(int) lowt = (image > low).astype(int) binary = filters.apply_hysteresis_threshold(image, low, high) return binary
def huge_cell_mask(self): """ Creating binary mask for homogeneous fluoresced cell by SD thresholding and hysteresis smoothing. Detecting one cell in frame, with largest area. """ # NOW DOESN'T WORKING, NEED UPDATE! raw_mask = filters.apply_hysteresis_threshold( self.gauss, low=self.__low_calc(self.img) * np.max(self.gauss), high=self.high * np.max(self.gauss)) logging.info('Mask builded successfully') labels_cells, cells_conunt = ndi.label(raw_mask) logging.info(f'{cells_conunt} cells detected') if cells_conunt > 1: size_list = [ np.sum( ma.masked_where(labels_cells == cell_num, labels_cells).mask) for cell_num in range(cells_conunt) ] logging.info(f'Cells sizes {size_list}') mask = ma.masked_where( labels_cells == size_list.index(max(size_list)) + 1, labels_cells).mask else: mask = raw_mask return mask, labels_cells
def diff_color(image1, image2): """ difference methode in de LAB kleurruimte :param image1: frame 1 :param image2: frame 2 :return: segmentatie van frame 2 """ # euclidische afstand in LAB werkt beter dan in RGB image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2LAB).astype(np.float32) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2LAB).astype(np.float32) # verschilbeeld nemen im = np.sqrt((image1[:, :, 1] - image2[:, :, 1])**2 + (image1[:, :, 0] - image2[:, :, 0])**2 + (image1[:, :, 2] - image2[:, :, 2])**2) # blur toepassen im = cv2.GaussianBlur(im, (5, 5), 0) # hysteresis thresholding threshhold = find_threshhold(im) im = (filters.apply_hysteresis_threshold(im, threshhold, threshhold * 6) * 255).astype(np.uint8) # opvulling van gaten in blobs contours, _ = cv2.findContours(im, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) for c in contours: cv2.drawContours(im, [c], 0, 255, -1) return im
def peak_img_diff(self, sigma=1, kernel_size=5, baseline_win=3, stim_shift=0, stim_win=3, up_min_tolerance=0.2, up_max_tolerance=0.75, down_min_tolerance=2, down_max_tolerance=0.75, path=False): """ Mask for up and down regions of FP channel data. baseline_win - indexes of frames for baseline image creation stim_shift - additional value for loop_start_index tolerance - tolerance value in au for mask creation, down < -tolerance, up > tolerance REQUIRE peaks position (find_stim_peak). """ trun = lambda k, sd: (((k - 1)/2)-0.5)/sd # calculate truncate value for gaussian fliter according to sigma value and kernel size prot_series_sigma = [filters.gaussian(i, sigma=sigma, truncate=trun(kernel_size, sigma)) for i in self.prot_series] baseline_prot_img = np.mean(prot_series_sigma[:baseline_win], axis=0) self.peak_diff_series = [] self.up_diff_mask = [] self.down_diff_mask = [] self.up_diff_mask_prop = [] self.comb_diff_mask = [] for stim_position in self.stim_peak: diff_frames_start = stim_position + stim_shift diff_frames_end = stim_position + stim_shift + stim_win stim_mean_img = np.mean(prot_series_sigma[diff_frames_start:diff_frames_end], axis=0) stim_diff_img = stim_mean_img - baseline_prot_img # creating and normalization of differential image stim_diff_img[self.cell_distances >= 30] = 0 stim_diff_img = stim_diff_img/np.max(np.abs(stim_diff_img)) self.peak_diff_series.append(stim_diff_img) # up regions thresholding frame_diff_up_mask = filters.apply_hysteresis_threshold(stim_diff_img, low=up_min_tolerance, high=up_max_tolerance) frame_diff_up_mask_elements = measure.label(frame_diff_up_mask) self.up_diff_mask.append(frame_diff_up_mask_elements) # up mask elements labeling # down regions thresholding frame_diff_down_mask = filters.apply_hysteresis_threshold(stim_diff_img, low=down_min_tolerance, high=down_max_tolerance) self.down_diff_mask.append(frame_diff_down_mask) self.comb_diff_mask.append((frame_diff_up_mask*2) + (frame_diff_down_mask-2)*-1) # find better up mask (with maximal area) self.best_up_mask_index = np.argmax([np.sum(u_m != 0) for u_m in self.up_diff_mask]) logging.info(f'Best up mask {self.best_up_mask_index+1} (stim frame {self.stim_peak[self.best_up_mask_index]})')
def run(self, image): if not self.high: self.high = filters.threshold_yen(image) else: self.high = self.high * image.max() low = self.high * (1 - self.expansion) self.mask = filters.apply_hysteresis_threshold(image, low, self.high) self.image = self.apply_mask(image, self.mask) return self.image
def grains_by_hysteresis_threshold(image, nsigma=5, plot=False): ''' Creates a grain binary mask from a greyscale image using the hysteresis threshold. The algorithm is thus: - Compute histogram of image - Measure background intensity and fit Gaussian - Upper threshold of skimage.filters.apply_hysteresis_threshold is the Otsu threshold of the image - Lower threshold is the maximum value of the BG gaussian fit + n*sigma that is still lower that Otsu's threshold This helps measure grain edges (which can be smaller than Otsu's threshold). Parameters ---------- image: numpy.ndarray Greyscale image. nsigma: int Maximum value of BG sigma to use as lower threshold. plot: bool Whether to plot the histogram and fit. Returns ------- mask: numpy.ndarray Binary mask of found grains. ''' # make image of type float image = image.astype(float) # creat histogram of intensities vals, bins = _exposure.histogram(image) # create guess of background -> maximum of histogram corresponds to bg pixels guess = _cgfpp(vals, bins, [bins[vals.argmax()]]) fp, _ = _optimize.curve_fit(_Gauss.vector, bins, vals, p0=guess) x0, A, sigma = fp # calcultae classical Otsu threshold of image thold_otsu = _filters.threshold_otsu(image) # the lower bound for hystereiss threshold is where the maximum of BG # Guassian fit x0+n*sigma that is smaller that Otsu threshold _nsigma = _np.arange(1, nsigma + 1) * sigma + x0 _lower = _nsigma[(thold_otsu - _nsigma) > 0].max() # compute grainmask mask = _filters.apply_hysteresis_threshold(image, _lower, thold_otsu) if plot: _plt.plot(bins, vals, label='Data') _plt.plot(bins, _Gauss.vector(bins, *fp), label='Fit') _plt.axvline(_lower, label='Lower threshold') _plt.axvline(thold_otsu, label='Upper (Otsu) threshold') _plt.legend() return mask
def apply_hysteresis_threshold(arr1d): """ TypeError: ndarray() missing required argument 'shape' (pos 1) :param arr1d: :return: """ import skimage.filters as sf thresh = sf.apply_hysteresis_threshold(arr1d, low=-25.0, high=-23.0) return thresh
def run(self, ips, snap, img, para=None): img[:] = snap > 0 dist = -ndimg.distance_transform_edt(snap) pts = find_maximum(dist, para['tor'], False) buf = np.zeros(ips.size, dtype=np.uint32) buf[pts[:, 0], pts[:, 1]] = img[pts[:, 0], pts[:, 1]] = 2 markers, n = ndimg.label(buf, np.ones((3, 3))) line = watershed(dist, markers, line=True, conn=para['con'] + 1) msk = apply_hysteresis_threshold(img, 0, 1) img[:] = snap * ~((line == 0) & msk)
def process_image(orgimg, img, lowthresh, highthresh, morphsize): # re-apply hysteresis threshold img = filters.apply_hysteresis_threshold(sub, lowthresh, highthresh).astype(np.uint8) # dilate to expand the area to be inpainted, attempting to cover some # shadows/borders left undetected by this algorithm img = cv2.dilate(img, cv2.getStructuringElement(cv2.MORPH_RECT, (int(round(morphsize)), int(round(morphsize))))) # return the inpainted image # NOTE: I haven't messed around with very many inpainting algorithms, I imagine with little bit of research. ENDNOTE # would turn up one better suited for skin. ENDNOTE return cv2.inpaint(image, img, 10, cv2.INPAINT_NS)
def _diff_binarization(self): diff_mask = apply_hysteresis_threshold(self.diff_image, self.LOW_DIFF_THRESHOLD, self.HIGH_DIFF_THRESHOLD) valid_diff_mask = np.bitwise_and(diff_mask, self.valid_registration_mask) if self.debug: show_image(valid_diff_mask, 'valid_diff_mask') self._save_image(valid_diff_mask, 'Diff mask') return valid_diff_mask
def hysteresis_thrsholding(img): edges = filters.sobel(img) low = 0.1 high = 0.6 lowt = (edges > low).astype(int) hight = (edges > high).astype(int) hyst = filters.apply_hysteresis_threshold(edges, low, high) return hight + hyst
def hysteresis(image, alpha=1.0): """Hystersis thresholding with low and high clipped values determined by the mean, li and isodata threshold""" low = np.min([alpha * threshold_mean(image), threshold_li(image)]) high = threshold_isodata(image) threshold = apply_hysteresis_threshold(image, low, high) return threshold
def __niblack_pre_process(self, max_response, n): im = np.double(max_response) m, s = _mean_std(im, 47) high = 22 low = 8 thresh_niblack2 = np.divide((im - m), s) * 20 lines = apply_hysteresis_threshold(thresh_niblack2, low, high) lines = reconstruction(np.logical_and(self.bin_image, lines), lines, method='dilation') return thresh_niblack2, lines
def niblack_pre_process(max_response, n, bin): im = np.double(max_response) # int(16.8) * 2 + 1 m, s = _mean_std(im, 47) high = 22 low = 8 thresh_niblack2 = np.divide((im - m), s) * 20 lines = apply_hysteresis_threshold(thresh_niblack2, low, high) lines = reconstruction(np.logical_and(bin, lines), lines, method='dilation') return thresh_niblack2, lines
def connected_components(image, hist_min, hist_max): image = np.array(image) thresh = filters.apply_hysteresis_threshold(np.array(image), hist_min, hist_max) thresh = (np.clip(thresh, 0, 1) * 255).astype(np.uint8) # Marker labelling ret, markers = cv2.connectedComponents(thresh) markers = markers + 1 markers[thresh == 0] = 0 return markers
def canny(): """Canny edge detection in 5 steps: rgb2gray, gaussian filter, Sobel filter, non-max suppression, Double threshold + hysteresis Returns: --------------------------- edges: ndarray Extracted edges from the image """ """Step 1: Converting to grayscale""" if otsu: # TODO improve Otsu threshold, currently better without it gray_image = rgb2gray(image) thresh = filters.threshold_otsu(gray_image) gray_image = gray_image > thresh else: gray_image = rgb2gray(image) """Plots, uncomment if needed""" # plot.imshow(gray_image, cmap = plot.cm.gray) # plot.show() """Step 2: Reducing the salt-and-pepper noise""" gaussian_image = filters.gaussian(gray_image, sigma=0.2) """Plots, uncomment if needed""" # plot.imshow(gaussian_image, cmap = plot.cm.gray) # plot.title("Gaussian blur") # plot.show() """ Step 3 and 4: Sobel filter + non-max suppression""" filtered_image, theta = sobel_filter(gaussian_image) # plot.imshow(filtered_image, cmap=plot.cm.gray) # plot.title("sobel filter") # plot.show() suppression_image = non_max_suppression(filtered_image, theta) """Plots, uncomment if needed""" # plot.imshow(suppression_image, cmap=plot.cm.gray) # plot.title("Suppression") # plot.show() """ Step 5: Double threshold + hysteresis """ sigma = 0.33 v = np.median(image) lower = int(max(0, (1.0 - sigma) * v)) upper = int(min(255, (1.0 + sigma) * v)) if canny_skimage: edges = feature.canny(gray_image, 3) else: edges = ((suppression_image > upper).astype(int)) \ + filters.apply_hysteresis_threshold(suppression_image, lower, upper) """ Plot of Canny edges """ plot.imshow(edges, cmap=plot.cm.gray) plot.title("Canny edges") plot.show() return edges
""" import matplotlib.pyplot as plt from skimage import data, filters fig, ax = plt.subplots(nrows=2, ncols=2) image = data.coins() edges = filters.sobel(image) low = 0.1 high = 0.35 lowt = (edges > low).astype(int) hight = (edges > high).astype(int) hyst = filters.apply_hysteresis_threshold(edges, low, high) ax[0, 0].imshow(image, cmap='gray') ax[0, 0].set_title('Original image') ax[0, 1].imshow(edges, cmap='magma') ax[0, 1].set_title('Sobel edges') ax[1, 0].imshow(lowt, cmap='magma') ax[1, 0].set_title('Low threshold') ax[1, 1].imshow(hight + hyst, cmap='magma') ax[1, 1].set_title('Hysteresis threshold') for a in ax.ravel(): a.axis('off')