spyrit.core.meas.DynamicHadamSplit2d

class spyrit.core.meas.DynamicHadamSplit2d(time_dim: int, h: int, M: int = None, order: tensor = None, fast: bool = True, reshape_output: bool = False, img_shape: int | Size | Iterable[int] = None, *, noise_model: Module = Identity(), white_acq: tensor = None, dtype: dtype = torch.float32, device: device = device(type='cpu'))[source]

Bases: DynamicLinearSplit

Simulate 2D Hadamard split acquisitions of a moving scene.

We perform the acquisition of \(2M\) square DMD patterns of size \(h\) by exploiting the Kronecker structure of the 2D Hadamard matrix:

Each measurement is acquired as, for \(k \in \{1, ..., 2M\}\):

\[y_k = \mathcal{N}\left( \sum_{i, j} A_{1d}[r_k, i] x_{t=k}[i, j] A_{1d}[j, c_k] \right),\]

where \(A_{1d} \in \mathbb{R}_+^{2h\times h}\) contains the positive and negative components of a 1d Hadamard matrix, \(x_{t=k} \in \mathbb{R}^{h \times h}\) is \(k^{\rm{th}}\) frame of the video, \((r_k, c_k) = (\left \lfloor k / h \right\rfloor, k \bmod h)\) are the row and column indices of the 1d Hadamard matrix used to generate the 2d Hadamard pattern used at time \(t=k\), \(\mathcal{N} \colon\, \mathbb{R} \to \mathbb{R}\) represents a noise operator (e.g., Gaussian).

Important

Only the forward methods benefit from the fast Hadamard transform algorithm, the adjoint methods do not because the dynamic forward operator (\(H_{\rm{dyn}}\) or \(A_{\rm{dyn}}\)) does not have Kronecker structure.

Note

The splitting of the \(k^{\rm{th}}\) 2D pattern into its positive and negative parts is given by splitting 1D patterns as:

\[\begin{split}H[k, :]^{+} = H_{1d}^{+}[r_k, :] \otimes H_{1d}^{+}[:, c_k] + H_{1d}^{-}[r_k, :] \otimes H_{1d}^{-}[:, c_k] \\ H[k, :]^{-} = H_{1d}^{+}[r_k, :] \otimes H_{1d}^{-}[:, c_k] + H_{1d}^{-}[r_k, :] \otimes H_{1d}^{+}[:, c_k]\end{split}\]
Args:

time_dim (int): dimension index in the input tensor \(x\) that corresponds to time (i.e., the frames dimension).

h (int): Image size \(h\). Must be a power of 2.

M (int): Number of (pos, neg) measurements. If None, it is set to \(h^2\) (no subsampling).

order (torch.tensor, optional): Order matrix \(O\) that defines the measurements to keep. The first component of \(y\) will correspond to the index where order is the highest.

fast (bool, optional): Whether to use the fast Hadamard transform algorithm (i.e. exploit the kronecker structure). If False, it uses matrix-vector products. Defaults to True.

reshape_output (bool, optional): Whether reshape the output of adjoint and pinv methods to images. If False, output are vectors.

img_shape (tuple): Shape of the underlying multi-dimensional array \(x\) over the extended field of view. If None, is set to \((h, h)\).

noise_model (see spyrit.core.noise): Noise model \(\mathcal{N}\). Defaults to torch.nn.Identity().

white_acq (torch.tensor, optional): Eventual spatial gain resulting from detector inhomogeneities and used for dynamic flat-field correction. It can be determined from a “white acquisition” without any object. If None, no correction is applied. Must have self.meas_shape shape.

dtype (torch.dtype, optional): Data type of the measurement matrix. Defaults to torch.float32.

device (torch.device, optional): Device of the measurement matrix. Defaults to torch.device(“cpu”).

Note

The argument order is particularly useful when rearranging the measurements by decreasing variance. The variance matrix can simply be put as order.

Attributes:

M (int): Number of (pos, neg) measurements.

N (int): Number of pixels in the field of view.

