def enhance_ridges(frame, mask=None): """Detect ridges (larger hessian eigenvalue)""" blurred = filters.gaussian_filter(frame, 2) Hxx, Hxy, Hyy = feature.hessian_matrix(blurred, sigma=4.5, mode="nearest") ridges = feature.hessian_matrix_eigvals(Hxx, Hxy, Hyy)[0] return np.abs(ridges)
def enhance_ridges(frame): """A ridge detection filter (larger hessian eigenvalue)""" blurred = filters.gaussian_filter(frame, 2) sigma = 4.5 Hxx, Hxy, Hyy = feature.hessian_matrix(blurred, sigma=sigma, mode='nearest') ridges = feature.hessian_matrix_eigvals(Hxx, Hxy, Hyy)[0] return np.abs(ridges)
def multiscale_seed_sequence(prob, l1_threshold=0, grid_density=10): npoints = ((prob.shape[1] // grid_density) * (prob.shape[2] // grid_density)) seeds = np.zeros(prob.shape, dtype=int) for seed, p in zip(seeds, prob): hm = feature.hessian_matrix(p, sigma=3) l1, l2 = feature.hessian_matrix_eigvals(*hm) curvy = (l1 > l1_threshold) seed[:] = multiscale_regular_seeds(curvy, npoints) return seeds
def test_hessian_matrix_eigvals(): square = np.zeros((5, 5)) square[2, 2] = 1 Hxx, Hxy, Hyy = hessian_matrix(square, sigma=0.1) l1, l2 = hessian_matrix_eigvals(Hxx, Hxy, Hyy) assert_array_equal( l1, np.array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) ) assert_array_equal( l2, np.array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) )
def test_hessian_matrix_eigvals(): square = np.zeros((5, 5)) square[2, 2] = 4 Hrr, Hrc, Hcc = hessian_matrix(square, sigma=0.1, order='rc') l1, l2 = hessian_matrix_eigvals(Hrr, Hrc, Hcc) assert_almost_equal(l1, np.array([[0, 0, 2, 0, 0], [0, 1, 0, 1, 0], [2, 0, -2, 0, 2], [0, 1, 0, 1, 0], [0, 0, 2, 0, 0]])) assert_almost_equal(l2, np.array([[0, 0, 0, 0, 0], [0, -1, 0, -1, 0], [0, 0, -2, 0, 0], [0, -1, 0, -1, 0], [0, 0, 0, 0, 0]]))
def _features_sigma(img, sigma, intensity=True, edges=True, texture=True): """Features for a single value of the Gaussian blurring parameter ``sigma`` """ features = [] img_blur = filters.gaussian(img, sigma) if intensity: features.append(img_blur) if edges: features.append(filters.sobel(img_blur)) if texture: H_elems = [ np.gradient(np.gradient(img_blur)[ax0], axis=ax1) for ax0, ax1 in combinations_with_replacement(range(img.ndim), 2) ] eigvals = feature.hessian_matrix_eigvals(H_elems) for eigval_mat in eigvals: features.append(eigval_mat) return features
def test_hessian_matrix_eigvals_3d(im3d): H = hessian_matrix(im3d) E = hessian_matrix_eigvals(H) # test descending order: e0, e1, e2 = E assert np.all(e0 >= e1) and np.all(e1 >= e2) E0, E1, E2 = E[:, E.shape[1] // 2] # cross section row_center, col_center = np.array(E0.shape) // 2 circles = [draw.circle_perimeter(row_center, col_center, radius, shape=E0.shape) for radius in range(1, E0.shape[1] // 2 - 1)] response0 = np.array([np.mean(E0[c]) for c in circles]) response2 = np.array([np.mean(E2[c]) for c in circles]) # eigenvalues are negative just inside the sphere, positive just outside assert np.argmin(response2) < np.argmax(response0) assert np.min(response2) < 0 assert np.max(response0) > 0
def test_hessian_matrix_eigvals(dtype): square = np.zeros((5, 5), dtype=dtype) square[2, 2] = 4 H = hessian_matrix(square, sigma=0.1, order='rc', use_gaussian_derivatives=False) l1, l2 = hessian_matrix_eigvals(H) out_dtype = _supported_float_type(dtype) assert all(a.dtype == out_dtype for a in (l1, l2)) assert_almost_equal( l1, np.array([[0, 0, 2, 0, 0], [0, 1, 0, 1, 0], [2, 0, -2, 0, 2], [0, 1, 0, 1, 0], [0, 0, 2, 0, 0]])) assert_almost_equal( l2, np.array([[0, 0, 0, 0, 0], [0, -1, 0, -1, 0], [0, 0, -2, 0, 0], [0, -1, 0, -1, 0], [0, 0, 0, 0, 0]]))
def eigValues(sigmas, flat_nodule): #já não é preciso fazer o filtro gaussiano porque esta função faz #(Hrr, Hrc, Hcc) = hessian_matrix(flat_nodule, sigma=sigma, order='rc') #eigValues = hessian_matrix_eigvals((Hrr, Hrc, Hcc)) eigValues = [] h_elem_aux = [] h_elem_max = () for s in sigmas: #já não é preciso fazer o filtro gaussiano porque esta função faz #para os vários sigmas usados vamos guardar apenas o tuplo com os maiores valores de hrr, hrc, hcc (Hrr, Hrc, Hcc) = hessian_matrix(flat_nodule, sigma=s, order='rc') h_elem_aux.append((Hrr, Hrc, Hcc)) for i in range(len(h_elem_aux) - 1): h_elem_max = np.maximum(h_elem_aux[i], h_elem_aux[i + 1]) eigValues = hessian_matrix_eigvals(h_elem_max) return eigValues
def maskedVesselSegmentation(array): image, binary = boneSegmentation(array, [1, 300]) kernel = np.ones((4, 4), np.float32) / 16 img = np.squeeze(np.uint8(binary)) img = cv2.filter2D(img, -1, kernel) img = cv2.erode(img, kernel, iterations=1) img = cv2.dilate(img, kernel, iterations=1) img = cv2.erode(img, kernel, iterations=1) img = frangi(img) hxx, hxy, hyy = hessian_matrix(img, sigma=3) i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy) img = i2 / abs(i2.max()) img = np.squeeze(np.uint8(img)) threshold = img.max() - img.mean() img = np.squeeze(np.uint8(img)) img = cv2.erode(img, kernel, iterations=1) img = np.squeeze(np.uint8(img)) img = cv2.dilate(img, kernel, iterations=1) threshold = img.max() - img.mean() image = np.where((img > threshold), 255, 0) return (image)
def process_image(img): """Process the image using Hessian filters.""" # img_orig = color.rgb2gray(img_orig) img = color.rgb2gray(img_orig) # Image is largest eigenvalue of Hessian. hxx, hxy, hyy = hessian_matrix(img, sigma=3, order="rc") i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy) Z = i1 border = 12 Z = Z[border:-border, border:-border] # Binarize the image. thresh = threshold_otsu(Z) alpha = 1 Z = np.abs(Z) img_ = img[border:-border, border:-border] thresh = threshold_otsu(Z) Z_ = Z > thresh return Z, Z_
def ridge_detection(img_pro, folder_pos, conf): img_cv2 = np.uint8(img_pro * 255.0) img_cv2[img_cv2 >= conf['rd_b_t']] = 255 Hxx, Hxy, Hyy = hessian_matrix(img_cv2, sigma=conf['rd_sigma_para'], order='xy') i1, i2 = hessian_matrix_eigvals(Hxx, Hxy, Hyy) i1[i1 <= conf['rd_threshold']] = 0.0 i1[i1 >= conf['rd_threshold']] = 1.0 pr = np.uint8(i1 * 255.0) kernel = np.ones((conf['rd_kernel_size'], conf['rd_kernel_size']), np.uint8) pr = cv2.erode(pr, kernel, iterations=1) / 255.0 base_fn = os.path.join(folder_pos, 'base.png') base_pr = 1.0 - cv2.imread(base_fn, cv2.IMREAD_GRAYSCALE) / 255.0 pr = np.maximum(pr, base_pr) output = pr2tensor(pr) return output
def test_hessian_matrix_eigvals_3d(im3d, dtype): im3d = im3d.astype(dtype, copy=False) H = hessian_matrix(im3d, use_gaussian_derivatives=False) E = hessian_matrix_eigvals(H) out_dtype = _supported_float_type(dtype) assert all(a.dtype == out_dtype for a in E) # test descending order: e0, e1, e2 = E assert np.all(e0 >= e1) and np.all(e1 >= e2) E0, E1, E2 = E[:, E.shape[1] // 2] # cross section row_center, col_center = np.array(E0.shape) // 2 circles = [ draw.circle_perimeter(row_center, col_center, radius, shape=E0.shape) for radius in range(1, E0.shape[1] // 2 - 1) ] response0 = np.array([np.mean(E0[c]) for c in circles]) response2 = np.array([np.mean(E2[c]) for c in circles]) # eigenvalues are negative just inside the sphere, positive just outside assert np.argmin(response2) < np.argmax(response0) assert np.min(response2) < 0 assert np.max(response0) > 0
def build_gradient(img, scale=0.15, delta=0, method='Scharr'): clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) if method == 'Sobel': grad_x = cv2.Sobel(img, cv2.CV_32F, 1, 0, scale=scale, delta=delta, borderType=cv2.BORDER_DEFAULT) grad_y = cv2.Sobel(img, cv2.CV_32F, 0, 1, scale=scale, delta=delta, borderType=cv2.BORDER_DEFAULT) abs_grad_x = cv2.convertScaleAbs(grad_x) abs_grad_y = cv2.convertScaleAbs(grad_y) grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0) grad = gradient_normalize(grad, q=0.001) elif method == 'Gauss': sigma = 1 sze = np.fix(6 * sigma) gauss = gaussian_kernel_1d(sigma, 0, np.int(sze) // 2) second = gaussian_kernel_1d(sigma, 2, np.int(sze) // 2) Gxx = (gauss.T * second) #[:, :, np.newaxis] Gyy = (gauss * second.T) #[:, :, np.newaxis] grad_x = cv2.filter2D(img, -1, Gxx) grad_y = cv2.filter2D(img, -1, Gyy) abs_grad_x = cv2.convertScaleAbs(grad_x) abs_grad_y = cv2.convertScaleAbs(grad_y) grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0) grad = gradient_normalize(grad, q=0.001) elif method == 'Laplacian': grad = cv2.Laplacian(img, cv2.CV_32F, ksize=3) elif method == 'Canny': grad = cv2.Canny(img.astype('uint8'), 125, 125) elif method == 'Ridge': H_elems = hessian_matrix(img, sigma=1 - scale, order='rc') maxima_ridges, minima_ridges = hessian_matrix_eigvals(H_elems) grad = minima_ridges grad = 255 - gradient_normalize(grad, q=0.001) else: grad_x = cv2.Scharr(img, cv2.CV_32F, 1, 0, scale=scale, delta=delta, borderType=cv2.BORDER_DEFAULT) grad_y = cv2.Scharr(img, cv2.CV_32F, 0, 1, scale=scale, delta=delta, borderType=cv2.BORDER_DEFAULT) abs_grad_x = cv2.convertScaleAbs(grad_x) abs_grad_y = cv2.convertScaleAbs(grad_y) grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0) grad = cv2.convertScaleAbs(grad) grad = grad.astype('uint8') grad = clahe.apply(grad) grad = grad.astype('float')**2 grad = grad / grad.max() * 255 grad = grad.reshape([*grad.shape, 1]) return grad.astype('uint8')
def computeStructureFeatures(Xdata, isTraining, path): path = path + '/structFeatures' print("\nComputing: All Structure Features") print("is Training? %r" %isTraining) start = time.time() # Separate color channel RChannel = Xdata[:,:,0] GChannel = Xdata[:,:,1] BChannel = Xdata[:,:,2] # Calculate Laplacian of Gaussian (sigma = 1.6) print("Computing: Laplacian of Gaussian") gaussianLF_R = gaussian_laplace(RChannel, 1.6) gaussianLF_G = gaussian_laplace(GChannel, 1.6) gaussianLF_B = gaussian_laplace(BChannel, 1.6) gaussianLF = np.dstack((gaussianLF_R, gaussianLF_G, gaussianLF_B)) gaussianLF = np.resize(gaussianLF, (gaussianLF.shape[0]*gaussianLF.shape[1], gaussianLF.shape[2])) end = time.time() if (isTraining): print("Computed: gaussianLapFeatures_Tr in %f seconds" %(end-start)) # with open('gaussianLapFeatures_Tr.pkl','wb') as outfile: # pickle.dump(gaussianLF, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/gaussianLapFeatures_Tr.csv", # gaussianLF, delimiter=",") else: print("Computed: gaussianLapFeatures_Ts in %f seconds" %(end-start)) # with open('gaussianLapFeatures_Ts.pkl','wb') as outfile: # pickle.dump(gaussianLF, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/gaussianLapFeatures_Ts.csv", # gaussianLF, delimiter=",") # Calculate eigenvalues of structure tensor (sigma =1.6, 3.5) print("Computing: eigenvalues of structure tensor") start = time.time() Axx_R1, Axy_R1, Ayy_R1 = structure_tensor(RChannel, sigma = 1.6) larger_R1, smaller_R1 = structure_tensor_eigvals(Axx_R1, Axy_R1, Ayy_R1) Axx_R2, Axy_R2, Ayy_R2 = structure_tensor(RChannel, sigma = 3.5) larger_R2, smaller_R2 = structure_tensor_eigvals(Axx_R2, Axy_R2, Ayy_R2) Axx_G1, Axy_G1, Ayy_G1 = structure_tensor(GChannel, sigma = 1.6) larger_G1, smaller_G1 = structure_tensor_eigvals(Axx_G1, Axy_G1, Ayy_G1) Axx_G2, Axy_G2, Ayy_G2 = structure_tensor(GChannel, sigma = 3.5) larger_G2, smaller_G2 = structure_tensor_eigvals(Axx_G2, Axy_G2, Ayy_G2) Axx_B1, Axy_B1, Ayy_B1 = structure_tensor(BChannel, sigma = 1.6) larger_B1, smaller_B1 = structure_tensor_eigvals(Axx_B1, Axy_B1, Ayy_B1) Axx_B2, Axy_B2, Ayy_B2 = structure_tensor(BChannel, sigma = 3.5) larger_B2, smaller_B2 = structure_tensor_eigvals(Axx_B2, Axy_B2, Ayy_B2) eigenST = np.dstack((larger_R1, smaller_R1, larger_R2, smaller_R2, larger_G1, smaller_G1, larger_G2, smaller_G2, larger_B1, smaller_B1, larger_B2, smaller_B2)) eigenST = np.resize(eigenST, (eigenST.shape[0]*eigenST.shape[1], eigenST.shape[2])) end = time.time() if (isTraining): print("Computed: eigenStructFeatures_Tr in %f seconds" %(end-start)) # with open('eigenStructFeatures_Tr.pkl','wb') as outfile: # pickle.dump(eigenST, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/eigenStructFeatures_Tr.csv", # eigenST, delimiter=",") else: print ("Computed: eigenStructFeatures_Ts in %f seconds" %(end-start)) # with open('eigenStructFeatures_Ts.pkl','wb') as outfile: # pickle.dump(eigenST, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/eigenStructFeatures_Ts.csv", # eigenST, delimiter=",") # Calculate eigenvalues of Hessian matrix print("Computing: eigenvalues of Hessian matrix") start = time.time() Hrr_R1, Hrc_R1, Hcc_R1 = hessian_matrix(RChannel, sigma = 1.6, order='rc') larger_R1, smaller_R1 = hessian_matrix_eigvals(Hrr_R1, Hrc_R1, Hcc_R1) Hrr_R2, Hrc_R2, Hcc_R2 = hessian_matrix(RChannel, sigma = 3.5, order='rc') larger_R2, smaller_R2 = hessian_matrix_eigvals(Hrr_R2, Hrc_R2, Hcc_R2) Hrr_G1, Hrc_G1, Hcc_G1 = hessian_matrix(GChannel, sigma = 1.6, order='rc') larger_G1, smaller_G1 = hessian_matrix_eigvals(Hrr_G1, Hrc_G1, Hcc_G1) Hrr_G2, Hrc_G2, Hcc_G2 = hessian_matrix(GChannel, sigma = 3.5, order='rc') larger_G2, smaller_G2 = hessian_matrix_eigvals(Hrr_G2, Hrc_G2, Hcc_G2) Hrr_B1, Hrc_B1, Hcc_B1 = hessian_matrix(BChannel, sigma = 1.6, order='rc') larger_B1, smaller_B1 = hessian_matrix_eigvals(Hrr_B1, Hrc_B1, Hcc_B1) Hrr_B2, Hrc_B2, Hcc_B2 = hessian_matrix(BChannel, sigma = 3.5, order='rc') larger_B2, smaller_B2 = hessian_matrix_eigvals(Hrr_B2, Hrc_B2, Hcc_B2) eigenHess = np.dstack((larger_R1, smaller_R1, larger_R2, smaller_R2, larger_G1, smaller_G1, larger_G2, smaller_G2, larger_B1, smaller_B1, larger_B2, smaller_B2)) eigenHess = np.resize(eigenHess, (eigenHess.shape[0]*eigenHess.shape[1], eigenHess.shape[2])) end = time.time() if (isTraining): print("Computed: eigenHessFeatures_Tr in %f seconds" % (end-start)) # with open('eigenHessFeatures_Tr.pkl','wb') as outfile: # pickle.dump(eigenHess, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/eigenHessFeatures_Tr.csv", # eigenHess, delimiter=",") else: print("Computed: eigenHessFeatures_Ts in %f seconds" % (end-start)) # with open('eigenHessFeatures_Ts.pkl','wb') as outfile: # pickle.dump(eigenHess, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/eigenHessFeatures_Ts.csv", # eigenHess, delimiter=",") # Calculate Gaussian gradient magnitude (sigma = 1.6) print("Computing: Gaussian gradient magnitude") start = time.time() gaussian_grad_R = gaussian_gradient_magnitude(RChannel, sigma = 1.6) gaussian_grad_G = gaussian_gradient_magnitude(GChannel, sigma = 1.6) gaussian_grad_B = gaussian_gradient_magnitude(BChannel, sigma = 1.6) gaussian_grad = np.dstack((gaussian_grad_R, gaussian_grad_G, gaussian_grad_B)) gaussian_grad = np.resize(gaussian_grad, (gaussian_grad.shape[0]*gaussian_grad.shape[1], gaussian_grad.shape[2])) end = time.time() if (isTraining): print("Computed: gaussianGradFeatures_Tr in %f seconds" % (end-start)) # with open('gaussianGradFeatures_Tr.pkl','wb') as outfile: # pickle.dump(gaussian_grad, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/gaussianGradFeatures_Tr.csv", # gaussian_grad, delimiter=",") else: print("Computed: gaussianGradFeatures_Ts in %f seconds" % (end-start)) # with open('gaussianGradFeatures_Ts.pkl','wb') as outfile: # pickle.dump(gaussian_grad, outfile, pickle.HIGHEST_PROTOCOL) # np.savetxt("/Users/wuwenjun/GitHub/CSE-577-Melanoma-Nuclei-Segmentation/gaussianGradFeatures_Ts.csv", # gaussian_grad, delimiter=",") All = np.concatenate((gaussianLF, eigenST, eigenHess, gaussian_grad),axis = 1) if (isTraining): path = path + '_Tr' np.savez_compressed(path, data = All) print("\nFINISHED: Structure Features for Training data\n") else: path = path + '_Ts' np.savez_compressed(path, data = All) print("\nFINISHED: Structure Features for Testing data\n")
def get_lcs(self, to_dataset=True): """ Extract points that sit on the dominant ridges of FTLE 2D data A ridge point is defined as a point, where the gradient vector is orthogonal to the eigenvector of the smallest (negative) eigenvalue of the Hessian matriv (curvature). The found points are filtered to extract only points on strong FTLE separatrices. Therefore points are only taken, if: a) FTLE value is high at the point's position b) the negative curvature is high Args: - eval_thrsh (str or float, optional): scalar. Selects zones with small Hessian eigenvalue smaller than eval_thrsh. use 'infer' to obtain the threshold from the 95 percentile of the data of the FTLE field. - FTLE_thrsh (str or float, optional): scalar. Selects connected areas (with 4 or 8 neighbors) larger than area_thrsh. use 'infer' to obtain the threshold from the 95 percentile of the data of the FTLE field. - area_thrsh (float, optional): scalar. Selects connected areas (with 4 or 8 neighbors) larger than area_thrsh - nr_neighb (int, optional): scalar. Connection neighbours (4 or 8) - ridge_points (bool, optional): x0,y0 exact ridge poisition if 1. (matrix coordinates) - to_dataset (bool, optional): Logical mask for ridges in the FTLE field LCS_forward and LCS_backward to the outputted dataset. Example: Define variables eval_thrsh = -0.005; # Selects zones with small Hessian eigenvalue smaller than eval_thrsh FTLE_thrsh = 0.07; # Selects zones with FTLE larger than FTLE_thrsh area_thrsh = 10; # Selects connected areas (with 4 or 8 neighbors) larger than area_thrsh nr_neighb = 8; # conection neighbours (4 or 8) Returns: combined_bin: logical mask for ridges in FTLE field x0: Positions of points on FTLE ridges y0: Positions of points on FTLE ridges """ if 'FTLE_forward' in self.lag_ftle.ds_output.keys(): ftle = self.lag_ftle.ds_output['FTLE_forward'].fillna( 0).squeeze().values m, n = ftle.shape elif 'FTLE_backward' in self.lag_ftle.ds_output.keys(): ftle = self.lag_ftle.ds_output['FTLE_backward'].fillna( 0).squeeze().values m, n = ftle.shape if self.ftle_thrsh == 'infer': self.ftle_thrsh = np.percentile(ftle, 95) # Gradient and Hessian matrix (2nd derivatives) from finite differences [dy, dx] = np.gradient(ftle) # Eigenvalues of Hessian matrix (analytically) # EVal = min( 1/2*(a+d) + sqrt(b.*c + 4*(a-d).^2), 1/2*(a+d) - sqrt(b.*c + 4*(a-d).^2) ); # psu = (a-EVal-c)./(d-EVal-b); # Smaller (negative) Eigenvector of Hessian matrix (analytically) # EVecx = 1./sqrt(1^2 + psu.^2); # EVecy = psu./sqrt(1^2 + psu.^2); # Make 2D hessian hxx, hxy, hyy = hessian_matrix(ftle, sigma=3) i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy) Lambda2 = np.zeros_like(hxx) Lambda1 = np.zeros_like(hxx) EVecx = np.zeros_like(hxx) EVecy = np.zeros_like(hxx) for i in range(0, m): for j in range(0, n): eigvalue, eigenvec = np.linalg.eigh( np.matrix([[hxx[i, j], hxy[i, j]], [hxy[i, j], hyy[i, j]]])) Lambda2[i, j], Lambda1[i, j], = eigvalue EVecx[i, j], EVecy[i, j] = eigenvec[1, 0], eigenvec[1, 1] EVal = np.minimum(Lambda2, Lambda1) EVal = np.nan_to_num(EVal) # Compute the direction of the minor eigenvector # Define ridges as zero level lines of inner product # of gradient and eigenvector of smaller (negative) eigenvalue ridge = EVecx * dx + EVecy * dy if self.eval_thrsh == 'infer': self.eval_thrsh = np.percentile(EVal, 95) # Define filter masks with high negative curvature Eval_neg_bin = EVal < self.eval_thrsh # High FTLE value FTLE_high_bin = ftle > self.ftle_thrsh # Combined mask combined_bin = FTLE_high_bin * Eval_neg_bin # Remove small connected areas in combined mask # label areas L = label(combined_bin, neighbors=self.nr_neighb) # filter mask Lmax = L.max() for i in range(1, Lmax): if ((L[L == i]).size < self.area_thrsh): # || (Lmax_ind > L_f/2) L[L == i] = 0 # set new mask combined_bin[L > 0] = 1 combined_bin[L == 0] = 0 print('Number of potential LCS founded:', Lmax) print('Area threshold:', self.area_thrsh) print('FTLE threshold:', self.ftle_thrsh) print('EVal threshold:', self.eval_thrsh) if to_dataset == True: if 'FTLE_forward' in self.lag_ftle.ds_output.keys(): self.lag_ftle.ds_output['LCS_forward'] = ( self.lag_ftle.ds_output['FTLE_forward'].dims, combined_bin[np.newaxis]) elif 'FTLE_backward' in self.ds_output.keys(): self.lag_ftle.ds_output['LCS_backward'] = ( self.lag_ftle.ds_output['FTLE_backward'].dims, combined_bin[np.newaxis]) # DEFINE RIDGE POINTS # search ridge==0 contour lines # suche Nulldurchgang fuer Gerade zwischen zwei direkt benachbarten grid Punkten # setze den Punkt, wenn der Nulldurchgang zwischen den beiden grid Punkten # liegt # clear x0 y0 x1 y1 x y if self.ridge_points == False: return combined_bin if self.ridge_points == True: x0 = 0 y0 = 0 m, n = np.shape(FTLE) X = np.arange(1, n) Y = np.arange(1, m) cnt = 0 x0 = [] y0 = [] for i in np.arange(0, m - 1): for j in np.arange(0, n - 2): if combined_bin[i, j] == 1: x = X[j:j + 2] z = np.array([ridge[i, j], ridge[i, j + 1]]) m1 = (z[1] - z[0]) / (x[1] - x[0] ) # Calculamos la pendiente # Calculamos el punto de corte con el eje y, n1 = z[0] - m1 * x[0] # round zero point (-n1/m1) to the nearest j if (np.abs(-n1 / m1 - x[0]) < np.abs(-n1 / m1 - x[1])): js = j else: js = j + 1 if (x[0] < -n1 / m1 and -n1 / m1 < x[1] and combined_bin[i, js] == 1): cnt = cnt + 1 x0.append(-n1 / m1) y0.append(Y[i]) for i in np.arange(0, m - 2): for j in np.arange(0, n - 1): if combined_bin[i, j] == 1: y = Y[i:i + 2] z = np.array([ridge[i, j], ridge[i + 1, j]]) m1 = (z[1] - z[0]) / (y[1] - y[0]) n1 = z[0] - m1 * y[0] # round zero point (-n1/m1) to the nearest i if (np.abs(-n1 / m1 - y[0]) < np.abs(-n1 / m1 - y[1])): isi = i else: isi = i + 1 if (y[0] < -n1 / m1 and -n1 / m1 < y[1] and combined_bin[isi, j] == 1): cnt = cnt + 1 x0.append(X[j]) y0.append(-n1 / m1) return x0, y0, combined_bin
from skimage.morphology import watershed, closing, opening from scipy.stats import logistic filename = "skeletons & matching cropped pics/cropped pics/v018-penn.9-1uB2D2-cropm.png" img = io.imread(filename) img = (img - np.mean(img)) / np.std(img) sigma = .75 Hxx, Hxy, Hyy = hessian_matrix(img, sigma=sigma, mode="wrap") e1, e2 = hessian_matrix_eigvals(Hxx, Hxy, Hyy) # How much bigger is the first eigenvalue's magnitude # compared with the second? log_condition = np.log(abs(e1/e2)) log_condition = log_condition / np.std(log_condition) out = logistic.cdf(log_condition) markers = np.zeros_like(out) markers[out < 0] = 1 markers[out > np.percentile(out, 90)] = 2 plt.imshow(out) plt.set_cmap('binary')
def get_max_hessian_eval(data, sigma=None): if sigma is None: sigma = np.ones(data.ndim) hess = hessian_matrix(data, sigma) evals = hessian_matrix_eigvals(hess) return evals.max(axis=0)
def get_hessian_matrix(input): Hessen = hessian_matrix(input, sigma=1.5) eigen1, eigen2 = hessian_matrix_eigvals(Hessen[0], Hessen[1], Hessen[2]) return eigen1, eigen2
def MVEF_2D(I, scales, thresholds): """Multiscale Vessel Enhancement Method for 2D images - based on Frangi's, Rana's, and Jalborg's works. This method searches for geometrical structures which can be regarded as tubular. The function is coded to enhance dark tube-like structure, so make sure that you do not need to inverse your image I before using this function. Args: I (2D array): I is a grayscale image (otherwise it is converted to grayscale) thresholds (list): thresholds is a list of two thresholds that control the sensitivity of the line filter to the measures Fr and R. It should look like [b, c], where b must not be zero. If c is zero, then its value is set to half the frobenius norm of the hessian matrix. scales (list): scales is a list of lengths that correspond to the diameter (in pixels) of the tube-like structure to find Outputs: I2 (2D array): one-canal image I, filtered by the multiscale vessel enhancement filter References: Based on [ Automatic detection of skeletal muscle architecture features, Frida Elen Jalborg, Master’s Thesis Spring 2016 ] [Frangi, 1998, Multiscale Vessel Enhancement filtering] [ Rana et al., 2009, Automated tracking of muscle fascicle orientation in B-mode ultrasound images] [ Rana et al., 2011, In-vivo determination of 3D muscle architecture of human muscle using free hand ultrasound] """ from skimage.feature import hessian_matrix, hessian_matrix_eigvals if len(I.shape) > 2: I = cv2.cvtColor(I, cv2.COLOR_RGB2GRAY) vesselness = np.zeros((I.shape[0], I.shape[1], len(scales))) I2 = np.zeros((I.shape[0], I.shape[1])) b = thresholds[0] c = thresholds[1] if b == 0: ValueError('first element of thresholds cannot be null') #calculation of Hessian matrix and its eigen values. #Corresponding eigen vectors are normal to and in the direction of #the tubular structure for sc in range(len(scales)): H = hessian_matrix(image=I, sigma=scales[sc], order='rc') eigvals = hessian_matrix_eigvals( H ) #2 eigenvalues in decreasing order; shape of ei = (2,I.shape[0], I.shape[1]) frobeniusnorm = np.sqrt(H[0]**2 + H[1]**2 + 2 * H[2]**2) if c == 0: c = 1 / 2 * np.amax(frobeniusnorm) for i in range(I.shape[0]): for j in range(I.shape[1]): 'Calculation of vesselness: looking for a POSITIVE highest' 'eigenvalue <=> looking for dark tube-like structures; looking' 'for a NEGATIVE highest eigen value <=> looking for bright' 'tube-like structures' #bright tube-like structures search did not work so the #temporary solution is to inverse the ultrasound image #and search for dark tube-like structures #if eigvals[0,i,j]<=0: #vesselness[i,j,sc] = 0 #not necessary since vesselness initialized with zeros if eigvals[0, i, j] > 0: 'ratio - for second order ellipsoid' R = eigvals[1, i, j] / eigvals[0, i, j] 'Frobenius norm - for second order structureness' Fr = m.sqrt(eigvals[0, i, j] * eigvals[0, i, j] + eigvals[1, i, j] * eigvals[1, i, j]) vesselness[i, j, sc] = scales[sc] * m.exp( -R * R / (2. * b * b)) * (1. - m.exp(-Fr * Fr / (2 * c * c))) 'Keep the highest value of vesselness across all scales' for ind1 in range(I2.shape[0]): for ind2 in range(I2.shape[1]): I2[ind1, ind2] = np.max(vesselness[ind1, ind2, :]) return I2
def shape_index(image, sigma=1, mode='constant', cval=0): """Compute the shape index. The shape index, as defined by Koenderink & van Doorn [1]_, is a single valued measure of local curvature, assuming the image as a 3D plane with intensities representing heights. It is derived from the eigen values of the Hessian, and its value ranges from -1 to 1 (and is undefined (=NaN) in *flat* regions), with following ranges representing following shapes: .. table:: Ranges of the shape index and corresponding shapes. =================== ============= Interval (s in ...) Shape =================== ============= [ -1, -7/8) Spherical cup [-7/8, -5/8) Through [-5/8, -3/8) Rut [-3/8, -1/8) Saddle rut [-1/8, +1/8) Saddle [+1/8, +3/8) Saddle ridge [+3/8, +5/8) Ridge [+5/8, +7/8) Dome [+7/8, +1] Spherical cap =================== ============= Parameters ---------- image : ndarray Input image. sigma : float, optional Standard deviation used for the Gaussian kernel, which is used for smoothing the input data before Hessian eigen value calculation. mode : {'constant', 'reflect', 'wrap', 'nearest', 'mirror'}, optional How to handle values outside the image borders cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. Returns ------- s : ndarray Shape index References ---------- .. [1] Koenderink, J. J. & van Doorn, A. J., "Surface shape and curvature scales", Image and Vision Computing, 1992, 10, 557-564. DOI:10.1016/0262-8856(92)90076-F Examples -------- >>> square = np.zeros((5, 5)) >>> square[2, 2] = 4 >>> s = shape_index(square, sigma=0.1) >>> s array([[ nan, nan, -0.5, nan, nan], [ nan, -0. , nan, -0. , nan], [-0.5, nan, -1. , nan, -0.5], [ nan, -0. , nan, -0. , nan], [ nan, nan, -0.5, nan, nan]]) """ R = hessian_matrix(image, sigma=sigma, mode=mode, cval=cval, order='rc') l1, l2 = hessian_matrix_eigvals(*R) return (2.0 / np.pi) * np.arctan((l2 + l1) / (l2 - l1))
def detectNeedle(self, magnitudevolume, phasevolume, maskThreshold, ridgeOperator, slice_index): #magnitude volume magn_imageData = magnitudevolume.GetImageData() magn_rows, magn_cols, magn_zed = magn_imageData.GetDimensions() magn_scalars = magn_imageData.GetPointData().GetScalars() magn_imageOrigin = magnitudevolume.GetOrigin() magn_imageSpacing = magnitudevolume.GetSpacing() magn_matrix = vtk.vtkMatrix4x4() magnitudevolume.GetIJKToRASMatrix(magn_matrix) # magnitudevolume.CreateDefaultDisplayNodes() # phase volume phase_imageData = phasevolume.GetImageData() phase_rows, phase_cols, phase_zed = phase_imageData.GetDimensions() phase_scalars = phase_imageData.GetPointData().GetScalars() #Convert vtk to numpy magn_array = numpy_support.vtk_to_numpy(magn_scalars) numpy_magn = magn_array.reshape(magn_zed, magn_rows, magn_cols) phase_array = numpy_support.vtk_to_numpy(phase_scalars) numpy_phase = phase_array.reshape(phase_zed, phase_rows, phase_cols) # slice = int(slice_number) # slice = (slice_index) # maskThreshold = int(maskThreshold) #2D Slice Selector ### 3 3D values are : numpy_magn , numpy_phase, mask numpy_magn = numpy_magn[slice_index, :, :] numpy_phase = numpy_phase[slice_index, :, :] #mask = mask[slice,:,:] numpy_magn_sliced = numpy_magn.astype(np.uint8) #mask thresholding img = cv2.pyrDown(numpy_magn_sliced) _, threshed = cv2.threshold(numpy_magn_sliced, maskThreshold, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(threshed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #find maximum contour and draw cmax = max(contours, key=cv2.contourArea) epsilon = 0.002 * cv2.arcLength(cmax, True) approx = cv2.approxPolyDP(cmax, epsilon, True) cv2.drawContours(numpy_magn_sliced, [approx], -1, (0, 255, 0), 3) width, height = numpy_magn_sliced.shape #fill maximum contour and draw mask = np.zeros([width, height, 3], dtype=np.uint8) cv2.fillPoly(mask, pts=[cmax], color=(255, 255, 255)) mask = mask[:, :, 0] #phase_cropped phase_cropped = cv2.bitwise_and(numpy_phase, numpy_phase, mask=mask) phase_cropped = np.expand_dims(phase_cropped, axis=0) node = slicer.vtkMRMLScalarVolumeNode() node.SetName('phase_cropped') slicer.mrmlScene.AddNode(node) slicer.util.updateVolumeFromArray(node, phase_cropped) node.SetOrigin(magn_imageOrigin) node.SetSpacing(magn_imageSpacing) node.SetIJKToRASDirectionMatrix(magn_matrix) unwrapped_phase = slicer.vtkMRMLScalarVolumeNode() unwrapped_phase.SetName('unwrapped_phase') slicer.mrmlScene.AddNode(unwrapped_phase) # # Run phase unwrapping module # parameter_name = slicer.mrmlScene.GetNodeByID( 'vtkMRMLCommandLineModuleNode1') if parameter_name is None: slicer.cli.createNode(slicer.modules.phaseunwrapping) else: pass cli_input = slicer.util.getFirstNodeByName('phase_cropped') cli_output = slicer.util.getNode('unwrapped_phase') cli_params = {'inputVolume': cli_input, 'outputVolume': cli_output} self.cliParamNode = slicer.cli.runSync(slicer.modules.phaseunwrapping, node=self.cliParamNode, parameters=cli_params) pu_imageData = unwrapped_phase.GetImageData() pu_rows, pu_cols, pu_zed = pu_imageData.GetDimensions() pu_scalars = pu_imageData.GetPointData().GetScalars() pu_NumpyArray = numpy_support.vtk_to_numpy(pu_scalars) phaseunwrapped = pu_NumpyArray.reshape(pu_zed, pu_rows, pu_cols) # for debug self.phaseunwrapped_numpy = pu_NumpyArray.reshape(pu_cols, pu_rows) I = phaseunwrapped.squeeze() A = np.fft.fft2(I) A1 = np.fft.fftshift(A) # Image size [M, N] = A.shape # filter size parameter R = 5 X = np.arange(0, N, 1) Y = np.arange(0, M, 1) [X, Y] = np.meshgrid(X, Y) Cx = 0.5 * N Cy = 0.5 * M Lo = np.exp(-(((X - Cx)**2) + ((Y - Cy)**2)) / ((2 * R)**2)) Hi = 1 - Lo J = A1 * Lo J1 = np.fft.ifftshift(J) B1 = np.fft.ifft2(J1) K = A1 * Hi K1 = np.fft.ifftshift(K) B2 = np.fft.ifft2(K1) B2 = np.real(B2) #Remove border for false positive border_size = 20 top, bottom, left, right = [border_size] * 4 mask_borderless = cv2.copyMakeBorder(mask, top, bottom, left, right, cv2.BORDER_CONSTANT, (0, 0, 0)) kernel = np.ones((5, 5), np.uint8) mask_borderless = cv2.erode(mask_borderless, kernel, iterations=5) mask_borderless = ndimage.binary_fill_holes(mask_borderless).astype( np.uint8) x, y = mask_borderless.shape mask_borderless = mask_borderless[0 + border_size:y - border_size, 0 + border_size:x - border_size] B2 = cv2.bitwise_and(B2, B2, mask=mask_borderless) H_elems = hessian_matrix(B2, sigma=5, order='rc') maxima_ridges, minima_ridges = hessian_matrix_eigvals(H_elems) hessian_det = maxima_ridges + minima_ridges coordinate = peak_local_max(maxima_ridges, num_peaks=1, min_distance=20, exclude_border=True, indices=True) x2 = np.asscalar(coordinate[:, 1]) y2 = np.asscalar(coordinate[:, 0]) point = (x2, y2) coords = [x2, y2, slice_index] circle1 = plt.Circle(point, 2, color='red') # Find or create MRML transform node transformNode = None try: transformNode = slicer.util.getNode('TipTransform') except slicer.util.MRMLNodeNotFoundException as exc: transformNode = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLLinearTransformNode') transformNode.SetName("TipTransform") transformNode.SetAndObserveMatrixTransformToParent(magn_matrix) # Fiducial Creation fidNode1 = None try: fidNode1 = slicer.util.getNode('needle_tip') except slicer.util.MRMLNodeNotFoundException as exc: fidNode1 = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsFiducialNode", "needle_tip") fidNode1.RemoveAllMarkups() # fidNode1.CreateDefaultDisplayNodes() # fidNode1.SetMaximumNumberOfControlPoints(1) fidNode1.AddFiducialFromArray(coords) fidNode1.SetAndObserveTransformNodeID(transformNode.GetID()) ###TODO: dont delete the volume after use. create a checkpoint to update on only one volume delete_wrapped = slicer.mrmlScene.GetFirstNodeByName('phase_cropped') slicer.mrmlScene.RemoveNode(delete_wrapped) delete_unwrapped = slicer.mrmlScene.GetFirstNodeByName( 'unwrapped_phase') slicer.mrmlScene.RemoveNode(delete_unwrapped) return True
def costMapGeneration(array): # bone segmentation threshold = [1250, 3000] image1, binary1 = boneSegmentation(array, threshold) # blood segmentation image, binary = boneSegmentation(array, [1, 250]) img = np.uint8(image) # vessel segmentation threshold2 = [1, 300] img = np.squeeze(img) kernel = np.ones((6, 6), np.float32) / 36 img = cv2.filter2D(img, -1, kernel) imgB0 = img # best image img = np.squeeze(array) img = cv2.filter2D(img, -1, kernel) img0 = img img = cv2.erode(img, kernel, iterations=2) img = cv2.dilate(img, kernel, iterations=2) img2 = cv2.erode(img, kernel, iterations=1) imf = img imf = cv2.dilate(imf, kernel, iterations=1) imf = cv2.erode(imf, kernel, iterations=1) imf = np.where((imf < 100), 0, 255) img11 = np.where((img < img.mean()), 0, 255) img21 = np.where((img2 < img.mean()), 0, 255) img3 = img11 + img21 img4 = np.where((img3 != 0), 255, 0) kernel = np.ones((2, 2), np.float32) / 4 img = cv2.filter2D(img0, -1, kernel) hxx, hxy, hyy = hessian_matrix(img, sigma=1) i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy) img = cv2.erode(img, kernel, iterations=2) imgh = np.where((i2 < i2.mean()), 255, 0) img = cv2.dilate(img, kernel, iterations=2) img20 = cv2.erode(img, kernel, iterations=20) img20 = np.where((img20 < img20.mean()), 0, 255) otherPlace = np.where((img20 <= 0), 255, 0) otherPlace = np.where((otherPlace <= 0), 255, 0) img10 = cv2.erode(img, kernel, iterations=10) img10 = np.where((img10 < img10.mean()), 0, 255) otherPlace10 = np.where((img10 <= 0), 255, 0) otherPlace10 = np.where((otherPlace10 <= 0), 255, 0) img55 = cv2.erode(img, kernel, iterations=5) img55 = np.where((img55 < img55.mean()), 0, 255) otherPlace55 = np.where((img55 <= 0), 255, 0) otherPlace55 = np.where((otherPlace55 <= 0), 255, 0) img15 = cv2.erode(img, kernel, iterations=5) img15 = np.where((img15 < img15.mean()), 0, 255) otherPlace15 = np.where((img15 <= 0), 255, 0) otherPlace15 = np.where((otherPlace15 <= 0), 255, 0) OP = otherPlace15 + otherPlace + otherPlace55 + otherPlace10 OP = np.where((OP > 0), 255, 0) img2 = cv2.erode(img, kernel, iterations=3) img = np.where((img < img.mean()), 0, 255) img2 = np.where((img2 < img.mean()), 0, 255) img5 = img4 - img2 img6 = np.where((img5 != 0), 255, 0) imgFrame = np.where((img20 <= img20.mean()), 0, 255) victorFrame = np.where((imf != 0), 0, 255) victorFrame = np.where((victorFrame <= 0), 0, 255) tangoZone = victorFrame + imgh bF = np.where((imgB0 < 255), 255, 0) OP1 = OP - imf OP = np.where((OP <= 0), 255, 0) superZone = bF - OP superZone = np.where((superZone <= 0), 0, 255) superZone = superZone - img11 superZone = np.where((superZone <= 0), 0, 255) superZone = superZone - OP1 superZone = np.where((superZone <= 0), 0, 255) comboZone = tangoZone + img11 - (binary) comboZone = np.where((comboZone <= 0), 255, 0) comboZone = np.where((comboZone <= 200), 255, 0) comboZone = np.where((comboZone <= 0), 255, 0) targetZone = comboZone comboZone = targetZone - otherPlace55 comboZone = np.where((comboZone <= 0) & (comboZone < 255), 0, 255) binZone = superZone + comboZone binZone = np.where((binZone > 0), 255, 0) binV2 = np.squeeze(binZone) # bone cost binV1 = np.squeeze(binary) # all squares now have a cost costMapV = np.where(binV1 == 1, 1000, 1) costMapB = np.where(binV2 == 1, 9000, 1) # final costmap costMap = np.squeeze(costMapV + costMapB) return (costMap, imgB0)
# pixel_x = res_x/img_b # pixel_y = res_y/img_h # noz = pixel_y * noz_d #circular mask # a, b = 560, 450 # n = 1112 # m = 1024 # r = 470 # y,x = np.ogrid[-a:n-a, -b:m-b] # mask = x*x + y*y >= r*r hxx, hyy, hxy = hessian_matrix(img, sigma=s_h, order='xy') i_h1, i_h2 = hessian_matrix_eigvals(hxx, hxy, hyy) i_g = gaussian(i_h1, sigma=s_g) i_e = morph.erosion(i_g) i_t = np.percentile(i_e[i_e > 0], t_percent) i_b = i_e > i_t # r = 435 # mask = x*x + y*y >= r*r # i_b[mask] = False i_rs = morph.remove_small_objects(i_b, min_size=240, connectivity=30) i_th = thin(i_rs, thinning) blobs = i_th > 1 * i_th.mean() all_labels = measure.label(blobs) blobs_labels = measure.label(blobs, background=0) i_f = i_th
def principal_curvatures(img, sigma=1.0, H=None): """ Return the principal curvatures {κ1, κ2} of an image, that is, the eigenvalues of the Hessian at each point (x,y). The output is arranged such that |κ1| <= |κ2|. Input: img: An ndarray representing a 2D or multichannel image. If the image is multichannel (e.g. RGB), then each channel will be proccessed individually. Additionally, the input image may be a masked array-- in which case the output will preserve this mask identically. PLEASE ADD SOME INFO HERE ABOUT WHAT SORT OF DTYPES ARE EXPECTED/REQUIRED, IF ANY sigma: (optional) The scale at which the Hessian is calculated. H: (optional) provide sigma (else it will be calculated) Output: (K1, K2): A tuple where K1, K2 each are the exact dimension of the input image, ordered in magnitude such that |κ1| <= |κ2| in all locations. If *signed* option is used, then elements of K1, K2 may be negative. Example: >>> K1, K2 = principal_curvatures(img) >>> K1.shape == img.shape True >>> (K1 <= K2).all() True >> K1.mask == img.mask True """ # determine if multichannel multichannel = (img.ndim == 3) if not multichannel: # add a trivial dimension img = img[:,:,np.newaxis] K1 = np.zeros_like(img, dtype='float64') K2 = np.zeros_like(img, dtype='float64') for ic in range(img.shape[2]): channel = img[:,:,ic] # returns the tuple (Hxx, Hxy, Hyy) if H is None: H = hessian_matrix(channel, sigma=sigma) # returns tuple (l1,l2) where l1 >= l2 but this *includes sign* L = hessian_matrix_eigvals(*H) L = np.dstack(L) mag = np.argsort(abs(L), axis=-1) # just some slice nonsense ix = np.ogrid[0:L.shape[0], 0:L.shape[1], 0:L.shape[2]] L = L[ix[0], ix[1], mag] # now k2 is larger in absolute value, as consistent with Frangi paper K1[:,:,ic] = L[:,:,0] K2[:,:,ic] = L[:,:,1] try: mask = img.mask except AttributeError: pass else: K1 = ma.masked_array(K1, mask=mask) K2 = ma.masked_array(K2, mask=mask) # now undo the trivial dimension if not multichannel: K1 = np.squeeze(K1) K2 = np.squeeze(K2) return K1, K2
def calculate(self, img, sigma=2.0): img = np.float32(img) rx, ry, rxx, ryy, rxy = self.estimate_derivatives(img, sigma) img_max_eigen_values, img_min_eigen_values = hessian_matrix_eigvals( rxx, rxy, ryy) return img_max_eigen_values, img_min_eigen_values
def detect_ridges(gray, sigma): H_elems = hessian_matrix(gray, sigma=sigma, order='rc') maxima_ridges, minima_ridges = hessian_matrix_eigvals(H_elems) return maxima_ridges, minima_ridges
def detect_ridges(gray, sigma=1.0): hxx, hyy, hxy = hessian_matrix(gray, sigma) i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy) return i1, i2
def detect_ridges(gray, sigma=3.0): hxx, hyy, hxy = feature.hessian_matrix(gray, sigma, mode='wrap') i1, i2 = feature.hessian_matrix_eigvals(hxx, hxy, hyy) return i1, i2 # i1 returns local maxima ridges and i2 returns local minima ridges
def __detect_using_custom(self, image): h_elems = hessian_matrix(image=np.float32(image), sigma=1.5, order='xy') eigvals = hessian_matrix_eigvals(h_elems) return eigvals[0]
ax[1].imshow(frangi(image), cmap=plt.cm.gray, vmin=0, vmax=0.00001) ax[1].set_title('Frangi filter result') for a in ax: a.axis('off') plt.tight_layout() plt.show() #%% Hessian의 Eigen value만 plot from skimage.feature import hessian_matrix, hessian_matrix_eigvals hxx, hxy, hyy = hessian_matrix(image, sigma=3) i1, i2 = hessian_matrix_eigvals([hxx, hxy, hyy]) plt.close('all') fig, ax = plt.subplots(ncols=3) ax[0].imshow(image, cmap=plt.cm.gray) ax[0].set_title('Original image') ax[1].imshow(i1, cmap=plt.cm.gray) ax[1].set_title('i1') ax[2].imshow(i2, cmap=plt.cm.gray) ax[2].set_title('i2') for a in ax: a.axis('off')
def detect_neuron_hessian(self, worm, z_diff, show=1, worm_green=None): # worm is the numpy array,[z,x,y] # calculate hessian of the worm image. z_scale = z_diff * 47.619 print('z_scale:{}'.format(z_scale)) grey_mask = self.get_gery_mask(worm) if worm_green is not None: grey_mask += self.get_gery_mask( worm_green, fac=12) * self.get_gery_mask(worm, fac=2) H_matrix = hessian_matrix(worm, sigma=1, order='rc') H_matrix_sub = list() for h_m in H_matrix: H_matrix_sub.append(h_m * grey_mask) H_eig = -hessian_matrix_eigvals(H_matrix_sub)[0] mask_n = H_eig > 1 label_n = ndi.label(mask_n)[0] if label_n.max() > 600: return None props = regionprops(label_n, intensity_image=worm) max_kernel3 = kernel_radius([3, 5, 5], r=3, dim1_scale=2.5, normalize=False) conn = np.ones((3, 3, 3)) area_thd = 6 self.neurons = dict() self.neurons['pts'] = list() self.neurons['pts_max'] = list() self.neurons['area'] = list() self.neurons['max_inten'] = list() self.neurons['mean_inten'] = list() self.neurons['label_o'] = list() self.neurons['bbox'] = list() self.neurons['mask'] = list() for prop in props: save_prop = True if prop.area > area_thd: worm_max = peak_local_max(prop.intensity_image, threshold_abs=None, exclude_border=False, indices=False, footprint=max_kernel3) worm_max_image = prop.intensity_image * worm_max candidate = list() worm_max_new = np.zeros(worm_max.shape) > 1 while worm_max_image.sum() > 0: pt = np.unravel_index(np.argmax(worm_max_image, axis=None), worm_max_image.shape) max_mask = pt_neighbor(size_im=worm_max.shape, pt=pt, r=4.2, dim1_scale=1.5) # 4.2, 2 candidate.append(pt) worm_max_new[pt] = True worm_max_image[max_mask] = 0 if len(candidate) >= 2: save_prop = False markers = ndi.label(worm_max_new)[0] label_sub = watershed(-prop.intensity_image, markers=markers, connectivity=conn, mask=prop.image) props_sub = regionprops( label_sub, intensity_image=prop.intensity_image) for prop_sub in props_sub: if prop_sub.area > area_thd: # neu_pos = np.unravel_index(np.argmax(prop_sub.intensity_image, axis=None), prop_sub.intensity_image.shape) # marker is of size prop neu_pos = np.where(markers == prop_sub.label) new_bbox = update_bbox(prop.bbox, prop_sub.bbox) neu_pos = np.array(neu_pos).T[0] + np.array( prop.bbox[:3]) neu_pos_c = np.array(prop_sub.centroid) + np.array( new_bbox[:3]) neuron = dict() neuron['neu_pos'] = neu_pos neuron['neu_pos_c'] = neu_pos_c neuron['bbox'] = new_bbox neuron['mask'] = prop_sub.image neuron['image'] = prop_sub.intensity_image neuron['label_o'] = prop.label neuron['max_inten'] = prop_sub.max_intensity neuron['mean_inten'] = prop_sub.mean_intensity neuron['area'] = prop_sub.area self.check_single_neuron(neuron) if save_prop: neu_pos = np.unravel_index( np.argmax(prop.intensity_image, axis=None), prop.intensity_image.shape) neu_pos = np.array(neu_pos) + np.array(prop.bbox[:3]) neu_pos_c = np.array(prop.centroid) neuron = dict() neuron['neu_pos'] = neu_pos neuron['neu_pos_c'] = neu_pos_c neuron['bbox'] = prop.bbox neuron['mask'] = prop.image neuron['image'] = prop.intensity_image neuron['label_o'] = prop.label neuron['max_inten'] = prop.max_intensity neuron['mean_inten'] = prop.mean_intensity neuron['area'] = prop.area self.check_single_neuron(neuron) neurons_pos = np.array(self.neurons['pts_max']) self.neurons['num_neuron'] = len(neurons_pos) print('find {} neurons'.format(self.neurons['num_neuron'])) print('\n') return self.neurons