Source code for nanomesh.image._plane

from __future__ import annotations

import logging
from typing import TYPE_CHECKING, Union

import matplotlib.pyplot as plt
import numpy as np

from .._doc import doc
from ._image import Image
from ._utils import show_image

logger = logging.getLogger(__name__)

if TYPE_CHECKING:
    from .mesh import TriangleMesh


[docs]@doc(Image, prefix='Data class for working with 2D image data', shape='(i,j) ') class Plane(Image, ndim=2):
[docs] def show(self, *, ax: plt.Axes = None, title: str = None, **kwargs) -> 'plt.Axes': """Plot the image using :mod:`matplotlib`. Parameters ---------- ax : matplotlib.axes.Axes, optional Axes to use for plotting. title : str, optional Title for the plot. **kwargs These parameters are passed to :func:`matplotlib.pyplot.imshow`. Returns ------- ax : matplotlib.axes.Axes Instance of :class:`matplotlib.axes.Axes` """ return show_image(self.image, ax=ax, title=title, **kwargs)
[docs] @doc(show) def plot(self, *args, **kwargs): return self.show(*args, **kwargs)
[docs] def generate_mesh(self, **kwargs) -> TriangleMesh: """Generate mesh from binary (segmented) image. Parameters ---------- **kwargs: Keyword arguments are passed to :func:`nanomesh.plane2mesh` Returns ------- mesh : TriangleMesh Description of the mesh. """ from nanomesh.image2mesh import plane2mesh return plane2mesh(image=self.image, **kwargs)
[docs] def select_roi(self, from_points: np.ndarray = None): """Select region of interest in interactive matplotlib figure. Parameters ---------- from_points : (n, 2) numpy.ndarray, optional List of points that are used as anchors for the roi selection. Returns ------- roi : `nanomesh.image._roi2d.ROISelector` Region of interest object. Bounding box is stored in :attr:`roi.bbox`. """ from ._roi2d import ROISelector ax = self.show(title='Select region of interest') if from_points is not None: # reverse columns to match image from_points = from_points[:, ::-1] ax.scatter(*from_points.T) roi = ROISelector(ax, snap_to=from_points) return roi
[docs] def crop(self, left: int, top: int, right: int, bottom: int) -> Plane: """Crop image to pixel indices. Parameters ---------- left, top, right, bottom : int Index of pixel delimiting cropping box. Returns ------- Plane New instance of :class:`Plane`. """ return Plane(self.image[top:bottom, left:right])
[docs] def crop_to_roi(self, bbox: np.ndarray) -> Plane: """Crop plane to rectangle defined by bounding box. Parameters ---------- bbox : (4,2) numpy.ndarray List of points describing region of interest. The bounding box may be rotated. Returns ------- Plane Cropped region as :class:`Plane` object. """ from ._roi2d import extract_rectangle cropped = extract_rectangle(self.image, bbox=bbox) return Plane(cropped)
[docs] def compare_with_mesh(self, mesh: TriangleMesh) -> 'plt.Axes': """Make a plot comparing the image with the given mesh. Parameters ---------- mesh : TriangleMesh Mesh to compare the image with. Returns ------- plt.Axes """ from ..utils import compare_mesh_with_image return compare_mesh_with_image(image=self.image, mesh=mesh)
[docs] def compare_with_digitized(self, digitized: Union[np.ndarray, 'Plane'], cmap: str = None, **kwargs) -> 'plt.Axes': """Compare image with digitized (segmented) image. Returns a plot with the overlay of the digitized image. Parameters ---------- digitized : numpy.ndarray, Plane Digitized image of the same dimensions to overlay cmap : str Matplotlib color map for :func:`matplotlib.pyplot.imshow` **kwargs These parameters are passed to :func:`skimage.color.label2rgb`. Returns ------- ax : matplotlib.axes.Axes """ from skimage.color import label2rgb if isinstance(digitized, Plane): digitized = digitized.image # bg_label=0 is default for scikit-image from 0.19 onwards kwargs.setdefault('bg_label', 0) image_overlay = label2rgb(digitized, image=self.image, **kwargs) fig, ax = plt.subplots() ax.imshow(image_overlay, interpolation='none', cmap=cmap) ax.axis('image') ax.set_xticks([]) ax.set_yticks([]) ax.set_title('Image comparison') return ax
[docs] def compare_with_other(self, other: Union[np.ndarray, 'Plane'], cmap: str = None, **kwargs) -> 'plt.Axes': """Compare image with other image. Parameters ---------- other : numpy.ndarray, Plane Other image of the same dimensions to overlay cmap : str Matplotlib color map for :func:`matplotlib.pyplot.imshow` **kwargs These parameters are passed to :func:`skimage.util.compare_images`. Returns ------- ax : matplotlib.axes.Axes """ from skimage.util import compare_images if isinstance(other, Plane): other = other.image kwargs.setdefault('method', 'checkerboard') kwargs.setdefault('n_tiles', (4, 4)) comp = compare_images(self.image, other, **kwargs) fig, ax = plt.subplots() ax.imshow(comp, interpolation='none', cmap=cmap) ax.axis('image') ax.set_xticks([]) ax.set_yticks([]) ax.set_title(f'Image comparison ({kwargs["method"]})') return ax
[docs] def clear_border(self, *, object_label: int, fill_val: int, **kwargs) -> Plane: """Remove objects at the border of the image. Parameters ---------- object_label : int Label of the objects to remove. fill_val : int Cleared objects are set to this value. **kwargs These parameters are passed to :func:`skimage.segmentation.clear_border`. Returns ------- Plane New instance of :class:`Plane`. """ from skimage import segmentation objects = (self.image == object_label).astype(int) border_cleared = segmentation.clear_border(objects, **kwargs) mask = (border_cleared != objects) out = self.image.copy() out[mask] = fill_val return self.__class__(out)
[docs] def try_all_threshold(self, **kwargs): """Produce a plot trying all available thresholds using :func:`skimage.filters.try_all_threshold`. Parameters ---------- **kwargs These parameters are passed to :func:`skimage.filters.try_all_threshold`. """ from skimage import filters kwargs.setdefault('verbose', False) self.apply(filters.try_all_threshold, **kwargs)