Skip to content
Snippets Groups Projects
Commit 8087839f authored by fima's avatar fima :beers:
Browse files

Merge branch 'update_documentation' into 'main'

Updated visualization. Added new functions to documentation. Updated...

See merge request !69
parents 984151df 9657a049
No related branches found
No related tags found
1 merge request!69Updated visualization. Added new functions to documentation. Updated...
Showing
with 184 additions and 103 deletions
docs/assets/screenshots/blob_detection.gif

1.93 MiB

docs/assets/screenshots/blob_get_mask.gif

815 KiB

docs/assets/screenshots/filter_original.png

219 KiB

docs/assets/screenshots/filter_processed.png

51.8 KiB

docs/assets/screenshots/local_thickness_2d.png

108 KiB

docs/assets/screenshots/local_thickness_3d.gif

1.44 MiB

docs/assets/screenshots/structure_tensor.gif

3.86 MiB

......@@ -3,32 +3,10 @@ Dealing with volumetric data can be done by `qim3d` for the most common image fo
Currently, it is possible to directly load `tiff`, `h5`, `nii`,`txm`, `vol` and common `PIL` formats using one single function.
!!! Example
```python
import qim3d
# Get some data from examples
vol = qim3d.examples.blobs_256x256x256
# Save in a local file
qim3d.io.save("blobs.tif", vol)
# Load data from file
loaded_vol = qim3d.io.load("blobs.tif")
```
::: qim3d.io.load
::: qim3d.io
options:
members:
- load
::: qim3d.io.save
options:
members:
- save
::: qim3d.io.downloader
options:
members:
- Downloader
- ImgExamples
\ No newline at end of file
# Processing data
::: qim3d.processing.filters
options:
members:
-
`qim3d` provides various tools for 3D image processing. Here, we provide a suite of powerful functionalities designed specifically for 3D image analysis and processing. From filter pipelines to structure tensor computation and blob detection, `qim3d` equips you with the tools you need to extract meaningful insights from your data.
::: qim3d.processing.filters.Pipeline
::: qim3d.processing
options:
members:
- append
::: qim3d.processing.structure_tensor
\ No newline at end of file
- structure_tensor
- local_thickness
- get_3d_cc
- Pipeline
- Blob
\ No newline at end of file
......@@ -12,6 +12,12 @@ And remember to keep your pip installation [up to date](/qim3d/#upgrade) so that
### v0.3.3 (coming soon!)
- Introduction of `qim3d.viz.slicer` (and also `qim3d.viz.orthogonal` ) 🎉
- Introduction of `qim3d.gui.annotation_tool` 🎉
- Introduction of `qim3d.processing.Blob` for blob detection 🎉
- Introduction of `qim3d.processing.local_thickness` 🎉
- Introduction of `qim3d.processing.structure_tensor` 🎉
- Support for loading DICOM files with `qim3d.io.load`🎉
- Introduction of `qim3d.processing.get_3d_cc` for 3D connected components and `qim3d.viz.plot_cc` for associated visualization 🎉
- Introduction of `qim3d.viz.colormaps` for easy visualization of e.g. multi-label segmentation results 🎉
### v0.3.2 (23/02/2024)
......@@ -20,9 +26,9 @@ This version focus on the increased usability of the `qim3d` library
- Online documentation available at [https://platform.qim.dk/qim3d](https://platform.qim.dk/qim3d)
- Virtual stacks also available for `txm` files
- Updated GUI launch pipeline
- New functionalities for `qim3d.vix.slices`
- New functionalities for `qim3d.viz.slices`
- Introduction of `qim3d.processing.filters` 🎉
- Introduction of `qim3d.viz.k3d` 🎉
- Introduction of `qim3d.viz.vol` 🎉
### v0.3.1 (01/02/2024)
......
# Data visualization
The `qim3d`libray aims to provide easy ways to explore and get insights from volumetric data.
The `qim3d` library aims to provide easy ways to explore and get insights from volumetric data.
!!! Example
```python
import qim3d
img = qim3d.examples.shell_225x128x128
qim3d.viz.slices(img, n_slices=15)
```
![Grid of slices](assets/screenshots/viz-slices.png)
!!! Example
```python
import qim3d
vol = qim3d.examples.bone_128x128x128
qim3d.viz.slicer(vol)
```
![viz slicer](assets/screenshots/viz-slicer.gif)
!!! Example
```python
import qim3d
vol = qim3d.examples.fly_150x256x256
qim3d.viz.orthogonal(vol, cmap="magma")
```
![viz orthogonal](assets/screenshots/viz-orthogonal.gif)
!!! Example
```python
import qim3d
vol = qim3d.examples.bone_128x128x128
qim3d.viz.vol(vol)
```
<iframe src="https://platform.qim.dk/k3d/fima-bone_128x128x128-20240221113459.html" width="100%" height="500" frameborder="0"></iframe>
::: qim3d.viz.img
::: qim3d.viz
options:
members:
- slices
- slicer
- orthogonal
::: qim3d.viz.k3d
options:
members:
- vol
- local_thickness
- vectors
- plot_cc
- objects
from .loading import DataLoader, load, ImgExamples
from .downloader import Downloader
from .load import DataLoader, load, ImgExamples
from .save import DataSaver, save
from .saving import DataSaver, save
from .sync import Sync
from . import logger
\ No newline at end of file
......@@ -7,16 +7,16 @@ from urllib.parse import quote
from tqdm import tqdm
from pathlib import Path
from qim3d.io.load import load
from qim3d.io import load
from qim3d.io.logger import log
import outputformat as ouf
class Downloader:
"""Class for downloading large data files available on the [QIM data repository](https://data.qim.dk/data-repository/).
"""Class for downloading large data files available on the [QIM data repository](https://data.qim.dk/).
Attributes:
[folder_name] (str): folder class with the name of the folder in https://data.qim.dk/data-repository/
[folder_name] (str): folder class with the name of the folder in <https://data.qim.dk/>
Example:
```python
......
......@@ -480,9 +480,11 @@ class DataLoader:
path (str or os.PathLike): The path to the file or directory.
Returns:
numpy.ndarray, numpy.memmap, h5py._hl.dataset.Dataset, nibabel.arrayproxy.ArrayProxy or tuple: The loaded volume.
If 'self.virtual_stack' is True, returns numpy.memmap, h5py._hl.dataset.Dataset or nibabel.arrayproxy.ArrayProxy depending on file format
If 'self.return_metadata' is True and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns a tuple (volume, metadata).
vol (numpy.ndarray, numpy.memmap, h5py._hl.dataset.Dataset, nibabel.arrayproxy.ArrayProxy or tuple): The loaded volume
If `virtual_stack=True`, returns `numpy.memmap`, `h5py._hl.dataset.Dataset` or `nibabel.arrayproxy.ArrayProxy` depending on file format
If `return_metadata=True` and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns `tuple` (volume, metadata).
Raises:
ValueError: If the format is not supported
ValueError: If the file or directory does not exist.
......@@ -585,11 +587,10 @@ def load(
to the DataLoader constructor.
Returns:
numpy.ndarray, numpy.memmap, h5py._hl.dataset.Dataset, nibabel.arrayproxy.ArrayProxy or tuple: The loaded volume.
vol (numpy.ndarray, numpy.memmap, h5py._hl.dataset.Dataset, nibabel.arrayproxy.ArrayProxy or tuple): The loaded volume
If 'virtual_stack' is True, returns numpy.memmap, h5py._hl.dataset.Dataset or nibabel.arrayproxy.ArrayProxy depending on file format
If 'return_metadata' is True and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns a tuple (volume, metadata).
If `virtual_stack=True`, returns `numpy.memmap`, `h5py._hl.dataset.Dataset` or `nibabel.arrayproxy.ArrayProxy` depending on file format
If `return_metadata=True` and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns `tuple` (volume, metadata).
Example:
```python
......@@ -635,7 +636,30 @@ def load(
class ImgExamples:
"""Image examples"""
"""Image examples
Attributes:
blobs_256x256 (numpy.ndarray): A 2D image of blobs.
blobs_256x256x256 (numpy.ndarray): A 3D volume of blobs.
bone_128x128x128 (numpy.ndarray): A 3D volume of bone.
cement_128x128x128 (numpy.ndarray): A 3D volume of cement.
fly_150x256x256 (numpy.ndarray): A 3D volume of a fly.
NT_10x200x100 (numpy.ndarray): A 3D volume of a neuron.
NT_128x128x128 (numpy.ndarray): A 3D volume of a neuron.
shell_225x128x128 (numpy.ndarray): A 3D volume of a shell.
Tip:
Call `qim3d.examples.<name>` to access the image examples easily as this class is instantiated when importing `qim3d`
Example:
```python
import qim3d
data = qim3d.examples.blobs_256x256
```
"""
def __init__(self):
img_examples_path = Path(qim3d.__file__).parents[0] / "img_examples"
......@@ -647,4 +671,4 @@ class ImgExamples:
# Generate loader for each image found
for idx, name in enumerate(img_names):
exec(f"self.{name} = qim3d.io.load(path = img_paths[idx])")
\ No newline at end of file
exec(f"self.{name} = load(path = img_paths[idx])")
\ No newline at end of file
File moved
from .local_thickness_ import local_thickness
from .structure_tensor_ import structure_tensor
from .filters import *
from .local_thickness import local_thickness
from .structure_tensor import structure_tensor
from .detection import *
from .cc import get_3d_cc
File moved
......@@ -6,6 +6,9 @@ __all__ = ["Blob"]
class Blob:
"""
Extract blobs from a volume using Difference of Gaussian (DoG) method
"""
def __init__(
self,
background="dark",
......@@ -19,6 +22,7 @@ class Blob:
):
"""
Initialize the blob detection object
Args:
background: 'dark' if background is darker than the blobs, 'bright' if background is lighter than the blobs
min_sigma: The minimum standard deviation for Gaussian kernel
......@@ -43,10 +47,37 @@ class Blob:
def detect(self, vol):
"""
Detect blobs in the volume
Args:
vol: The volume to detect blobs in
Returns:
blobs: The blobs found in the volume as (p, r, c, radius)
Example:
```python
import qim3d
# Get data
vol = qim3d.examples.cement_128x128x128
vol_blurred = qim3d.processing.gaussian(vol, sigma=2)
# Initialize Blob detector
blob_detector = qim3d.processing.Blob(
min_sigma=1,
max_sigma=8,
threshold=0.001,
overlap=0.1,
background="bright"
)
# Detect blobs
blobs = blob_detector.detect(vol_blurred)
# Visualize results
qim3d.viz.circles(blobs,vol,alpha=0.8,color='blue')
```
![blob detection](assets/screenshots/blob_detection.gif)
"""
self.vol_shape = vol.shape
if self.background == "bright":
......@@ -70,8 +101,32 @@ class Blob:
def get_mask(self):
'''
Retrieve a binary volume with the blobs marked as True
Returns:
binary_volume: A binary volume with the blobs marked as True
Example:
```python
import qim3d
# Get data
vol = qim3d.examples.cement_128x128x128
vol_blurred = qim3d.processing.gaussian(vol, sigma=2)
# Initialize Blob detector
blob_detector = qim3d.processing.Blob(
min_sigma=1,
max_sigma=8,
threshold=0.001,
overlap=0.1,
background="bright"
)
# Get mask and visualize
mask = blob_detector.get_mask()
qim3d.viz.slicer(mask)
```
![blob detection](assets/screenshots/blob_get_mask.gif)
'''
binary_volume = np.zeros(self.vol_shape, dtype=bool)
......
......@@ -87,6 +87,37 @@ class Minimum(FilterBase):
class Pipeline:
"""
Example:
```python
import qim3d
from qim3d.processing import Pipeline, Median, Gaussian, Maximum, Minimum
# Get data
vol = qim3d.examples.fly_150x256x256
# Show original
qim3d.viz.slices(vol, axis=0, show=True)
# Create filter pipeline
pipeline = Pipeline(
Median(size=5),
Gaussian(sigma=3)
)
# Append a third filter to the pipeline
pipeline.append(Maximum(size=3))
# Apply filter pipeline
vol_filtered = pipeline(vol)
# Show filtered
qim3d.viz.slices(vol_filtered, axis=0)
```
![original volume](assets/screenshots/filter_original.png)
![filtered volume](assets/screenshots/filter_processed.png)
"""
def __init__(self, *args: Type[FilterBase]):
"""
Represents a sequence of image filters.
......@@ -125,6 +156,20 @@ class Pipeline:
Args:
fn: An instance of a FilterBase subclass to be appended.
Example:
```python
import qim3d
from qim3d.processing import Pipeline, Maximum, Median
# Create filter pipeline
pipeline = Pipeline(
Maximum(size=3)
)
# Append a second filter to the pipeline
pipeline.append(Median(size=5))
```
"""
self._add_filter(str(len(self.filters)), fn)
......
......@@ -15,7 +15,7 @@ def local_thickness(
visualize=False,
**viz_kwargs
) -> np.ndarray:
"""Wrapper for the local thickness function from the localthickness package (https://github.com/vedranaa/local-thickness)
"""Wrapper for the local thickness function from the [local thickness package](https://github.com/vedranaa/local-thickness)
Args:
image (np.ndarray): 2D or 3D NumPy array representing the image/volume.
......@@ -26,11 +26,27 @@ def local_thickness(
mask (np.ndarray, optional): binary mask of the same size of the image defining parts of the
image to be included in the computation of the local thickness. Default is None.
visualize (bool, optional): Whether to visualize the local thickness. Default is False.
**viz_kwargs: Additional keyword arguments for the visualization function. Only used if visualize=True.
**viz_kwargs: Additional keyword arguments passed to `qim3d.viz.local_thickness`. Only used if `visualize=True`.
Returns:
local_thickness (np.ndarray): 2D or 3D NumPy array representing the local thickness of the input image/volume.
Example:
```python
import qim3d
fly = qim3d.examples.fly_150x256x256 # 3D volume
lt_fly = qim3d.processing.local_thickness(fly, visualize=True, axis=0)
```
![local thickness 3d](assets/screenshots/local_thickness_3d.gif)
```python
import qim3d
blobs = qim3d.examples.blobs_256x256 # 2D image
lt_blobs = qim3d.processing.local_thickness(blobs, visualize=True)
```
![local thickness 2d](assets/screenshots/local_thickness_2d.png)
!!! quote "Reference"
Dahl, V. A., & Dahl, A. B. (2023, June). Fast Local Thickness. 2023 IEEE/CVF Conference on Computer Vision and Pattern Recognition Workshops (CVPRW).
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment