Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • QIM/tools/qim3d
1 result
Select Git revision
Loading items
Show changes
Commits on Source (11)
Showing
with 224 additions and 100 deletions
......@@ -24,3 +24,6 @@ build/
# MacOS finder files
*.DS_Store
# Installed itk-vtk-viewer files
itk_vtk_viewer/
\ No newline at end of file
docs/assets/screenshots/CLI-k3d.png

342 KiB | W: 0px | H: 0px

docs/assets/screenshots/CLI-k3d.png

398 KiB | W: 0px | H: 0px

docs/assets/screenshots/CLI-k3d.png
docs/assets/screenshots/CLI-k3d.png
docs/assets/screenshots/CLI-k3d.png
docs/assets/screenshots/CLI-k3d.png
  • 2-up
  • Swipe
  • Onion skin
docs/assets/screenshots/cowry_shell_slicer.gif

1.63 MiB

Image diff could not be displayed: it is too large. Options to address this: view the blob.
docs/assets/screenshots/local_thickness_2d.png

108 KiB | W: 0px | H: 0px

docs/assets/screenshots/local_thickness_2d.png

69.9 KiB | W: 0px | H: 0px

docs/assets/screenshots/local_thickness_2d.png
docs/assets/screenshots/local_thickness_2d.png
docs/assets/screenshots/local_thickness_2d.png
docs/assets/screenshots/local_thickness_2d.png
  • 2-up
  • Swipe
  • Onion skin
docs/assets/screenshots/synthetic_blob_slices.png

61.2 KiB | W: 0px | H: 0px

docs/assets/screenshots/synthetic_blob_slices.png

61.3 KiB | W: 0px | H: 0px

