mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-28 21:30:05 +08:00
111 lines
3.1 KiB
Python
111 lines
3.1 KiB
Python
__all__ = ['montage2d']
|
|
|
|
import numpy as np
|
|
from .. import exposure
|
|
|
|
EPSILON = 1e-6
|
|
|
|
|
|
def montage2d(arr_in, fill='mean', rescale_intensity=False, grid_shape=None):
|
|
"""Create a 2-dimensional 'montage' from a 3-dimensional input array
|
|
representing an ensemble of equally shaped 2-dimensional images.
|
|
|
|
For example, ``montage2d(arr_in, fill)`` with the following `arr_in`
|
|
|
|
+---+---+---+
|
|
| 1 | 2 | 3 |
|
|
+---+---+---+
|
|
|
|
will return:
|
|
|
|
+---+---+
|
|
| 1 | 2 |
|
|
+---+---+
|
|
| 3 | * |
|
|
+---+---+
|
|
|
|
Where the '*' patch will be determined by the `fill` parameter.
|
|
|
|
Parameters
|
|
----------
|
|
arr_in: ndarray, shape=[n_images, height, width]
|
|
3-dimensional input array representing an ensemble of n_images
|
|
of equal shape (i.e. [height, width]).
|
|
fill: float or 'mean', optional
|
|
How to fill the 2-dimensional output array when sqrt(n_images)
|
|
is not an integer. If 'mean' is chosen, then fill = arr_in.mean().
|
|
rescale_intensity: bool, optional
|
|
Whether to rescale the intensity of each image to [0, 1].
|
|
grid_shape: tuple, optional
|
|
The desired grid shape for the montage (tiles_y, tiles_x).
|
|
The default aspect ratio is square.
|
|
|
|
Returns
|
|
-------
|
|
arr_out: ndarray, shape=[alpha * height, alpha * width]
|
|
Output array where 'alpha' has been determined automatically to
|
|
fit (at least) the `n_images` in `arr_in`.
|
|
|
|
Examples
|
|
--------
|
|
>>> import numpy as np
|
|
>>> from skimage.util.montage import montage2d
|
|
>>> arr_in = np.arange(3 * 2 * 2).reshape(3, 2, 2)
|
|
>>> arr_in # doctest: +NORMALIZE_WHITESPACE
|
|
array([[[ 0, 1],
|
|
[ 2, 3]],
|
|
[[ 4, 5],
|
|
[ 6, 7]],
|
|
[[ 8, 9],
|
|
[10, 11]]])
|
|
>>> arr_out = montage2d(arr_in)
|
|
>>> arr_out.shape
|
|
(4, 4)
|
|
>>> arr_out
|
|
array([[ 0. , 1. , 4. , 5. ],
|
|
[ 2. , 3. , 6. , 7. ],
|
|
[ 8. , 9. , 5.5, 5.5],
|
|
[ 10. , 11. , 5.5, 5.5]])
|
|
>>> arr_in.mean()
|
|
5.5
|
|
>>> arr_out_nonsquare = montage2d(arr_in, grid_shape=(1, 3))
|
|
>>> arr_out_nonsquare
|
|
array([[ 0., 1., 4., 5., 8., 9.],
|
|
[ 2., 3., 6., 7., 10., 11.]])
|
|
>>> arr_out_nonsquare.shape
|
|
(2, 6)
|
|
|
|
"""
|
|
|
|
assert arr_in.ndim == 3
|
|
|
|
n_images, height, width = arr_in.shape
|
|
|
|
arr_in = arr_in.copy()
|
|
|
|
# -- rescale intensity if necessary
|
|
if rescale_intensity:
|
|
for i in range(n_images):
|
|
arr_in[i] = exposure.rescale_intensity(arr_in[i])
|
|
|
|
# -- determine alpha
|
|
if grid_shape:
|
|
alpha_y, alpha_x = grid_shape
|
|
else:
|
|
alpha_y = alpha_x = int(np.ceil(np.sqrt(n_images)))
|
|
|
|
# -- fill missing patches
|
|
if fill == 'mean':
|
|
fill = arr_in.mean()
|
|
|
|
n_missing = int((alpha_y * alpha_x) - n_images)
|
|
missing = np.ones((n_missing, height, width), dtype=arr_in.dtype) * fill
|
|
arr_out = np.vstack((arr_in, missing))
|
|
|
|
# -- reshape to 2d montage, step by step
|
|
arr_out = arr_out.reshape(alpha_y, alpha_x, height, width)
|
|
arr_out = arr_out.swapaxes(1, 2)
|
|
arr_out = arr_out.reshape(alpha_y * height, alpha_x * width)
|
|
|
|
return arr_out
|