From 84cfe39aaece34aa4615565bf5a8bb1566bd1705 Mon Sep 17 00:00:00 2001 From: saarah815 Date: Fri, 9 Aug 2024 13:58:22 +0100 Subject: [PATCH 01/10] work_in_progress --- .../registration_widget.py | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/brainglobe_registration/registration_widget.py b/brainglobe_registration/registration_widget.py index edaffc9..d224572 100644 --- a/brainglobe_registration/registration_widget.py +++ b/brainglobe_registration/registration_widget.py @@ -19,12 +19,15 @@ from brainglobe_atlasapi.list_atlases import get_downloaded_atlases from brainglobe_utils.qtpy.collapsible_widget import CollapsibleWidgetContainer from brainglobe_utils.qtpy.logo import header_widget +from brainreg.core.utils.preprocess import ( + filter_plane, +) from dask_image.ndinterp import affine_transform as dask_affine_transform from napari.qt.threading import thread_worker from napari.utils.notifications import show_error from napari.viewer import Viewer from pytransform3d.rotations import active_matrix_from_angle -from qtpy.QtWidgets import QPushButton, QTabWidget +from qtpy.QtWidgets import QCheckBox, QPushButton, QTabWidget from skimage.segmentation import find_boundaries from skimage.transform import rescale @@ -141,6 +144,9 @@ def __init__(self, napari_viewer: Viewer): self._on_default_file_selection_change ) + self.filter_checkbox = QCheckBox("Filter Images") + self.filter_checkbox.setChecked(False) + self.run_button = QPushButton("Run") self.run_button.clicked.connect(self._on_run_button_click) self.run_button.setEnabled(False) @@ -176,6 +182,9 @@ def __init__(self, napari_viewer: Viewer): self.add_widget( self.parameters_tab, widget_title="Advanced Settings (optional)" ) + + self.add_widget(self.filter_checkbox, collapsible=False) + self.add_widget(self.run_button, collapsible=False) self.layout().itemAt(1).widget().collapse(animate=False) @@ -276,9 +285,23 @@ def _on_run_button_click(self): current_atlas_slice = self._viewer.dims.current_step[0] + # ADD FILTERING HERE + if self.filter_checkbox.isChecked(): + atlas_layer = filter_plane( + self._atlas_data_layer.data[current_atlas_slice, :, :] + ) + moving_image_layer = filter_plane(self._moving_image.data) + else: + atlas_layer = self._atlas_data_layer.data[ + current_atlas_slice, :, : + ] + moving_image_layer = self._moving_image.data + result, parameters, registered_annotation_image = run_registration( - self._atlas_data_layer.data[current_atlas_slice, :, :], - self._moving_image.data, + # self._atlas_data_layer.data[current_atlas_slice, :, :], + atlas_layer, + # self._moving_image.data, + moving_image_layer, self._atlas_annotations_layer.data[current_atlas_slice, :, :], self.transform_selections, ) From dc8d89f944a0334d53d692efdd944d44fddbf94f Mon Sep 17 00:00:00 2001 From: saarah815 Date: Mon, 12 Aug 2024 11:28:33 +0100 Subject: [PATCH 02/10] filter_images --- .../registration_widget.py | 4 +- brainglobe_registration/utils/utils.py | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/brainglobe_registration/registration_widget.py b/brainglobe_registration/registration_widget.py index d224572..a5ddd00 100644 --- a/brainglobe_registration/registration_widget.py +++ b/brainglobe_registration/registration_widget.py @@ -19,9 +19,6 @@ from brainglobe_atlasapi.list_atlases import get_downloaded_atlases from brainglobe_utils.qtpy.collapsible_widget import CollapsibleWidgetContainer from brainglobe_utils.qtpy.logo import header_widget -from brainreg.core.utils.preprocess import ( - filter_plane, -) from dask_image.ndinterp import affine_transform as dask_affine_transform from napari.qt.threading import thread_worker from napari.utils.notifications import show_error @@ -36,6 +33,7 @@ adjust_napari_image_layer, calculate_rotated_bounding_box, check_atlas_installed, + filter_plane, find_layer_index, get_image_layer_names, open_parameter_file, diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index e94faa7..56ea6c4 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -8,6 +8,8 @@ from brainglobe_utils.qtpy.dialog import display_info from pytransform3d.rotations import active_matrix_from_angle from qtpy.QtWidgets import QWidget +from scipy.ndimage import gaussian_filter +from skimage import morphology def adjust_napari_image_layer( @@ -175,3 +177,49 @@ def check_atlas_installed(parent_widget: QWidget): "brainglobe-atlasapi or brainrender-napari", ) + + +def filter_plane(img_plane): + """ + Apply a set of filter to the plane (typically to avoid overfitting details + in the image during registration) + The filter is composed of a despeckle filter using opening and a pseudo + flatfield filter + + :param np.array img_plane: A 2D array to filter + :return: The filtered image + :rtype: np.array + """ + img_plane = np.copy(img_plane) + img_plane = despeckle_by_opening(img_plane) + img_plane = pseudo_flatfield(img_plane) + return img_plane + + +def despeckle_by_opening(img_plane, radius=2): + """ + Despeckle the image plane using a grayscale opening operation + + :param np.array img_plane: + :param int radius: The radius of the opening kernel + :return: The despeckled image + :rtype: np.array + """ + kernel = morphology.disk(radius) + morphology.opening(img_plane, out=img_plane, footprint=kernel) + return img_plane + + +def pseudo_flatfield(img_plane, sigma=5): + """ + Pseudo flat field filter implementation using a de-trending by a + heavily gaussian filtered copy of the image. + + :param np.array img_plane: The image to filter + :param int sigma: The sigma of the gaussian filter applied to the + image used for de-trending + :return: The pseudo flat field filtered image + :rtype: np.array + """ + filtered_img = gaussian_filter(img_plane, sigma) + return img_plane / (filtered_img + 1) From 275330aef8c340a7d1a0c82a284803d4f8cde486 Mon Sep 17 00:00:00 2001 From: saarah815 Date: Mon, 12 Aug 2024 14:38:16 +0100 Subject: [PATCH 03/10] filter_images --- .../registration_widget.py | 7 ++- brainglobe_registration/utils/utils.py | 50 ++++++++++++++----- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/brainglobe_registration/registration_widget.py b/brainglobe_registration/registration_widget.py index a5ddd00..05adfab 100644 --- a/brainglobe_registration/registration_widget.py +++ b/brainglobe_registration/registration_widget.py @@ -283,10 +283,11 @@ def _on_run_button_click(self): current_atlas_slice = self._viewer.dims.current_step[0] - # ADD FILTERING HERE if self.filter_checkbox.isChecked(): atlas_layer = filter_plane( - self._atlas_data_layer.data[current_atlas_slice, :, :] + self._atlas_data_layer.data[ + current_atlas_slice, :, : + ].compute() ) moving_image_layer = filter_plane(self._moving_image.data) else: @@ -296,9 +297,7 @@ def _on_run_button_click(self): moving_image_layer = self._moving_image.data result, parameters, registered_annotation_image = run_registration( - # self._atlas_data_layer.data[current_atlas_slice, :, :], atlas_layer, - # self._moving_image.data, moving_image_layer, self._atlas_annotations_layer.data[current_atlas_slice, :, :], self.transform_selections, diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index 56ea6c4..4e0e6f3 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -186,11 +186,22 @@ def filter_plane(img_plane): The filter is composed of a despeckle filter using opening and a pseudo flatfield filter - :param np.array img_plane: A 2D array to filter - :return: The filtered image - :rtype: np.array + Parameters + ---------- + img_plane : np.array + A 2D array to filter + + Returns + ---------- + np.array + Filtered image + + References + ---------- + [1] https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py """ - img_plane = np.copy(img_plane) + img_plane = despeckle_by_opening(img_plane) img_plane = pseudo_flatfield(img_plane) return img_plane @@ -200,10 +211,17 @@ def despeckle_by_opening(img_plane, radius=2): """ Despeckle the image plane using a grayscale opening operation - :param np.array img_plane: - :param int radius: The radius of the opening kernel - :return: The despeckled image - :rtype: np.array + Parameters + ---------- + img_plane : np.array + + radius: int + The radius of the opening kernel + + Returns + ---------- + np.array + The despeckled image """ kernel = morphology.disk(radius) morphology.opening(img_plane, out=img_plane, footprint=kernel) @@ -215,11 +233,19 @@ def pseudo_flatfield(img_plane, sigma=5): Pseudo flat field filter implementation using a de-trending by a heavily gaussian filtered copy of the image. - :param np.array img_plane: The image to filter - :param int sigma: The sigma of the gaussian filter applied to the + Parameters + ---------- + img_plane : np.array + The image to filter + + sigma : int + The sigma of the gaussian filter applied to the image used for de-trending - :return: The pseudo flat field filtered image - :rtype: np.array + + Returns + ---------- + np.array + The pseudo flat field filtered image """ filtered_img = gaussian_filter(img_plane, sigma) return img_plane / (filtered_img + 1) From 0382ef7210752144fa2f9e78d2f1af90c3cb5679 Mon Sep 17 00:00:00 2001 From: saarah815 Date: Mon, 12 Aug 2024 15:16:02 +0100 Subject: [PATCH 04/10] filter_images --- brainglobe_registration/utils/utils.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index 4e0e6f3..5b25efc 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -186,6 +186,9 @@ def filter_plane(img_plane): The filter is composed of a despeckle filter using opening and a pseudo flatfield filter + Originally from: https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py + Parameters ---------- img_plane : np.array @@ -195,11 +198,6 @@ def filter_plane(img_plane): ---------- np.array Filtered image - - References - ---------- - [1] https://github.com/brainglobe/brainreg/blob/main - /brainreg/core/utils/preprocess.py """ img_plane = despeckle_by_opening(img_plane) @@ -211,6 +209,9 @@ def despeckle_by_opening(img_plane, radius=2): """ Despeckle the image plane using a grayscale opening operation + Originally from: https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py + Parameters ---------- img_plane : np.array @@ -233,6 +234,9 @@ def pseudo_flatfield(img_plane, sigma=5): Pseudo flat field filter implementation using a de-trending by a heavily gaussian filtered copy of the image. + Originally from: https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py + Parameters ---------- img_plane : np.array From 4bcaf29e1b79f1de96fb7593fcce9de7aa28d794 Mon Sep 17 00:00:00 2001 From: saarah815 Date: Mon, 12 Aug 2024 15:17:12 +0100 Subject: [PATCH 05/10] filter_images --- brainglobe_registration/utils/utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index 5b25efc..b44712b 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -186,8 +186,8 @@ def filter_plane(img_plane): The filter is composed of a despeckle filter using opening and a pseudo flatfield filter - Originally from: https://github.com/brainglobe/brainreg/blob/main - /brainreg/core/utils/preprocess.py + Originally from: [https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py] Parameters ---------- @@ -209,8 +209,8 @@ def despeckle_by_opening(img_plane, radius=2): """ Despeckle the image plane using a grayscale opening operation - Originally from: https://github.com/brainglobe/brainreg/blob/main - /brainreg/core/utils/preprocess.py + Originally from: [https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py] Parameters ---------- @@ -234,8 +234,8 @@ def pseudo_flatfield(img_plane, sigma=5): Pseudo flat field filter implementation using a de-trending by a heavily gaussian filtered copy of the image. - Originally from: https://github.com/brainglobe/brainreg/blob/main - /brainreg/core/utils/preprocess.py + Originally from: [https://github.com/brainglobe/brainreg/blob/main + /brainreg/core/utils/preprocess.py] Parameters ---------- From 55762fb1958a7d12b5dcb4254a2bfc7d31d323de Mon Sep 17 00:00:00 2001 From: saarah815 <63860766+saarah815@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:11:35 +0100 Subject: [PATCH 06/10] Update brainglobe_registration/utils/utils.py Co-authored-by: Igor Tatarnikov <61896994+IgorTatarnikov@users.noreply.github.com> --- brainglobe_registration/utils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index b44712b..873370f 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -215,7 +215,8 @@ def despeckle_by_opening(img_plane, radius=2): Parameters ---------- img_plane : np.array - + The image to filter + radius: int The radius of the opening kernel From 2153af3e1800fe0086f50d7fba6e3e85c172473a Mon Sep 17 00:00:00 2001 From: saarah815 <63860766+saarah815@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:11:43 +0100 Subject: [PATCH 07/10] Update brainglobe_registration/utils/utils.py Co-authored-by: Igor Tatarnikov <61896994+IgorTatarnikov@users.noreply.github.com> --- brainglobe_registration/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index 873370f..7273261 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -248,7 +248,7 @@ def pseudo_flatfield(img_plane, sigma=5): image used for de-trending Returns - ---------- + ------- np.array The pseudo flat field filtered image """ From b61b34c207cbdff10421175189c720a1a4606a8c Mon Sep 17 00:00:00 2001 From: saarah815 <63860766+saarah815@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:11:50 +0100 Subject: [PATCH 08/10] Update brainglobe_registration/utils/utils.py Co-authored-by: Igor Tatarnikov <61896994+IgorTatarnikov@users.noreply.github.com> --- brainglobe_registration/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index 7273261..e551e19 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -195,7 +195,7 @@ def filter_plane(img_plane): A 2D array to filter Returns - ---------- + ------- np.array Filtered image """ From 9a469b7a721ce982ed6b9d493c1fff02427908a9 Mon Sep 17 00:00:00 2001 From: saarah815 <63860766+saarah815@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:11:56 +0100 Subject: [PATCH 09/10] Update brainglobe_registration/utils/utils.py Co-authored-by: Igor Tatarnikov <61896994+IgorTatarnikov@users.noreply.github.com> --- brainglobe_registration/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index e551e19..10250cf 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -221,7 +221,7 @@ def despeckle_by_opening(img_plane, radius=2): The radius of the opening kernel Returns - ---------- + ------- np.array The despeckled image """ From 0bac989fcd9456628299272907982816ede9698a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:13:30 +0000 Subject: [PATCH 10/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- brainglobe_registration/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brainglobe_registration/utils/utils.py b/brainglobe_registration/utils/utils.py index 10250cf..858ebab 100644 --- a/brainglobe_registration/utils/utils.py +++ b/brainglobe_registration/utils/utils.py @@ -216,7 +216,7 @@ def despeckle_by_opening(img_plane, radius=2): ---------- img_plane : np.array The image to filter - + radius: int The radius of the opening kernel