Mercurial > repos > imgteam > ridge_filter
comparison filter_skimage.py @ 0:0cb07fefbe70 draft
planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/ridge_filter/ commit 85b0f6afacb8933db19e03682559cc4d71031cf1
| author | imgteam |
|---|---|
| date | Fri, 12 Dec 2025 22:21:46 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:0cb07fefbe70 |
|---|---|
| 1 import argparse | |
| 2 import json | |
| 3 from typing import ( | |
| 4 Any, | |
| 5 Callable, | |
| 6 ) | |
| 7 | |
| 8 import giatools | |
| 9 import numpy as np | |
| 10 import skimage.filters | |
| 11 | |
| 12 | |
| 13 filters = { | |
| 14 'frangi': lambda img, **kwargs: ( | |
| 15 apply_nd_filter(skimage.filters.frangi, img, **kwargs) | |
| 16 ), | |
| 17 'hessian': lambda img, **kwargs: ( | |
| 18 apply_nd_filter(skimage.filters.hessian, img, **kwargs) | |
| 19 ), | |
| 20 'laplace': lambda img, **kwargs: ( | |
| 21 apply_nd_filter(skimage.filters.laplace, img, **kwargs) | |
| 22 ), | |
| 23 'meijering': lambda img, **kwargs: ( | |
| 24 apply_nd_filter(skimage.filters.meijering, img, **kwargs) | |
| 25 ), | |
| 26 'sato': lambda img, **kwargs: ( | |
| 27 apply_nd_filter(skimage.filters.sato, img, **kwargs) | |
| 28 ), | |
| 29 } | |
| 30 | |
| 31 | |
| 32 def apply_nd_filter( | |
| 33 filter_impl: Callable[[np.ndarray, Any, ...], np.ndarray], | |
| 34 img: giatools.Image, | |
| 35 dtype: str, | |
| 36 **kwargs: Any, | |
| 37 ) -> giatools.Image: | |
| 38 """ | |
| 39 Apply the filter to the 2-D/3-D, potentially multi-frame and multi-channel image. | |
| 40 """ | |
| 41 result_data = np.empty(img.data.shape, dtype=dtype) | |
| 42 for qtc in np.ndindex( | |
| 43 img.data.shape[ 0], # Q axis | |
| 44 img.data.shape[ 1], # T axis | |
| 45 img.data.shape[-1], # C axis | |
| 46 ): | |
| 47 sl = np.s_[*qtc[:2], ..., qtc[2]] # noqa: E999 | |
| 48 arr = img.data[sl] | |
| 49 assert arr.ndim == 3 # sanity check, should always be True | |
| 50 | |
| 51 # Perform 2-D or 3-D filtering | |
| 52 if arr.shape[0] == 1: | |
| 53 info = 'Performing 2-D filtering' | |
| 54 result_data[sl][0] = filter_impl(arr[0], **kwargs).astype(dtype) | |
| 55 else: | |
| 56 info = 'Performing 3-D filtering' | |
| 57 result_data[sl] = filter_impl(arr, **kwargs).astype(dtype) | |
| 58 | |
| 59 # Print status info | |
| 60 print(info) | |
| 61 | |
| 62 # Return results as 16bit, 32bit, or 64bit floating point | |
| 63 return giatools.Image(result_data.astype(dtype), img.axes) | |
| 64 | |
| 65 | |
| 66 def apply_filter( | |
| 67 input_filepath: str, | |
| 68 output_filepath: str, | |
| 69 filter_type: str, | |
| 70 **kwargs: Any, | |
| 71 ): | |
| 72 # Validate and transform input parameters | |
| 73 params = dict(kwargs) | |
| 74 if (sigma_min := params.pop('sigma_min', None)) is not None and (sigma_max := params.pop('sigma_max', None)) is not None: | |
| 75 num_sigma = params.pop('num_sigma') | |
| 76 if sigma_min < sigma_max: | |
| 77 params['sigmas'] = np.linspace(sigma_min, sigma_max, num_sigma) | |
| 78 elif sigma_min == sigma_max: | |
| 79 params['sigmas'] = [sigma_min] | |
| 80 else: | |
| 81 raise ValueError(f'Minimum sigma ({sigma_min:g}) must not be greater than Maximum sigma ({sigma_max:g})') | |
| 82 | |
| 83 # Read the input image | |
| 84 img = giatools.Image.read(input_filepath) | |
| 85 | |
| 86 # Perform filtering | |
| 87 print(f'Applying filter: "{filter_type}"') | |
| 88 filter_impl = filters[filter_type] | |
| 89 res = filter_impl(img, **params).normalize_axes_like(img.original_axes) | |
| 90 | |
| 91 # Adopt metadata and write the result | |
| 92 res.metadata = img.metadata | |
| 93 res.write(output_filepath, backend='tifffile') | |
| 94 | |
| 95 | |
| 96 if __name__ == "__main__": | |
| 97 parser = argparse.ArgumentParser() | |
| 98 parser.add_argument('input', type=str) | |
| 99 parser.add_argument('output', type=str) | |
| 100 parser.add_argument('params', type=str) | |
| 101 args = parser.parse_args() | |
| 102 | |
| 103 # Read the config file | |
| 104 with open(args.params) as cfgf: | |
| 105 cfg = json.load(cfgf) | |
| 106 | |
| 107 apply_filter( | |
| 108 args.input, | |
| 109 args.output, | |
| 110 **cfg, | |
| 111 ) |