docs/assets/screenshots/synthetic_blob_slices.png
docs/assets/screenshots/synthetic_blob_slices.png
docs/assets/screenshots/synthetic_blob_slices.png
docs/assets/screenshots/synthetic_blob_slices.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -4,7 +4,7 @@ The library also includes a command line interface for easy access to some funct
This offers quick interactions, making it ideal for tasks that require efficiency or when certain functionalities need to run on a server.
!!! Example
```bash
``` title="Command"
qim3d gui --data-explorer
```
![CLI Data Explorer](assets/screenshots/CLI-data_explorer.gif)
......@@ -38,7 +38,7 @@ This offers quick interactions, making it ideal for tasks that require efficienc
Here's an example of how to open the [Data Explorer](gui.md#data_explorer)
```
``` title="Command"
qim3d gui --data-explorer
```
``` title="Output"
......@@ -54,7 +54,7 @@ This offers quick interactions, making it ideal for tasks that require efficienc
Or for the local thickness GUI:
```
``` title="Command"
qim3d gui --local-thickness --host 127.0.0.1 --platform
```
......@@ -98,32 +98,64 @@ The command line interface also allows you to easily visualize data.
### `qim3d viz`
!!! quote "Reference"
Volumetric visualization uses K3D:
[Github page](https://github.com/K3D-tools/K3D-jupyter)
Volumetric visualization uses [itk-vtk-viewer](https://kitware.github.io/itk-vtk-viewer/docs/index.html) and [K3D](https://github.com/K3D-tools/K3D-jupyter).
You can launch volumetric visualizations directly from the command line. By default, it will launch the `itk-vtk-viewer`, but `k3d` can be selected by passing the argument `--method k3d`.
It is possible to launch the k3d visualization directly from the command line.
!!! info
If `itk-vtk-viewer` is not installed, you will be prompted for automatic installation via the `qim3d` library.
| Arguments | Description |
| --------- | ----------- |
| `--source` | Path to the volume file (Any image format supported by `qim3d.io.load()`) |
| `--destination` | Path to the `html` file to be saved. By default, `k3d.html` is saved where the command is run. |
| `--no-browser` | Do not open the file when finished. |
| Argument | Description |
| ---------------- | --------------- |
| `source` | Path to the volume file or OME-Zarr store (any image format supported by `qim3d.io.load()`). |
| `--method` | Visualization method: `itk-vtk-viewer` (default) or `k3d`. |
| `--destination` | Custom `.html` file to be saved when using `k3d`. By default, `k3d.html` is saved. An file is aways saved when calling `k3d`. |
| `--no-browser` | Prevent the file from opening automatically when finished.|
!!! Example "Visualization of a OME-Zarr store"
``` title="Command"
qim3d viz Okinawa_Foram_1.zarr/
```
!!! Example
``` title="Output"
itk-vtk-viewer
=> Serving /home/fima/Notebooks/Qim3d on port 3000
enp0s31f6 => http://10.52.0.158:3000/
wlp0s20f3 => http://10.197.104.229:3000/
Serving directory '/home/fima/Notebooks/Qim3d'
http://localhost:8042/
Visualization url:
http://localhost:3000/?rotate=false&fileToLoad=http://localhost:8042/Okinawa_Foram_1.zarr
```
qim3d viz --source blobs_256x256x256.tif
A new tab in the default browser will be open with the visualization:
![itk-vtk-viewer](assets/screenshots/itk-vtk-viewer.gif)
!!! Example "Example using k3d"
``` title="Command"
qim3d viz blobs_256x256x256.tif --method k3d
```
``` title="Output"
Loading data from blobs_256x256x256.tif
Done, volume shape: (256, 256, 256)
Loading data from cement_128x128x128.tif
Loading: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2.02MB/2.02MB [00:00<00:00, 936MB/s]
Volume using 2.0 MB of memory
System memory:
• Total.: 31.0 GB
• Used..: 18.8 GB (60.8%)
• Free..: 12.1 GB (39.2%)
Done, volume shape: (128, 128, 128)
Generating k3d plot...
Done, plot available at <k3d.html>
Opening in default browser...
```
And a new tab will be opened in the default browser with the interactive k3d plot:
......@@ -133,22 +165,31 @@ Or an specific path for destination can be used. We can also choose to not open
!!! Example
```
qim3d viz --source blobs_256x256x256.tif --destination my_plot.html --no-browser
qim3d viz cement_128x128x128.tif --destination my_plot.html --no-browser
```
``` title="Output"
Loading data from blobs_256x256x256.tif
Done, volume shape: (256, 256, 256)
Loading data from cement_128x128x128.tif
Loading: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2.02MB/2.02MB [00:00<00:00, 909MB/s]
Volume using 2.0 MB of memory
System memory:
• Total.: 31.0 GB
• Used..: 18.9 GB (61.1%)
• Free..: 12.0 GB (38.9%)
Done, volume shape: (128, 128, 128)
Generating k3d plot...
Done, plot available at <my_plot.html>
```
This writes to disk the `my_plot.html` file.
## File preview
Command line interface, which allows users to preview 3D structers or 2D images directly in command line.
### `qim3d preview <filename>`
### `qim3d preview`
| Arguments | Description |
| --------- | ----------- |
| `--axis` | Specifies from which axis the slice will be taken. If the object is 2D image, then this is ignored. Defaults to 0.|
......@@ -157,35 +198,35 @@ Command line interface, which allows users to preview 3D structers or 2D images
| `--absolute_values` |If values are low the image might be just black square. By default maximum value is set to 255. This flag turns this behaviour off.|
!!! Example
```
``` title="Command"
qim3d preview blobs_256x256x256.tif
```
![CLI k3d](assets/preview/default.png){ width="512" }
!!! Example
```
``` title="Command"
qim3d preview blobs_256x256x256.tif --resolution 30
```
![CLI k3d](assets/preview/res30.png){ width="512" }
!!! Example
```
``` title="Command"
qim3d preview blobs_256x256x256.tif --resolution 50 --axis 1
```
![CLI k3d](assets/preview/axis1.png){ width="512" }
!!! Example
```
``` title="Command"
qim3d preview blobs_256x256x256.tif --resolution 50 --axis 2 --slice 0
```
![CLI k3d](assets/preview/relativeIntensity.png){ width="512" }
!!! Example
```
``` title="Command"
qim3d preview qim_logo.png --resolution 40
```
......
......@@ -9,6 +9,11 @@ As the library is still in its early development stages, **there may be breaking
And remember to keep your pip installation [up to date](/qim3d/#get-the-latest-version) so that you have the latest features!
### v0.4.4 (11/10/2024)
- Introduction of `itk-vtk-viewer` for OME-Zarr data visualization 🎉 ![itk-vtk-viewer](assets/screenshots/itk-vtk-viewer.gif)
### v0.4.3 (02/10/2024)
- Updated requirements
......
......@@ -8,6 +8,7 @@ The `qim3d` library aims to provide easy ways to explore and get insights from v
- slicer
- orthogonal
- vol
- itk_vtk
- mesh
- local_thickness
- vectors
......
......@@ -8,7 +8,7 @@ Documentation available at https://platform.qim.dk/qim3d/
"""
__version__ = "0.4.3"
__version__ = "0.4.4"
import importlib as _importlib
......
import argparse
import webbrowser
import platform
import outputformat as ouf
import qim3d
import os
QIM_TITLE = ouf.rainbow(
f"\n _ _____ __ \n ____ _(_)___ ___ |__ /____/ / \n / __ `/ / __ `__ \ /_ </ __ / \n/ /_/ / / / / / / /__/ / /_/ / \n\__, /_/_/ /_/ /_/____/\__,_/ \n /_/ v{qim3d.__version__}\n\n",
......@@ -42,7 +44,15 @@ def main():
# Viz
viz_parser = subparsers.add_parser("viz", help="Volumetric visualization.")
viz_parser.add_argument("filename", default=False, help="Path to the image file")
viz_parser.add_argument("source", help="Path to the image file")
viz_parser.add_argument(
"-m",
"--method",
type=str,
metavar="METHOD",
default="itk-vtk",
help="Which method is used to display file.",
)
viz_parser.add_argument(
"--destination", default="k3d.html", help="Path to save html file."
)
......@@ -142,19 +152,35 @@ def main():
interface.launch(inbrowser=inbrowser, force_light_mode=False)
elif args.subcommand == "viz":
# Load the data
print(f"Loading data from {args.filename}")
volume = qim3d.io.load(str(args.filename))
print(f"Done, volume shape: {volume.shape}")
# Make k3d plot
if args.method == "itk-vtk":
try:
# We need the full path to the file for the viewer
current_dir = os.getcwd()
full_path = os.path.normpath(os.path.join(current_dir, args.source))
qim3d.viz.itk_vtk(full_path, open_browser=not args.no_browser)
except qim3d.viz.NotInstalledError as err:
print(err)
message = "Itk-vtk-viewer is not installed or qim3d can not find it.\nYou can either:\n\to Use 'qim3d viz SOURCE -m k3d' to display data using different method\n\to Install itk-vtk-viewer yourself following https://kitware.github.io/itk-vtk-viewer/docs/cli.html#Installation\n\to Let QIM3D install itk-vtk-viewer now (it will also install node.js in qim3d library)\nDo you want QIM3D to install itk-vtk-viewer now?"
print(message)
answer = input("[Y/n]:")
if answer in "Yy":
qim3d.viz.Installer().install()
qim3d.viz.itk_vtk(full_path)
elif args.method == "k3d":
volume = qim3d.io.load(str(args.source))
print("\nGenerating k3d plot...")
qim3d.viz.vol(volume, show=False, save=str(args.destination))
print(f"Done, plot available at <{args.destination}>")
if not args.no_browser:
print("Opening in default browser...")
webbrowser.open_new_tab(args.destination)
else:
raise NotImplementedError(
f"Method '{args.method}' is not valid. Try 'k3d' or default 'itk-vtk-viewer'"
)
elif args.subcommand == "preview":
......
......@@ -39,7 +39,7 @@ def blob(
import qim3d
# Generate synthetic blob
synthetic_blob = qim3d.generate.blob(noise_scale = 0.05)
synthetic_blob = qim3d.generate.blob(noise_scale = 0.015)
# Visualize slices
qim3d.viz.slices(synthetic_blob, vmin = 0, vmax = 255, n_slices = 15)
......
......@@ -16,15 +16,45 @@ class Downloader:
"""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/>
folder_name (str): Folder class with the name of the folder in <https://data.qim.dk/>
Syntax for downloading and loading a file is `qim3d.io.Downloader().{folder_name}.{file_name}(load_file=True)`
??? info "Overview of available data"
Below is a table of the available folders and files on the [QIM data repository](https://data.qim.dk/).
Folder name | File name | File size
------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------
`Coal` | `CoalBrikett` <br> `CoalBrikett_Zoom` <br> `CoalBrikettZoom_DOWNSAMPLED` | 2.23 GB <br> 3.72 GB <br> 238 MB
`Corals` | `Coral_1` <br> `Coral_2` <br> `Coral2_DOWNSAMPLED` <br> `MexCoral` | 2.26 GB <br> 2.38 GB <br> 162 MB <br> 2.23 GB
`Cowry_Shell` | `Cowry_Shell` <br> `Cowry_DOWNSAMPLED` | 1.82 GB <br> 116 MB
`Crab` | `HerrmitCrab` <br> `OkinawaCrab` | 2.38 GB <br> 1.86 GB
`Deer_Mandible` | `Animal_Mandible` <br> `DeerMandible_DOWNSAMPLED` <br> | 2.79 GB <br> 638 MB
`Foam` | `Foam` <br> `Foam_DOWNSAMPLED` <br> `Foam_2` <br> `Foam_2_zoom` | 3.72 GB <br> 238 MB <br> 3.72 GB <br> 3.72 GB
`Hourglass` | `Hourglass` <br> `Hourglass_4X_80kV_Air_9s_1_97um` <br> `Hourglass_longexp_rerun` | 3.72 GB <br> 1.83 GB <br> 3.72 GB
`Kiwi` | `Kiwi` | 2.86 GB
`Loofah` | `Loofah` <br> `Loofah_DOWNSAMPLED` | 2.23 GB <br> 143 MB
`Marine_Gastropods` | `MarineGatropod_1` <br> `MarineGastropod1_DOWNSAMPLED` <br> `MarineGatropod_2` <br> `MarineGastropod2_DOWNSAMPLED` | 2.23 GB <br> 143 MB <br> 2.60 GB <br> 166 MB
`Mussel` | `ClosedMussel1` <br> `ClosedMussel1_DOWNSAMPLED` | 2.23 GB <br> 143 MB
`Oak_Branch` | `Oak_branch` <br> `OakBranch_DOWNSAMPLED` | 2.38 GB <br> 152 MB
`Okinawa_Forams` | `Okinawa_Foram_1` <br> `Okinawa_Foram_2` | 1.84 GB <br> 1.84 GB
`Physalis` | `Physalis` <br> `Physalis_DOWNSAMPLED` | 3.72 GB <br> 238 MB
`Raspberry` | `Raspberry2` <br> `Raspberry2_DOWNSAMPLED` | 2.97 GB <br> 190 MB
`Rope` | `FibreRope1` <br> `FibreRope1_DOWNSAMPLED` | 1.82 GB <br> 686 MB
`Sea_Urchin` | `SeaUrchin` <br> `Cordatum_Shell` <br> `Cordatum_Spine` | 2.60 GB <br> 1.85 GB <br> 183 MB
`Snail` | `Escargot` | 2.60 GB
`Sponge` | `Sponge` | 1.11 GB
Example:
```python
import qim3d
dl = qim3d.io.Downloader()
img = dl.Corals.Coral2_DOWNSAMPLED(load_file = True)
downloader = qim3d.io.Downloader()
data = downloader.Cowry_Shell.Cowry_DOWNSAMPLED(load_file=True)
qim3d.viz.orthogonal(data, cmap = "magma")
```
![cowry shell](assets/screenshots/cowry_shell_slicer.gif)
"""
def __init__(self):
......
......@@ -26,7 +26,7 @@ import qim3d
from qim3d.utils.logger import log
from qim3d.utils.misc import get_file_size, sizeof, stringify_path
from qim3d.utils.system import Memory
from qim3d.utils import ProgressBar
from qim3d.utils.progress_bar import FileLoadingProgressBar
import trimesh
dask.config.set(scheduler="processes")
......@@ -51,10 +51,6 @@ class DataLoader:
load_txrm(path): Load a TXRM/TXM/XRM file from the specified path
load_vol(path): Load a VOL file from the specified path. Path should point to the .vgi metadata file
load(path): Load a file or directory based on the given path
Example:
loader = qim3d.io.DataLoader(virtual_stack=True)
data = loader.load_tiff("image.tif")
"""
def __init__(self, **kwargs):
......@@ -675,10 +671,6 @@ class DataLoader:
ValueError: If the format is not supported
ValueError: If the file or directory does not exist.
MemoryError: If file size exceeds available memory and force_load is not set to True. In check_size function.
Example:
loader = qim3d.io.DataLoader()
data = loader.load("image.tif")
"""
# Stringify path in case it is not already a string
......@@ -832,7 +824,7 @@ def load(
)
if progress_bar and os.name == 'posix':
with ProgressBar(path):
with FileLoadingProgressBar(path):
data = loader.load(path)
else:
data = loader.load(path)
......
......@@ -3,8 +3,12 @@ Exporting data to different formats.
"""
import os
import math
import shutil
import numpy as np
import zarr
import tqdm
from ome_zarr.io import parse_url
from ome_zarr.writer import (
write_image,
......@@ -16,10 +20,6 @@ from ome_zarr.writer import (
from ome_zarr.scale import dask_resize
from ome_zarr.reader import Reader
from ome_zarr import scale
import math
import shutil
from qim3d.utils.logger import log
from scipy.ndimage import zoom
from typing import Any, Callable, Iterator, List, Tuple, Union
import dask.array as da
......@@ -27,6 +27,10 @@ from skimage.transform import (
resize,
)
from qim3d.utils.logger import log
from qim3d.utils.progress_bar import OmeZarrExportProgressBar
from qim3d.utils.ome_zarr import get_n_chunks
ListOfArrayLike = Union[List[da.Array], List[np.ndarray]]
ArrayLike = Union[da.Array, np.ndarray]
......@@ -79,6 +83,8 @@ def export_ome_zarr(
order=0,
replace=False,
method="scaleZYX",
progress_bar:bool = True,
progress_bar_repeat_time = "auto",
):
"""
Export image data to OME-Zarr format with pyramidal downsampling.
......@@ -92,7 +98,7 @@ def export_ome_zarr(
downsample_rate (int, optional): Factor by which to downsample the data for each scale. Must be greater than 1. Defaults to 2.
order (int, optional): Interpolation order to use when downsampling. Defaults to 0 (nearest-neighbor).
replace (bool, optional): Whether to replace the existing directory if it already exists. Defaults to False.
progress_bar (bool, optional): Whether to display progress while writing data to disk. Defaults to True.
Raises:
ValueError: If the directory already exists and `replace` is False.
ValueError: If `downsample_rate` is less than or equal to 1.
......@@ -145,14 +151,23 @@ def export_ome_zarr(
mip, axes = _create_mip(image=data, fmt=fmt, scaler=scaler, axes="zyx")
log.info("Writing data to disk")
write_multiscale(
mip,
kwargs = dict(
pyramid=mip,
group=root,
fmt=fmt,
axes=axes,
name=None,
compute=True,
)
if progress_bar:
n_chunks = get_n_chunks(
shapes = (scaled_data.shape for scaled_data in mip),
dtypes = (scaled_data.dtype for scaled_data in mip)
)
with OmeZarrExportProgressBar(path = path, n_chunks = n_chunks, reapeat_time=progress_bar_repeat_time):
write_multiscale(**kwargs)
else:
write_multiscale(**kwargs)
log.info("All done!")
return
......
......@@ -6,18 +6,20 @@ Example:
```python
import qim3d
vol = qim3d.examples.fly_150x256x256
# Generate synthetic blob
synthetic_blob = qim3d.generate.blob(noise_scale = 0.015)
qim3d.io.save("fly.tif", vol)
qim3d.io.save("fly.tif", synthetic_blob)
```
Volumes can also be saved with one file per slice:
```python
import qim3d
vol = qim3d.examples.fly_150x256x256
# Generate synthetic blob
synthetic_blob = qim3d.generate.blob(noise_scale = 0.015)
qim3d.io.save("slices", vol, basename="fly-slices", sliced_dim=0)
qim3d.io.save("slices", synthetic_blob, basename="fly-slices", sliced_dim=0)
```
"""
......@@ -53,11 +55,6 @@ class DataSaver:
Methods:
save_tiff(path,data): Save data to a TIFF file to the given path.
load(path,data): Save data to the given path.
Example:
image = qim3d.examples.blobs_256x256
saver = qim3d.io.DataSaver(compression=True)
saver.save_tiff("image.tif",image)
"""
def __init__(self, **kwargs):
......@@ -319,12 +316,6 @@ class DataSaver:
ValueError: If the provided path does not exist and self.basename is not provided
ValueError: If a file extension is not provided.
ValueError: if a file with the specified path already exists and replace=False.
Example:
image = qim3d.examples.blobs_256x256
saver = qim3d.io.DataSaver(compression=True)
saver.save("image.tif",image)
"""
path = stringify_path(path)
......@@ -438,8 +429,20 @@ def save(
```python
import qim3d
vol = qim3d.examples.blobs_256x256x256
qim3d.io.save("blobs.tif", vol)
# Generate synthetic blob
synthetic_blob = qim3d.generate.blob(noise_scale = 0.015)
qim3d.io.save("blob.tif", synthetic_blob, replace=True)
```
Volumes can also be saved with one file per slice:
```python
import qim3d
# Generate synthetic blob
synthetic_blob = qim3d.generate.blob(noise_scale = 0.015)
qim3d.io.save("slices", synthetic_blob, basename="blob-slices", sliced_dim=0)
```
"""
......
......@@ -22,11 +22,6 @@ class UNet(nn.Module):
Raises:
ValueError: If `size` is not one of 'small', 'medium', or 'large'.
Example:
```python
model = UNet(size='large')
```
"""
def __init__(
......@@ -104,13 +99,21 @@ class Hyperparameters:
Example:
```
hyperparams = Hyperparameters(model=my_model, n_epochs=20, learning_rate=0.001)
import qim3d
params_dict = hyperparams() # Get the hyperparameters
# This examples shows how to define a UNet model and its hyperparameters.
# Defining the model
my_model = qim3d.models.UNet(size='medium')
# Choosing the hyperparameters
hyperparams = qim3d.models.Hyperparameters(model=my_model, n_epochs=20, learning_rate=0.001)
params_dict = hyperparams() # Get the hyperparameters
optimizer = params_dict['optimizer']
criterion = params_dict['criterion']
n_epochs = params_dict['n_epochs']
```
"""
......
......@@ -48,8 +48,14 @@ def local_thickness(
```python
import qim3d
blobs = qim3d.examples.blobs_256x256 # 2D image
lt_blobs = qim3d.processing.local_thickness(blobs, visualize=True)
# Generate synthetic collection of blobs
num_objects = 15
synthetic_collection, labels = qim3d.generate.collection(num_objects = num_objects)
# Extract one slice to show that localthickness works on 2D slices too
slice = synthetic_collection[:,:,50]
lt_blobs = qim3d.processing.local_thickness(slice, visualize=True)
```
![local thickness 2d](assets/screenshots/local_thickness_2d.png)
......
......@@ -2,6 +2,7 @@ import numpy as np
from skimage import measure, filters
import trimesh
from typing import Tuple, Any
from qim3d.utils.logger import log
def create_mesh(
......@@ -35,7 +36,7 @@ def create_mesh(
threshold=0.5,
dtype='uint8'
)
mesh = qim3d.processing.create_mesh(vol step_size=3)
mesh = qim3d.processing.create_mesh(vol, step_size=3)
qim3d.viz.mesh(mesh.vertices, mesh.faces)
```
......@@ -46,7 +47,7 @@ def create_mesh(
# Compute the threshold level if not provided
if level is None:
level = filters.threshold_otsu(volume)
print(f"Computed level using Otsu's method: {level}")
log.info(f"Computed level using Otsu's method: {level}")
# Apply padding to the volume
if padding is not None:
......@@ -58,15 +59,13 @@ def create_mesh(
mode="constant",
constant_values=padding_value,
)
print(f"Padded volume with {padding} to shape: {volume.shape}")
log.info(f"Padded volume with {padding} to shape: {volume.shape}")
# Call skimage.measure.marching_cubes with user-provided kwargs
verts, faces, normals, values = measure.marching_cubes(
volume, level=level, step_size=step_size, **kwargs
)
print(len(verts))
# Create the Trimesh object
mesh = trimesh.Trimesh(vertices=verts, faces=faces)
......
......@@ -73,7 +73,7 @@ def watershed(bin_vol: np.ndarray, min_distance: int = 5) -> tuple[np.ndarray, i
import qim3d
vol = qim3d.examples.cement_128x128x128
binary = qim3d.processing.filters.gaussian(vol, 2)<60
binary = qim3d.processing.filters.gaussian(vol, sigma = 2)<60
qim3d.viz.slices(binary, axis=1)
```
......