feat: Add Bioxel asset catalog and layer management functionality
- Introduced a new asset catalog definition file for Blender to manage Bioxel assets. - Implemented layer caching and snapshot functionality in `layer.py`, allowing for VDB file generation and low-resolution snapshots. - Created node management functions in `node.py` for handling Bioxel nodes within Blender's Geometry Node Editor. - Added an operator to extract mesh data from selected nodes in `structure.py`. - Developed UI panels in `panels.py` for layer management, including import options and layer library display.
This commit is contained in:
@@ -78,8 +78,8 @@ class Layer():
|
||||
mask_frame = mask[f, :, :, :]
|
||||
if smooth > 0:
|
||||
mask_frame = scipy.median_filter(mask_frame.astype(np.float32),
|
||||
mode="nearest",
|
||||
size=smooth)
|
||||
mode="nearest",
|
||||
size=smooth)
|
||||
# mask_frame = scipy.median_filter(
|
||||
# mask_frame.astype(np.float32), size=2)
|
||||
mask_frames += (mask_frame,)
|
||||
@@ -88,8 +88,8 @@ class Layer():
|
||||
mask_frame = mask[:, :, :]
|
||||
if smooth > 0:
|
||||
mask_frame = scipy.median_filter(mask_frame.astype(np.float32),
|
||||
mode="nearest",
|
||||
size=smooth)
|
||||
mode="nearest",
|
||||
size=smooth)
|
||||
# mask_frame = scipy.median_filter(
|
||||
# mask_frame.astype(np.float32), size=2)
|
||||
mask_frames += (mask_frame,)
|
||||
@@ -150,3 +150,32 @@ class Layer():
|
||||
|
||||
mat_scale = transforms3d.zooms.zfdir2aff(factors[0])
|
||||
self.affine = np.dot(self.affine, mat_scale)
|
||||
|
||||
def snapshot(self, shape: tuple, smooth: int = 0):
|
||||
if len(shape) != 3:
|
||||
raise Exception("Shape must be 3 dim")
|
||||
|
||||
data = self.data
|
||||
|
||||
snapshot = data[0, :, :, :, :]
|
||||
|
||||
factors = np.divide(self.shape, shape)
|
||||
zoom_factors = [1 / f for f in factors]
|
||||
order = 0 if snapshot.dtype == bool else 1
|
||||
snapshot = ndi.zoom(snapshot,
|
||||
zoom_factors+[1.0],
|
||||
mode="nearest",
|
||||
grid_mode=False,
|
||||
order=order)
|
||||
|
||||
snapshot = snapshot.astype(np.float32)
|
||||
|
||||
if self.kind in ['scalar', 'vector', 'color']:
|
||||
mn = float(np.nanmin(snapshot))
|
||||
mx = float(np.nanmax(snapshot))
|
||||
if mx - mn > 1e-8:
|
||||
snapshot = (snapshot - mn) / (mx - mn)
|
||||
else:
|
||||
snapshot = np.clip(snapshot, 0.0, 1.0)
|
||||
|
||||
return snapshot
|
||||
|
||||
@@ -39,7 +39,6 @@ from . import _ni_support
|
||||
from . import _nd_image
|
||||
|
||||
|
||||
|
||||
def _invalid_origin(origin, lenw):
|
||||
return (origin < -(lenw // 2)) or (origin > (lenw - 1) // 2)
|
||||
|
||||
@@ -73,7 +72,6 @@ def _complex_via_real_components(func, input, weights, output, cval, **kwargs):
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def correlate1d(input, weights, axis=-1, output=None, mode="reflect",
|
||||
cval=0.0, origin=0):
|
||||
"""Calculate a 1-D correlation along the given axis.
|
||||
@@ -133,7 +131,6 @@ def correlate1d(input, weights, axis=-1, output=None, mode="reflect",
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def convolve1d(input, weights, axis=-1, output=None, mode="reflect",
|
||||
cval=0.0, origin=0):
|
||||
"""Calculate a 1-D convolution along the given axis.
|
||||
@@ -205,7 +202,6 @@ def _gaussian_kernel1d(sigma, order, radius):
|
||||
return q * phi_x
|
||||
|
||||
|
||||
|
||||
def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
|
||||
mode="reflect", cval=0.0, truncate=4.0, *, radius=None):
|
||||
"""1-D Gaussian filter.
|
||||
@@ -274,7 +270,6 @@ def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
|
||||
return correlate1d(input, weights, axis, output, mode, cval, 0)
|
||||
|
||||
|
||||
|
||||
def gaussian_filter(input, sigma, order=0, output=None,
|
||||
mode="reflect", cval=0.0, truncate=4.0, *, radius=None,
|
||||
axes=None):
|
||||
@@ -381,7 +376,6 @@ def gaussian_filter(input, sigma, order=0, output=None,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def prewitt(input, axis=-1, output=None, mode="reflect", cval=0.0):
|
||||
"""Calculate a Prewitt filter.
|
||||
|
||||
@@ -443,7 +437,6 @@ def prewitt(input, axis=-1, output=None, mode="reflect", cval=0.0):
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def sobel(input, axis=-1, output=None, mode="reflect", cval=0.0):
|
||||
"""Calculate a Sobel filter.
|
||||
|
||||
@@ -501,7 +494,6 @@ def sobel(input, axis=-1, output=None, mode="reflect", cval=0.0):
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def generic_laplace(input, derivative2, output=None, mode="reflect",
|
||||
cval=0.0,
|
||||
extra_arguments=(),
|
||||
@@ -549,7 +541,6 @@ def generic_laplace(input, derivative2, output=None, mode="reflect",
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def laplace(input, output=None, mode="reflect", cval=0.0):
|
||||
"""N-D Laplace filter based on approximate second derivatives.
|
||||
|
||||
@@ -584,7 +575,6 @@ def laplace(input, output=None, mode="reflect", cval=0.0):
|
||||
return generic_laplace(input, derivative2, output, mode, cval)
|
||||
|
||||
|
||||
|
||||
def gaussian_laplace(input, sigma, output=None, mode="reflect",
|
||||
cval=0.0, **kwargs):
|
||||
"""Multidimensional Laplace filter using Gaussian second derivatives.
|
||||
@@ -637,7 +627,6 @@ def gaussian_laplace(input, sigma, output=None, mode="reflect",
|
||||
extra_keywords=kwargs)
|
||||
|
||||
|
||||
|
||||
def generic_gradient_magnitude(input, derivative, output=None,
|
||||
mode="reflect", cval=0.0,
|
||||
extra_arguments=(), extra_keywords=None):
|
||||
@@ -690,7 +679,6 @@ def generic_gradient_magnitude(input, derivative, output=None,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def gaussian_gradient_magnitude(input, sigma, output=None,
|
||||
mode="reflect", cval=0.0, **kwargs):
|
||||
"""Multidimensional gradient magnitude using Gaussian derivatives.
|
||||
@@ -792,7 +780,6 @@ def _correlate_or_convolve(input, weights, output, mode, cval, origin,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def correlate(input, weights, output=None, mode='reflect', cval=0.0,
|
||||
origin=0):
|
||||
"""
|
||||
@@ -856,7 +843,6 @@ def correlate(input, weights, output=None, mode='reflect', cval=0.0,
|
||||
origin, False)
|
||||
|
||||
|
||||
|
||||
def convolve(input, weights, output=None, mode='reflect', cval=0.0,
|
||||
origin=0):
|
||||
"""
|
||||
@@ -967,7 +953,6 @@ def convolve(input, weights, output=None, mode='reflect', cval=0.0,
|
||||
origin, True)
|
||||
|
||||
|
||||
|
||||
def uniform_filter1d(input, size, axis=-1, output=None,
|
||||
mode="reflect", cval=0.0, origin=0):
|
||||
"""Calculate a 1-D uniform filter along the given axis.
|
||||
@@ -1018,7 +1003,6 @@ def uniform_filter1d(input, size, axis=-1, output=None,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def uniform_filter(input, size=3, output=None, mode="reflect",
|
||||
cval=0.0, origin=0, *, axes=None):
|
||||
"""Multidimensional uniform filter.
|
||||
@@ -1088,7 +1072,6 @@ def uniform_filter(input, size=3, output=None, mode="reflect",
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def minimum_filter1d(input, size, axis=-1, output=None,
|
||||
mode="reflect", cval=0.0, origin=0):
|
||||
"""Calculate a 1-D minimum filter along the given axis.
|
||||
@@ -1145,7 +1128,6 @@ def minimum_filter1d(input, size, axis=-1, output=None,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def maximum_filter1d(input, size, axis=-1, output=None,
|
||||
mode="reflect", cval=0.0, origin=0):
|
||||
"""Calculate a 1-D maximum filter along the given axis.
|
||||
@@ -1302,7 +1284,6 @@ def _min_or_max_filter(input, size, footprint, structure, output, mode,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def minimum_filter(input, size=None, footprint=None, output=None,
|
||||
mode="reflect", cval=0.0, origin=0, *, axes=None):
|
||||
"""Calculate a multidimensional minimum filter.
|
||||
@@ -1350,7 +1331,6 @@ def minimum_filter(input, size=None, footprint=None, output=None,
|
||||
cval, origin, 1, axes)
|
||||
|
||||
|
||||
|
||||
def maximum_filter(input, size=None, footprint=None, output=None,
|
||||
mode="reflect", cval=0.0, origin=0, *, axes=None):
|
||||
"""Calculate a multidimensional maximum filter.
|
||||
@@ -1398,7 +1378,6 @@ def maximum_filter(input, size=None, footprint=None, output=None,
|
||||
cval, origin, 0, axes)
|
||||
|
||||
|
||||
|
||||
def _rank_filter(input, rank, size=None, footprint=None, output=None,
|
||||
mode="reflect", cval=0.0, origin=0, operation='rank',
|
||||
axes=None):
|
||||
@@ -1491,7 +1470,6 @@ def _rank_filter(input, rank, size=None, footprint=None, output=None,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def rank_filter(input, rank, size=None, footprint=None, output=None,
|
||||
mode="reflect", cval=0.0, origin=0, *, axes=None):
|
||||
"""Calculate a multidimensional rank filter.
|
||||
@@ -1535,7 +1513,6 @@ def rank_filter(input, rank, size=None, footprint=None, output=None,
|
||||
origin, 'rank', axes=axes)
|
||||
|
||||
|
||||
|
||||
def median_filter(input, size=None, footprint=None, output=None,
|
||||
mode="reflect", cval=0.0, origin=0, *, axes=None):
|
||||
"""
|
||||
@@ -1586,7 +1563,6 @@ def median_filter(input, size=None, footprint=None, output=None,
|
||||
origin, 'median', axes=axes)
|
||||
|
||||
|
||||
|
||||
def percentile_filter(input, percentile, size=None, footprint=None,
|
||||
output=None, mode="reflect", cval=0.0, origin=0, *,
|
||||
axes=None):
|
||||
@@ -1630,7 +1606,6 @@ def percentile_filter(input, percentile, size=None, footprint=None,
|
||||
cval, origin, 'percentile', axes=axes)
|
||||
|
||||
|
||||
|
||||
def generic_filter1d(input, function, filter_size, axis=-1,
|
||||
output=None, mode="reflect", cval=0.0, origin=0,
|
||||
extra_arguments=(), extra_keywords=None):
|
||||
@@ -1718,7 +1693,6 @@ def generic_filter1d(input, function, filter_size, axis=-1,
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def generic_filter(input, function, size=None, footprint=None,
|
||||
output=None, mode="reflect", cval=0.0, origin=0,
|
||||
extra_arguments=(), extra_keywords=None):
|
||||
@@ -1846,4 +1820,4 @@ def generic_filter(input, function, size=None, footprint=None,
|
||||
mode = _ni_support._extend_mode_to_code(mode)
|
||||
_nd_image.generic_filter(input, function, footprint, output, mode,
|
||||
cval, origins, extra_arguments, extra_keywords)
|
||||
return output
|
||||
return output
|
||||
|
||||
@@ -11,7 +11,7 @@ def _prepad_for_spline_filter(input, mode, cval):
|
||||
npad = 12
|
||||
if mode == 'grid-constant':
|
||||
padded = np.pad(input, npad, mode='constant',
|
||||
constant_values=cval)
|
||||
constant_values=cval)
|
||||
elif mode == 'nearest':
|
||||
padded = np.pad(input, npad, mode='edge')
|
||||
else:
|
||||
@@ -21,6 +21,7 @@ def _prepad_for_spline_filter(input, mode, cval):
|
||||
padded = input
|
||||
return padded, npad
|
||||
|
||||
|
||||
def spline_filter1d(input, order=3, axis=-1, output=np.float64,
|
||||
mode='mirror'):
|
||||
"""
|
||||
|
||||
@@ -83,7 +83,8 @@ def _get_output(output, input, shape=None, complex_output=False):
|
||||
elif isinstance(output, (type, np.dtype)):
|
||||
# Classes (like `np.float32`) and dtypes are interpreted as dtype
|
||||
if complex_output and np.dtype(output).kind != 'c':
|
||||
warnings.warn("promoting specified output dtype to complex", stacklevel=3)
|
||||
warnings.warn(
|
||||
"promoting specified output dtype to complex", stacklevel=3)
|
||||
output = np.promote_types(output, np.complex64)
|
||||
output = np.zeros(shape, dtype=output)
|
||||
elif isinstance(output, str):
|
||||
|
||||
@@ -7,4 +7,4 @@ def normalize_axis_index(axis, ndim):
|
||||
|
||||
if axis < 0:
|
||||
axis = axis + ndim
|
||||
return axis
|
||||
return axis
|
||||
|
||||
@@ -3,6 +3,7 @@ import numpy as np
|
||||
from .. import scipy as ndi
|
||||
from ._utils import convert_to_float
|
||||
|
||||
|
||||
def _clip_warp_output(input_image, output_image, mode, cval, clip):
|
||||
"""Clip output image to range of values of input image.
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ _integer_types = (
|
||||
np.uintp,
|
||||
np.uintc,
|
||||
)
|
||||
_integer_ranges = {t: (np.iinfo(t).min, np.iinfo(t).max) for t in _integer_types}
|
||||
_integer_ranges = {t: (np.iinfo(t).min, np.iinfo(t).max)
|
||||
for t in _integer_types}
|
||||
dtype_range = {
|
||||
bool: (False, True),
|
||||
np.bool_: (False, True),
|
||||
@@ -175,7 +176,8 @@ def _scale(a, n, m, copy=True):
|
||||
# downscale with precision loss
|
||||
if copy:
|
||||
b = np.empty(a.shape, _dtype_bits(kind, m))
|
||||
np.floor_divide(a, 2 ** (n - m), out=b, dtype=a.dtype, casting='unsafe')
|
||||
np.floor_divide(a, 2 ** (n - m), out=b,
|
||||
dtype=a.dtype, casting='unsafe')
|
||||
return b
|
||||
else:
|
||||
a //= 2 ** (n - m)
|
||||
@@ -282,7 +284,8 @@ def _convert(image, dtype, force_copy=False, uniform=False):
|
||||
return image
|
||||
|
||||
if not (dtype_in in _supported_types and dtype_out in _supported_types):
|
||||
raise ValueError(f'Cannot convert from {dtypeobj_in} to ' f'{dtypeobj_out}.')
|
||||
raise ValueError(
|
||||
f'Cannot convert from {dtypeobj_in} to ' f'{dtypeobj_out}.')
|
||||
|
||||
if kind_in in 'ui':
|
||||
imin_in = np.iinfo(dtype_in).min
|
||||
@@ -318,7 +321,8 @@ def _convert(image, dtype, force_copy=False, uniform=False):
|
||||
|
||||
if not uniform:
|
||||
if kind_out == 'u':
|
||||
image_out = np.multiply(image, imax_out, dtype=computation_type)
|
||||
image_out = np.multiply(
|
||||
image, imax_out, dtype=computation_type)
|
||||
else:
|
||||
image_out = np.multiply(
|
||||
image, (imax_out - imin_out) / 2, dtype=computation_type
|
||||
@@ -327,7 +331,8 @@ def _convert(image, dtype, force_copy=False, uniform=False):
|
||||
np.rint(image_out, out=image_out)
|
||||
np.clip(image_out, imin_out, imax_out, out=image_out)
|
||||
elif kind_out == 'u':
|
||||
image_out = np.multiply(image, imax_out + 1, dtype=computation_type)
|
||||
image_out = np.multiply(
|
||||
image, imax_out + 1, dtype=computation_type)
|
||||
np.clip(image_out, 0, imax_out, out=image_out)
|
||||
else:
|
||||
image_out = np.multiply(
|
||||
|
||||
Reference in New Issue
Block a user