L (int): Number of pixels in the extended field of view.

meas_shape (tuple): Shape of the measurements patterns. It is equal to \((h, h)\).

meas_dims (torch.Size): Dimensions of the image the acquisition matrix applies to. Is equal to (-2, -1).

img_shape (tuple): Shape of the underlying multi-dimensional array \(x\) over the extended field of view.

H1d (torch.tensor): Static 1D Hadamard matrix of shape \((h, h)\).

H (torch.tensor): Static 2D Hadamard matrix of shape \((M, N)\) given by \(H_{1d} \otimes H_{1d}\).

A (torch.tensor): Splitted static 2d Hadamard matrix of shape \((2M, N)\) given by \(A_{1d} \otimes A_{1d}\).

H_dyn (torch.tensor): Differential dynamic Hadamard matrix \(H_{\rm{dyn}}\) of shape. \((M, L)\). Must be set using the build_dynamic_forward() method before being accessed.

A_dyn (torch.tensor): Splitted dynamic Hadamard matrix \(A_{\rm{dyn}}\) of shape. \((2M, L)\). Must be set using the build_dynamic_forward() method before being accessed.

order (torch.tensor): Order matrix \(O\). It is used by sort_by_significance(). Defaults to rectangular order (e.g., linear indices).

indices (torch.tensor): Indices used to reorder the measurement vector. It is used by the method reindex().

Example:
>>> import torch
>>> from spyrit.core.meas import DynamicHadamSplit2d
>>>
>>> order = torch.rand([32,32])
>>> # acquisition with 2 * 32 ** 2 splitted Hadamard patterns of size 32x32.
>>> meas_op = DynamicHadamSplit2d(time_dim=1, h=32, M=32**2, order=order, img_shape=(40, 40))
>>> print(meas_op)
DynamicHadamSplit2d(
  (noise_model): Identity()
)
Reference:

[Maitre2024_2] Maitre, T., Bretin, E., Phan, R., Ducros, N., & Sdika, M. (2024, October). Dynamic single-pixel imaging on an extended field of view without warping the patterns. In International Conference on Medical Image Computing and Computer-Assisted Intervention (pp. 275-284). Cham: Springer Nature Switzerland. DOI: 10.1007/978-3-031-72104-5_27

[Maitre2026] (Submitted to TIP) Maitre, T., Bretin, E., Mahieu-Williame, L., Phan, R., Sdika, M., & Ducros, N. (2025). Dual-arm motion-compensated single-pixel imaging. HAL Id: hal-05068181

Methods

adjoint(y[, unvectorize])

Apply adjoint of matrix \(A_{\rm{dyn}}\).

adjoint_H_dyn(m[, unvectorize])

Apply adjoint of matrix \(H_{\rm{dyn}}\).

build_dynamic_forward(motion[, mode, ...])

Builds the dynamic forward operator \(A_{\rm{dyn}}\).

forward(x)

Simulates noisy measurements leveraging the Kronecker structure of the 2d splitted Hadamard transform A.

forward_A_dyn(x)

Simulates noisy dynamic measurements with the splitted dynamic matrix

forward_H(x)

Simulates noisy measurements leveraging the Kronecker structure of the 2d Hadamard transform H.

forward_H_dyn(x)

Simulates noisy dynamic measurements with the dynamic matrix

measure(x)

Simulates noiseless measurements leveraging the Kronecker structure of the 2d splitted Hadamard transform A.

measure_A_dyn(x)

Simulates noiseless dynamic measurements with the splitted dynamic matrix

measure_H(x)

Simulates noiseless measurements leveraging the Kronecker structure of the 2d Hadamard transform H.

measure_H_dyn(x)

Simulates noiseless dynamic measurements with the dynamic matrix

reindex(x[, axis, inverse_permutation])

Sorts a tensor along a specified axis using the indices tensor.

set_matrix_to_inverse(matrix_name)

unvectorize(input)

Unflatten the measured dimensions.

vectorize(input)

Flatten the measured dimensions.