def test_3d_energy_decrease(): a_black = np.zeros((5, 5, 5)).astype(np.uint8) a_black[2, 2, 2] = 255 a_white = invert(a_black) assert_array_less( meijering(a_black, black_ridges=True).std(), a_black.std()) assert_array_less( meijering(a_white, black_ridges=False).std(), a_white.std()) assert_array_less( sato(a_black, black_ridges=True, mode='reflect').std(), a_black.std()) assert_array_less( sato(a_white, black_ridges=False, mode='reflect').std(), a_white.std()) assert_array_less(frangi(a_black, black_ridges=True).std(), a_black.std()) assert_array_less(frangi(a_white, black_ridges=False).std(), a_white.std()) assert_array_less( hessian(a_black, black_ridges=True, mode='reflect').std(), a_black.std()) assert_array_less( hessian(a_white, black_ridges=False, mode='reflect').std(), a_white.std())
def __call__(self, x): image = self.frangi_transform(x) img = (np.transpose(image.cpu().detach().numpy(), (1, 2, 0)) * 255) gray_img = rgb2gray(img) plt.imsave('frame.jpg', gray_img, cmap='gray') filtered_1 = frangi(gray_img, sigmas=range( 2, 5, 3)) # gray_img is uint8 while filtered img is between 0 and 1 #print(filtered_1) filtered_2 = frangi(gray_img, sigmas=range( 5, 8, 3)) # gray_img is uint8 while filtered img is between 0 and 1 filtered_3 = frangi(gray_img, sigmas=range( 8, 12, 3)) # gray_img is uint8 while filtered img is between 0 and 1 plt.imsave('filtered_1.jpg', filtered_1, cmap='gray') plt.imsave('filtered_2.jpg', filtered_2, cmap='gray') plt.imsave('filtered_3.jpg', filtered_3, cmap='gray') filtered_1 = transforms.ToTensor()(filtered_1).float( ) # gray_img is uint8 while filtered img is between 0 and 1 filtered_2 = transforms.ToTensor()(filtered_2).float( ) # gray_img is uint8 while filtered img is between 0 and 1 filtered_3 = transforms.ToTensor()(filtered_3).float( ) # gray_img is uint8 while filtered img is between 0 and 1 filtered = torch.cat([filtered_1, filtered_2, filtered_3], dim=0) #print(self.base_transform(x).size()) return [self.base_transform(x), filtered]
def test_2d_linearity(): a_black = np.ones((3, 3)).astype(np.uint8) a_white = invert(a_black) assert_allclose(meijering(1 * a_black, black_ridges=True), meijering(10 * a_black, black_ridges=True), atol=1e-3) assert_allclose(meijering(1 * a_white, black_ridges=False), meijering(10 * a_white, black_ridges=False), atol=1e-3) assert_allclose(sato(1 * a_black, black_ridges=True), sato(10 * a_black, black_ridges=True), atol=1e-3) assert_allclose(sato(1 * a_white, black_ridges=False), sato(10 * a_white, black_ridges=False), atol=1e-3) assert_allclose(frangi(1 * a_black, black_ridges=True), frangi(10 * a_black, black_ridges=True), atol=1e-3) assert_allclose(frangi(1 * a_white, black_ridges=False), frangi(10 * a_white, black_ridges=False), atol=1e-3) assert_allclose(hessian(1 * a_black, black_ridges=True), hessian(10 * a_black, black_ridges=True), atol=1e-3) assert_allclose(hessian(1 * a_white, black_ridges=False), hessian(10 * a_white, black_ridges=False), atol=1e-3)
def test_cropped_camera_image(): image = crop(camera(), ((206, 206), (206, 206))) assert_allclose(frangi(image), np.zeros((100, 100)), atol=1e-03) assert_allclose(frangi(image, black_ridges=True), np.zeros((100, 100)), atol=1e-03) assert_allclose(hessian(image), np.ones((100, 100)), atol=1 - 1e-07)
def test_3d_linearity(): # Note: last axis intentionally not size 3 to avoid 2D+RGB autodetection # warning from an internal call to `skimage.filters.gaussian`. a_black = np.ones((3, 3, 5)).astype(np.uint8) a_white = invert(a_black) assert_allclose(meijering(1 * a_black, black_ridges=True), meijering(10 * a_black, black_ridges=True), atol=1e-3) assert_allclose(meijering(1 * a_white, black_ridges=False), meijering(10 * a_white, black_ridges=False), atol=1e-3) assert_allclose(sato(1 * a_black, black_ridges=True, mode='reflect'), sato(10 * a_black, black_ridges=True, mode='reflect'), atol=1e-3) assert_allclose(sato(1 * a_white, black_ridges=False, mode='reflect'), sato(10 * a_white, black_ridges=False, mode='reflect'), atol=1e-3) assert_allclose(frangi(1 * a_black, black_ridges=True), frangi(10 * a_black, black_ridges=True), atol=1e-3) assert_allclose(frangi(1 * a_white, black_ridges=False), frangi(10 * a_white, black_ridges=False), atol=1e-3) assert_allclose(hessian(1 * a_black, black_ridges=True, mode='reflect'), hessian(10 * a_black, black_ridges=True, mode='reflect'), atol=1e-3) assert_allclose(hessian(1 * a_white, black_ridges=False, mode='reflect'), hessian(10 * a_white, black_ridges=False, mode='reflect'), atol=1e-3)
def frangiFilter(imageName): ## read image im = cv2.cv2.imread(imageName, 0) ## create the different 3D arrays that will be used importStack = np.empty([im.shape[i] for i in [0, 1]]) imgStackProcesses = np.empty([im.shape[i] for i in [0, 1]]) imgStackSoma = np.empty([im.shape[i] for i in [0, 1]]) threshStack = np.empty([im.shape[i] for i in [0, 1]]) somaStack = np.empty([im.shape[i] for i in [0, 1]]) ## fill each array importStack = im imgStackProcesses = filters.frangi(importStack, scale_range=(1, 6), beta1=1, beta2=25) imgStackSoma = filters.frangi(importStack, scale_range=(5, 20), beta1=1, beta2=15) threshStack = ((imgStackProcesses > 4e-6) + (imgStackSoma > 4e-6)) > 0 showThreshStack = threshStack showThreshStack[showThreshStack > 0] = 1 ## save arrays to binary .npy files np.save('importStack', importStack) np.save('imgStackProcesses', imgStackProcesses) #np.save('imgStackSoma', imgStackSoma) np.save('threshStack', threshStack) ## set threshold pixThresh = 1e3 ## remove small objects bigOnly = morphology.remove_small_objects(showThreshStack, pixThresh) bigOnlyShow = np.multiply(bigOnly, 255) ## label objects in bigOnly lab, n = ndimage.label(bigOnly) ## display """fig, ax = plt.subplots(ncols=3) ax[0].imshow(im) ax[0].set_title('Original image') ax[1].imshow(imgStackProcesses) ax[1].set_title('Frangi filter processes') ax[2].imshow(imgStackSoma) ax[2].set_title('Frangi filter soma') fig2, ax2 = plt.subplots(ncols = 3) ax2[0].imshow(showThreshStack) ax2[0].set_title('ThreshStack') ax2[1].imshow(bigOnlyShow) ax2[1].set_title('No small') ax2[2].imshow(lab) ax2[2].set_title("labeled image") plt.show()""" """## get list of unique labels
def enhance_vessels(self, image=None): assert (isinstance(image, np.ndarray)) assert (image.ndim <= 3) if image.dtype != np.float32: image = img_as_float32(image) vessel_filtered_image = frangi(image=image, sigmas=self.sigmas, alpha=self.alpha, beta=self.beta, gamma=self.gamma, black_ridges=False) print('Max intensity for vesselness output = {}'.format( np.amax(vessel_filtered_image))) # Exclude extremal slices while calculating maximum max_vesselness_response = np.amax(vessel_filtered_image[:, :, :-10]) thresh_value = 0.8 * max_vesselness_response # Use the threshold to create a binary mask vesselMask = np.where(vessel_filtered_image >= thresh_value, 1, 0).astype(np.uint8) speedR3 = 1 + self.lmbda * np.power(vessel_filtered_image, self.p) post_proc_img = np.array(speedR3, dtype=np.float32) return post_proc_img, vesselMask
def get_blood_vessels(image, mask): image = np.array(image) image = resize(image, None, fx=0.7, fy=0.7) mask = np.asarray(mask) mask = resize(mask, None, fx=0.7, fy=0.7) mask = mask[:, :, 1] # r=0 g b=0 image[:, :, [0, 2]] = 0 green = image[:, :, 1] green = contrast_stretching(green) # green = equalize_hist(green) green = frangi(green) # green = contrast_stretching(green) green = equalize_hist(green) green = np.asarray(green) # p = 0.06 # for contrast_stretching p = 0.92 # for equalize_hist print("sdsd") green[green > p] = 1 green[green <= p] = 0 res = bitwise_and(green, green, mask=mask) return res
def frangi_enhancement(image, scale_range=(1, 10), scale_step=2, beta1=0.5, beta2=15, black_ridges=False): ''' This filter can be used to detect continuous edges on a 2D image e.g. vessels, wrinkles, rivers. It can be used to calculate the fraction of the whole image containing such objects. :param image: :param scale_range:The range of sigmas used. A larger Sigma will decrease the identification of noise or small structures as vessels. :param scale_step:float, optional Step size between sigmas. :param beta1:float, optional :param beta2:beta2 : float, optional :param black_ridges: the filter detects black ridges; when False, it detects white ridges. :return: ''' result = frangi(image, scale_range=scale_range, scale_step=scale_step, beta1=beta1, beta2=beta2, black_ridges=black_ridges) return result
def getVesselnessImage(volume, segmentation): """ Calculate a Vessel probabilty map by applying Frangi's algorithm. See: https://link.springer.com/chapter/10.1007/BFb0056195 Steps: 1) Min projection between ILM and RPE 2) Median filtering the image 2) Vesselness filtering with scale 1..10 (step 1), beta1=0.5, beta2=0.005 Parameters ---------- volume: ndarray oct volume segmentation: ndarray segmentation volume Returns ---------- result: ndarray, int32 2D image of RPEDC distances """ result = median_filter(getProjectionILMRPE(volume, segmentation, 'min', True), size=5, mode='reflect') return (frangi( result, scale_range=(1, 10), scale_step=1, beta1=0.5, beta2=0.005) * 255).astype('uint8')
def inference(self, x_img): if self.parameter is None: return x_img x_img = 255 * x_img x_img = frangi(x_img) x_img = normalize(x_img) return x_img
def process_image(red, green, blue, mask): mask = np.asarray(mask) mask = mask[:, :, 1] red = rescale_intensity(red, in_range=(red.min(), red.max())) green = equalize_adapthist(green) plt.imshow(green, cmap="gray") plt.show() lowpass = ndimage.gaussian_filter(green, 20) green = green - lowpass green = rescale_intensity(green, in_range=(green.min(), green.max())) plt.imshow(green, cmap="gray") plt.show() fran = frangi(green, scale_range=(0, 6), scale_step=1) res1 = np.asarray(fran) # res1 = fran plt.imshow(res1, cmap="gray") plt.show() thresh = threshold_triangle(res1) res2 = res1 >= thresh res2 = remove_small_objects(res2, 30, 20) res2[mask == 0] = 0 result = np.zeros_like(res2) result[res2] = 1 # result[mask == 0] = 0 plt.imshow(res2, cmap="gray") plt.show() return result
def run(self, ips, imgs, para=None): imgs[:] = frangi(imgs, range(para['start'], para['end'], para['step']), alpha=para['alpha'], beta=para['beta'], gamma=para['gamma'], black_ridges=para['bridges'])
def run(self, ips, snap, img, para=None): rst = frangi(snap, range(para['start'], para['end'], para['step']), alpha=para['alpha'], beta=para['beta'], gamma=para['gamma'], black_ridges=para['bridges'])
def simple(image): kernel_ero = np.ones((3, 3), np.uint8) kernel_open = np.ones((11, 11), np.uint8) kernel_dil = np.ones((6, 6), np.uint8) maskO = mask(image) image = image[:, :, 1] image = cv2.GaussianBlur(image, (3, 3), 0) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(3, 3)) image = clahe.apply(image) image = frangi(image) image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX) image = np.uint8(image) image = cv2.erode(image, kernel_ero, iterations=1) image = image * maskO image = cv2.normalize(image, None, 0, 1, cv2.NORM_MINMAX) image[image >= 0.9] = 1 image[image < 0.1] = 0 return image
def segmentBloodVessel(self, image): ''' Performs segmentation of the blood vessels in the retina image. :param image: Input image. -- shape (1636, 1536, 3) :return: Segmented binary image. -- shape (1636, 1536) ''' grey_image = color.rgb2gray(image) # Apply median filter in order to decrease noise. median = filters.median(grey_image) # Apply CLAHE to enhance contrast. clahe = exposure.equalize_adapthist(median) # Apply the frangi filter on the preprocessed image in order to find vessel structures. out = filters.frangi(clahe, sigmas=range(4, 9, 1)) # Thresholding with the frangi filtered image to create binary. mask = np.where(out >= 1e-5) out[mask] = 1 # Cut of the black caption on the bottom of the image. roi = np.zeros((grey_image.shape), dtype=bool) roi[50:1525, 50:1510] = True out[~roi] = 0 # Apply an morphological opening to decrease noise. erosion = cv2.erode(out, np.ones((3, 3), np.uint8), iterations=1) result = cv2.dilate(erosion, np.ones((3, 3), np.uint8), iterations=1) return (result)
def run(self, ips, imgs, para=None): IPy.show_img( frangi(imgs, range(para['start'], para['end'], para['step']), alpha=para['alpha'], beta=para['beta'], gamma=para['gamma'], black_ridges=para['bridges']), ips.title + '-frangi')
def compute_frangi(img, params): frangi_scale_range = make_tuple(params.get("frangi_scale_range", "(1, 10)")) frangi_scale_step = float(params.get("frangi_scale_step", 2)) frangi_beta1 = float(params.get("frangi_beta1", .5)) frangi_beta2 = float(params.get("frangi_beta2", 15)) frangi_black_ridges = strtobool(params.get("frangi_black_ridges", "True")) feat = frangi(rgb2gray(img), scale_range = frangi_scale_range, scale_step =frangi_scale_step, beta =frangi_beta1, gamma=frangi_beta2, black_ridges =frangi_black_ridges) return feat[:, :, None] # add singleton dimension
def apply(self, c): if self.filter_name == "frangi": return frangi(c) if self.filter_name == "hessian": return hessian(c) if self.filter_name == "sato": return sato(c) raise ValueError("FilterName - {} - not known".format( self.filter_name))
def roiWise(s, params): name = params.get("name", "classTask") print("\tpixelWise:\t", name, end="") level = int(params.get("level", 1)) win_size = int(params.get("win_size", 2048)) #the size of the ROI which will be iteratively considered osh = s["os_handle"] dim_base = osh.level_dimensions[0] dims = osh.level_dimensions[level] ratio_x = dim_base[0] / dims[0] #figure out the difference between desi ratio_y = dim_base[1] / dims[1] frangi_scale_range = (1, 6) frangi_scale_step = 2 frangi_beta1 = .5 frangi_beta2 = 100 frangi_black_ridges = True mask = [] for x in range(0, dim_base[0], round(win_size * ratio_x)): row_piece = [] print('.', end='', flush=True) for y in range(0, dim_base[1], round(win_size * ratio_y)): region = np.asarray(osh.read_region((x, y), 1, (win_size, win_size))) region = region[:, :, 0:3] # remove alpha channel g = rgb2gray(region) feat = frangi(g, frangi_scale_range, frangi_scale_step, frangi_beta1, frangi_beta2, frangi_black_ridges) feat = feat / 8.875854409275627e-08 region_mask = np.bitwise_and(g < .3, feat > 5) region_mask = remove_small_objects(region_mask, min_size=100, in_place=True) # region_std = region.std(axis=2) # region_gray = rgb2gray(region) # region_mask = np.bitwise_and(region_std < 20, region_gray < 100/255) # region_mask = scipy.ndimage.morphology.binary_dilation(region_mask, iterations=1) # region_mask = resize(region_mask , (region_mask.shape[0] / 2, region_mask.shape[1] / 2)) row_piece.append(region_mask) row_piece = np.concatenate(row_piece, axis=0) mask.append(row_piece) mask = np.concatenate(mask, axis=1) if params.get("area_thresh", "") != "": mask = remove_small_objects(mask, min_size=int(params.get("area_thresh", "")), in_place=True) s.addToPrintList(name, str(mask.mean())) #TODO, migrate to printMaskHelper, but currently don't see how this output affects final mask #s.addToPrintList(name, # printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask, s["img_mask_use"])) io.imsave(s["outdir"] + os.sep + s["filename"] + "_BubbleBounds.png", img_as_ubyte(mask)) #.astype(np.uint8) * 255) return
def filterFunc(self, image): NScales = int( (self.properties['SMax'].val - self.properties['SMin'].val) / float(self.properties['NScales'].val)) NScales = np.max([NScales, 1]) edges = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) edges = frangi(edges, scale_range = (self.properties['SMin'].val,self.properties['SMax'].val),\ scale_step = NScales) return cv2.convertScaleAbs(255 * edges / np.max(edges))
def test_2d_null_matrix(): a_black = np.zeros((3, 3)).astype(np.uint8) a_white = invert(a_black) zeros = np.zeros((3, 3)) ones = np.ones((3, 3)) assert_equal(meijering(a_black, black_ridges=True), ones) assert_equal(meijering(a_white, black_ridges=False), ones) assert_equal(sato(a_black, black_ridges=True), zeros) assert_equal(sato(a_white, black_ridges=False), zeros) assert_allclose(frangi(a_black, black_ridges=True), zeros, atol=1e-3) assert_allclose(frangi(a_white, black_ridges=False), zeros, atol=1e-3) assert_equal(hessian(a_black, black_ridges=False), ones) assert_equal(hessian(a_white, black_ridges=True), ones)
def test_2d_cropped_camera_image(): a_black = crop(camera(), ((206, 206), (206, 206))) a_white = invert(a_black) zeros = np.zeros((100, 100)) ones = np.ones((100, 100)) assert_allclose(meijering(a_black, black_ridges=True), meijering(a_white, black_ridges=False)) assert_allclose(sato(a_black, black_ridges=True), sato(a_white, black_ridges=False)) assert_allclose(frangi(a_black, black_ridges=True), zeros, atol=1e-3) assert_allclose(frangi(a_white, black_ridges=False), zeros, atol=1e-3) assert_allclose(hessian(a_black, black_ridges=True), ones, atol=1 - 1e-7) assert_allclose(hessian(a_white, black_ridges=False), ones, atol=1 - 1e-7)
def test_3d_null_matrix(): # Note: last axis intentionally not size 3 to avoid 2D+RGB autodetection # warning from an internal call to `skimage.filters.gaussian`. a_black = np.zeros((3, 3, 5)).astype(np.uint8) a_white = invert(a_black) zeros = np.zeros((3, 3, 5)) ones = np.ones((3, 3, 5)) assert_allclose(meijering(a_black, black_ridges=True), zeros, atol=1e-1) assert_allclose(meijering(a_white, black_ridges=False), zeros, atol=1e-1) assert_equal(sato(a_black, black_ridges=True, mode='reflect'), zeros) assert_equal(sato(a_white, black_ridges=False, mode='reflect'), zeros) assert_allclose(frangi(a_black, black_ridges=True), zeros, atol=1e-3) assert_allclose(frangi(a_white, black_ridges=False), zeros, atol=1e-3) assert_equal(hessian(a_black, black_ridges=False, mode='reflect'), ones) assert_equal(hessian(a_white, black_ridges=True, mode='reflect'), ones)
def find_all_bounding_boxes(I, min_size=500, max_size=1e6, cost_thresh=100): print('Finding bounding boxes...') g = filters.frangi(I) T = filters.threshold_li(g) bw = g > T bw = closing(bw, disk(5)) skel = morphology.skeletonize(bw) region_labels = label(skel) props = regionprops(region_labels) for ii in range(np.max(region_labels)): region = props[ii] if (props[ii].convex_area < min_size) or (props[ii].bbox_area > max_size): skel[region_labels == (ii + 1)] = 0 region_labels = label(skel) props = regionprops(region_labels) cost = np.array([get_ellipse_fit_cost(r) for r in props]) for ii in range(np.max(region_labels)): region = props[ii] if cost[ii] > cost_thresh: skel[region_labels == (ii + 1)] = 0 region_labels = label(skel) props = regionprops(region_labels) bounding_box_dict = defaultdict() if plot_tgl: plt.imshow(I) ax = plt.gca() for ii, region in enumerate(props): box = region.bbox bounding_box_dict[ii] = box #Plot if plot_tgl: coord = box[:2][::-1] w = box[3] - box[1] h = box[2] - box[0] rect = patches.Rectangle(coord, w, h, linewidth=2, edgecolor='r', facecolor='none') ax.add_patch(rect) if plot_tgl: plt.show() return (bounding_box_dict)
def test_3d_cropped_camera_image(): a_black = crop(camera(), ((200, 212), (100, 312))) a_black = np.dstack([a_black, a_black, a_black]) a_white = invert(a_black) zeros = np.zeros((100, 100, 3)) ones = np.ones((100, 100, 3)) assert_allclose(meijering(a_black, black_ridges=True), meijering(a_white, black_ridges=False)) assert_allclose(sato(a_black, black_ridges=True, mode='reflect'), sato(a_white, black_ridges=False, mode='reflect')) assert_allclose(frangi(a_black, black_ridges=True), zeros, atol=1e-3) assert_allclose(frangi(a_white, black_ridges=False), zeros, atol=1e-3) assert_allclose(hessian(a_black, black_ridges=True, mode='reflect'), ones, atol=1 - 1e-7) assert_allclose(hessian(a_white, black_ridges=False, mode='reflect'), ones, atol=1 - 1e-7)
def frangiFilter(): global filterimage imgFilter9 = filters.frangi(img, sigmas=range(1, 10, 2), scale_range=None, scale_step=None, alpha=0.5, beta=0.5, gamma=15, black_ridges=True, mode='reflect', cval=0) filterimage = imgFilter9 io.imshow(imgFilter9) io.show()
def generateFrangiData(dataPath): path = Path(dataPath) for subset in path.iterdir(): print(subset.name) if not subset.name in ['train', 'val']: continue for item in subset.iterdir(): print(item.name) if not item.is_dir(): # item is a image imageName = item.name image = cv2.imread(dataPath + '/' + subset.name +'/' + item.name, 0) labImage = upContrast(image) processedImage = cv2.cvtColor(labImage, cv2.COLOR_LAB2BGR) filtered = frangi(cv2.cvtColor(processedImage, cv2.COLOR_BGR2GRAY), beta=1.0, gamma=0.1) filtered = img_as_ubyte(filtered) skimage.io.imsave(dataPath + '/' + subset.name +'_new/' + item.name, filtered)
def filter_frangi(a_stack, kwargs, scale_max=True, p_out=None): a_frangi = np.zeros(a_stack.shape, dtype='float32') for ix_slice, a_slice in enumerate(a_stack): a_frangi[ix_slice] = frangi(a_slice, **kwargs) if scale_max: if np.max(a_frangi) > 0: a_frangi = a_frangi * (10000 / np.max(a_frangi)) if p_out: with warnings.catch_warnings(): p_out.parent.mkdir(parents=True, exist_ok=True) imsave_fiji(p_out, a_frangi.astype('float32')) return a_frangi
def master_control(image): # image = cv2.resize(image, (int(image.shape[1]*0.3), int(image.shape[0]*0.3)), interpolation=cv2.INTER_CUBIC) # 图片分辨率很大是要变小 b, g, r = cv2.split(image) # image sk_frangi_img = frangi( g, scale_range=(0, 1), scale_step=0.01, beta1=1.5, beta2=0.01) # 线宽范围,步长,连接程度(越大连接越多),减少程度(越大减得越多)0.015 sk_frangi_img = morphology.closing(sk_frangi_img, morphology.disk(1)) sk_gabor_img_1, sk_gabor_1 = gabor(g, frequency=0.35, theta=0) sk_gabor_img_2, sk_gabor_2 = gabor(g, frequency=0.35, theta=45) # 越小越明显 sk_gabor_img_3, sk_gabor_3 = gabor(g, frequency=0.35, theta=90) sk_gabor_img_4, sk_gabor_4 = gabor(g, frequency=0.35, theta=360) # 横向皱纹 sk_gabor_img_1 = morphology.opening(sk_gabor_img_1, morphology.disk(2)) sk_gabor_img_2 = morphology.opening(sk_gabor_img_2, morphology.disk(1)) sk_gabor_img_3 = morphology.opening(sk_gabor_img_3, morphology.disk(2)) sk_gabor_img_4 = morphology.opening(sk_gabor_img_4, morphology.disk(2)) all_img = cv2.add( 0.1 * sk_gabor_img_2, 0.9 * sk_frangi_img ) # + 0.02 * sk_gabor_img_1 + 0.02 * sk_gabor_img_2 + 0.02 * sk_gabor_img_3 all_img = morphology.closing(all_img, morphology.disk(1)) _, all_img = cv2.threshold(all_img, 0.3, 1, 0) img1 = all_img # print(all_img, all_img.shape, type(all_img)) # contours, image_cont = cv2.findContours(all_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # all_img = all_img + image_cont bool_img = all_img.astype(bool) label_image = measure.label(bool_img) count = 0 for region in measure.regionprops(label_image): if region.area < 10: # or region.area > 700 x = region.coords for i in range(len(x)): all_img[x[i][0]][x[i][1]] = 0 continue if region.eccentricity > 0.98: count += 1 else: x = region.coords for i in range(len(x)): all_img[x[i][0]][x[i][1]] = 0 skel, distance = morphology.medial_axis(all_img.astype(int), return_distance=True) skels = morphology.closing(skel, morphology.disk(1)) trans1 = skels # 细化 return skels, count # np.uint16(skels.astype(int))
def test_energy_decrease(): a = np.zeros((5, 5)) a[2, 2] = 1. assert frangi(a).std() < a.std() assert frangi(a, black_ridges=False).std() < a.std() assert hessian(a).std() > a.std()
Frangi filter ============= The Frangi and hybrid Hessian filters can be used to detect continuous edges, such as vessels, wrinkles, and rivers. """ from skimage.data import camera from skimage.filters import frangi, hessian import matplotlib.pyplot as plt image = camera() fig, ax = plt.subplots(ncols=3) ax[0].imshow(image, cmap=plt.cm.gray) ax[0].set_title('Original image') ax[1].imshow(frangi(image), cmap=plt.cm.gray) ax[1].set_title('Frangi filter result') ax[2].imshow(hessian(image), cmap=plt.cm.gray) ax[2].set_title('Hybrid Hessian filter result') for a in ax: a.axis('off') plt.tight_layout() plt.show()
def frangi_segmentation(image, colors, frangi_args, threshold_args, separate_objects=True, contrast_kernel_size='skip', color_args_1='skip', color_args_2='skip', color_args_3='skip', neighborhood_args='skip', morphology_args_1='skip', morphology_args_2='skip', hollow_args='skip', fill_gaps_args='skip', diameter_args='skip', diameter_bins='skip', image_name='image', verbose=False): """ Possible approach to object detection using frangi filters. Selects colorbands for analysis, runs frangi filter, thresholds to identify candidate objects, then removes spurrious objects by color and morphology characteristics. See frangi_approach.ipynb. Unless noted, the dictionaries are called by their respective functions in order. Parameters ---------- image : ndarray RGB image to analyze colors : dict or str Parameters for picking the colorspace. See `pyroots.band_selector`. frangi_args : list of dict or dict Parameters to pass to `skimage.filters.frangi` threshold_args : list of dict or dict Parameters to pass to `skimage.filters.threshold_adaptive` contrast_kernel_size : int, str, or None Kernel size for `skimage.exposure.equalize_adapthist`. If `int`, then gives the size of the kernel used for adaptive contrast enhancement. If `None`, uses default (1/8 shortest image dimension). If `skip`, then skips. color_args_1 : dict Parameters to pass to `pyroots.color_filter`. color_args_2 : dict Parameters to pass to `pyroots.color_filter`. Combines with color_args_1 in an 'and' statement. color_args_3 : dict Parameters to pass to `pyroots.color_filter`. Combines with color_args_1, 2 in an 'and' statement. neighborhood_args : dict Parameters to pass to 'pyroots.neighborhood_filter'. morphology_args_1 : dict Parameters to pass to `pyroots.morphology_filter` morphology_args_2 : dict Parameters to pass to `pyroots.morphology_filter`. Happens after fill_gaps_args in the algorithm. hollow_args : dict Parameters to pass to `pyroots.hollow_filter` fill_gaps_args : dict Paramaters to pass to `pyroots.fill_gaps` diameter_bins : list To pass to `pyroots.bin_by_diameter` image_name : str Identifier of image for summarizing Returns ------- A dictionary containing: 1. `"geometry"` summary `pandas.DataFrame` 2. `"objects"` binary image 3. `"length"` medial axis image 4. `"diameter"` medial axis image """ # Pull band from colorspace working_image = band_selector(image, colors) # expects dictionary (lazy coding) nbands = len(working_image) if verbose is True: print("Color bands selected") ## Count nubmer of dictionaries in threshold_args and frangi_args. Should equal number of bands. Convert to list if necessary try: len(threshold_args[0]) except: threshold_args = [threshold_args] if nbands != len(threshold_args): raise ValueError( """Number of dictionaries in `threshold_args` doesn't equal the number of bands in `colors['band']`!""" ) pass try: len(frangi_args[0]) except: frangi_args = [frangi_args] if nbands != len(frangi_args): raise ValueError( """Number of dictionaries in `frangi_args` doesn't equal the number of bands in `colors['band']`!""" ) pass working_image = [img_as_float(i) for i in working_image] # Contrast enhancement try: for i in range(nbands): temp = exposure.equalize_adapthist(working_image[i], kernel_size = contrast_kernel_size) working_image[i] = img_as_float(temp) if verbose: print("Contrast enhanced") except: if contrast_kernel_size is not 'skip': warn('Skipping contrast enhancement') pass # invert if necessary for i in range(nbands): if not colors['dark_on_light'][i]: working_image[i] = 1 - working_image[i] # Identify smoothing sigma for edges and frangi thresholding # simultaneously detect edges (computationally cheaper than multiple frangi enhancements) edges = [np.ones_like(working_image[0]) == 1] * nbands # all True sigma_val = [0.125] * nbands # step is 0, 0.25, 0.5, 1, 2, 4, 8, 16 for i in range(nbands): edge_val = 1 while edge_val > 0.1 and sigma_val[i] < 10: sigma_val[i] = 2*sigma_val[i] temp = filters.gaussian(working_image[i], sigma=sigma_val[i]) temp = filters.scharr(temp) temp = temp > filters.threshold_otsu(temp) edge_val = np.sum(temp) / np.sum(np.ones_like(temp)) edges_temp = temp.copy() if sigma_val[i] == 0.25: # try without smoothing temp = filters.scharr(working_image[i]) temp = temp > filters.threshold_otsu(temp) edge_val = np.sum(temp) / np.sum(np.ones_like(temp)) if edge_val <= 0.1: sigma_val[i] = 0 edges_temp = temp.copy() if separate_objects: edges[i] = morphology.skeletonize(edges_temp) if verbose: print("Sigma value: {}".format(sigma_val)) if separate_objects: print("Edges found") # Frangi vessel enhancement for i in range(nbands): temp = filters.gaussian(working_image[i], sigma=sigma_val[i]) temp = filters.frangi(temp, **frangi_args[i]) temp = 1 - temp/np.max(temp) temp = temp < filters.threshold_local(temp, **threshold_args[i]) working_image[i] = temp.copy() frangi = working_image.copy() if verbose: print("Frangi filter, threshold complete") # Combine bands, separate objects combined = working_image[0] * ~edges[0] for i in range(1, nbands): combined = combined * working_image[i] * ~edges[i] working_image = combined.copy() # Filter candidate objects by color try: color1 = color_filter(image, working_image, **color_args_1) #colorspace, target_band, low, high, percent) if verbose: print("Color filter 1 complete") except: if color_args_1 is not 'skip': warn("Skipping Color Filter 1") color1 = np.ones(working_image.shape) # no filtering try: color2 = color_filter(image, working_image, **color_args_2) # nesting equates to an "and" statement. if verbose: print("Color filter 2 complete") except: if color_args_2 is not 'skip': warn("Skipping Color Filter 2") color2 = np.ones(working_image.shape) # no filtering try: color3 = color_filter(image, working_image, **color_args_3) # nesting equates to an "and" statement. if verbose: print("Color filter 3 complete") except: if color_args_3 is not 'skip': warn("Skipping Color Filter 3") color3 = np.ones(working_image.shape) # no filtering # Combine bands working_image = color1 * color2 * color3 del color1 del color2 del color3 # Re-expand to area if separate_objects: # find edges removed temp = [frangi[i] * edges[i] for i in range(nbands)] rm_edges = temp[0].copy() for i in range(1, nbands): rm_edges = rm_edges * temp[i] # filter by color per criteria above try: color1 = color_filter(image, rm_edges, **color_args_1) except: color1 = np.ones(rm_edges.shape) try: color2 = color_filter(image, rm_edges, **color_args_2) except: color2 = np.ones(rm_edges.shape) try: color3 = color_filter(image, rm_edges, **color_args_3) except: color3 = np.ones(rm_edges.shape) # Combine color filters expanded = color1 * color2 * color3 else: expanded = np.zeros(colorfilt.shape) == 1 # evaluate to false working_image = expanded ^ working_image # bitwise or try: # remove little objects (for computational efficiency) working_image = morphology.remove_small_objects( working_image, min_size=morphology_args_1['min_size'] ) except: pass if verbose: print("Edges re-added") # Filter candidate objects by morphology try: working_image = morphology_filter(working_image, **morphology_args_1) if verbose: print("Morphology filter 1 complete") except: if morphology_args_1 is not 'skip': warn("Skipping morphology filter 1") pass # Filter objects by neighborhood colors try: working_image = neighborhood_filter(image, working_image, **neighborhood_args) if verbose: print("Neighborhood filter complete") except: if neighborhood_args is not 'skip': warn("Skipping neighborhood filter") pass # Filter candidate objects by hollowness if hollow_args is not 'skip': temp = morphology.remove_small_holes(working_image, min_size=10) try: if np.sum(temp) > 0: working_image = hollow_filter(temp, **hollow_args) if verbose: print("Hollow filter complete") except: warn("Skipping hollow filter") pass # Close small gaps and holes in accepted objects try: working_image = fill_gaps(working_image, **fill_gaps_args) if verbose: print("Gap filling complete") except: if fill_gaps_args is not 'skip': warn("Skipping filling gaps") pass # Filter candidate objects by morphology try: working_image = morphology_filter(working_image, **morphology_args_2) if verbose: print("Morphology filter 2 complete") except: if morphology_args_2 is not 'skip': warn("Skipping morphology filter 2") pass # Skeletonize. Now working with a dictionary of objects. skel = skeleton_with_distance(working_image) if verbose: print("Skeletonization complete") # Diameter filter try: diam = diameter_filter(skel, **diameter_args) if verbose: print("Diameter filter complete") except: diam = skel.copy() if diameter_args is not 'skip': warn("Skipping diameter filter") pass # Summarize if diameter_bins is None or diameter_bins is 'skip': summary_df = summarize_geometry(diam['geometry'], image_name) else: diam_out, summary_df = bin_by_diameter(diam['length'], diam['diameter'], diameter_bins, image_name) diam['diameter'] = diam_out out = {'geometry' : summary_df, 'objects' : diam['objects'], 'length' : diam['length'], 'diameter' : diam['diameter']} if verbose is True: print("Done") return(out)
def test_values_decreased(): a = np.multiply(np.ones((3, 3)), 10) assert_equal(frangi(a), np.zeros((3, 3))) assert_equal(hessian(a), np.ones((3, 3)))
def test_cropped_camera_image(): image = crop(camera(), ((206, 206), (206, 206))) assert_allclose(frangi(image), np.zeros((100, 100)), atol=1e-03) assert_allclose(frangi(image, black_ridges=True), np.zeros((100, 100)), atol=1e-03) assert_allclose(hessian(image), np.ones((100, 100)), atol=1-1e-07)
def test_null_matrix(): a = np.zeros((3, 3)) assert_almost_equal(frangi(a), np.zeros((3, 3))) assert_almost_equal(frangi(a, black_ridges=False), np.zeros((3, 3))) assert_equal(hessian(a), np.ones((3, 3)))