- more arithmetics for Transform
This commit is contained in:
@@ -798,6 +798,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// eq 2.8 The L2 Polynomial Spline Pyramid, Unser et al. 1993
|
/// eq 2.8 The L2 Polynomial Spline Pyramid, Unser et al. 1993
|
||||||
|
/// may be used for future improvements
|
||||||
|
#[expect(dead_code)]
|
||||||
fn u<'a, A, B>(m: usize, z: A) -> Array<Complex<f64>, B>
|
fn u<'a, A, B>(m: usize, z: A) -> Array<Complex<f64>, B>
|
||||||
where
|
where
|
||||||
A: AsArray<'a, Complex<f64>, B>,
|
A: AsArray<'a, Complex<f64>, B>,
|
||||||
@@ -816,6 +818,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// table III The L2 Polynomial Spline Pyramid, Unser et al. 1993
|
/// table III The L2 Polynomial Spline Pyramid, Unser et al. 1993
|
||||||
|
/// may be used for future improvements
|
||||||
|
#[expect(dead_code)]
|
||||||
pub(crate) fn reduction_filter(shape: &[usize]) -> Result<Array<Complex<f64>, D>, Error> {
|
pub(crate) fn reduction_filter(shape: &[usize]) -> Result<Array<Complex<f64>, D>, Error> {
|
||||||
let mut filter: Array<Complex<f64>, D> = ArrayD::ones(shape).into_dimensionality()?;
|
let mut filter: Array<Complex<f64>, D> = ArrayD::ones(shape).into_dimensionality()?;
|
||||||
for (i, &s) in shape.iter().enumerate() {
|
for (i, &s) in shape.iter().enumerate() {
|
||||||
|
|||||||
@@ -10,4 +10,7 @@ pub enum Error {
|
|||||||
ShapeError(#[from] ndarray::ShapeError),
|
ShapeError(#[from] ndarray::ShapeError),
|
||||||
#[error("number of dimensions is not defined")]
|
#[error("number of dimensions is not defined")]
|
||||||
NumberOfDimensionsNotDefined,
|
NumberOfDimensionsNotDefined,
|
||||||
|
/// the dimensionality of the data does not match
|
||||||
|
#[error("dimensionality mismatch: {0} != {0}")]
|
||||||
|
DimensionalityMismatch(usize, usize),
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -75,7 +75,7 @@ impl FixedMu {
|
|||||||
|
|
||||||
/// first_bin, last_bin: center of bin
|
/// first_bin, last_bin: center of bin
|
||||||
/// n_bins >= 2
|
/// n_bins >= 2
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[expect(clippy::too_many_arguments)]
|
||||||
fn parzen(
|
fn parzen(
|
||||||
alpha: f64,
|
alpha: f64,
|
||||||
dalpha: &[f64],
|
dalpha: &[f64],
|
||||||
|
|||||||
+279
-3
@@ -3,13 +3,13 @@ use crate::error::Error;
|
|||||||
use crate::metric::FixedMu;
|
use crate::metric::FixedMu;
|
||||||
use crate::register::{Registration, RegistrationResult, RegistrationStep};
|
use crate::register::{Registration, RegistrationResult, RegistrationStep};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ndarray::{Array, Array2, ArrayD, AsArray, Dimension, Ix2, s};
|
use ndarray::{Array, Array2, ArrayD, ArrayView2, AsArray, Dimension, Ix2, IxDyn, s};
|
||||||
use num::cast::AsPrimitive;
|
use num::cast::AsPrimitive;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_yaml::{from_reader, to_writer};
|
use serde_yaml::{from_reader, to_writer};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Mul;
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// get coordinates resulting from transforming input coordinates, coordinate must have N
|
/// get coordinates resulting from transforming input coordinates, coordinate must have N
|
||||||
@@ -143,7 +143,7 @@ impl<D: Dimension> Mul<Transform<D>> for &Transform<D> {
|
|||||||
impl<D: Dimension> Mul<&Transform<D>> for &Transform<D> {
|
impl<D: Dimension> Mul<&Transform<D>> for &Transform<D> {
|
||||||
type Output = Transform<D>;
|
type Output = Transform<D>;
|
||||||
|
|
||||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
#[expect(clippy::suspicious_arithmetic_impl)]
|
||||||
fn mul(self, rhs: &Transform<D>) -> Self::Output {
|
fn mul(self, rhs: &Transform<D>) -> Self::Output {
|
||||||
let m = self.matrix().dot(&rhs.matrix());
|
let m = self.matrix().dot(&rhs.matrix());
|
||||||
let dm = self.dmatrix().dot(&rhs.matrix()) + self.matrix().dot(&rhs.dmatrix());
|
let dm = self.dmatrix().dot(&rhs.matrix()) + self.matrix().dot(&rhs.dmatrix());
|
||||||
@@ -170,6 +170,202 @@ impl<D: Dimension> Mul<&Transform<D>> for &Transform<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Add for Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
&self + &rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Add<&Transform<D>> for Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn add(self, rhs: &Transform<D>) -> Self::Output {
|
||||||
|
&self + rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Add<Transform<D>> for &Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn add(self, rhs: Transform<D>) -> Self::Output {
|
||||||
|
self + &rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Add<&Transform<D>> for &Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn add(self, rhs: &Transform<D>) -> Self::Output {
|
||||||
|
let m = self.matrix() + &rhs.matrix();
|
||||||
|
let dm = (self.dmatrix().powi(2) + rhs.matrix().powi(2)).sqrt();
|
||||||
|
Self::Output {
|
||||||
|
parameters: m
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(m.slice(s![..self.ndim, self.ndim]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
dparameters: dm
|
||||||
|
.slice(s![..self.ndim, ..])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(dm.slice(s![..self.ndim, ..]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
center: self.center.clone(),
|
||||||
|
shape: self.shape.clone(),
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: self.dimension,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Sub for Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
&self - &rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Sub<&Transform<D>> for Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn sub(self, rhs: &Transform<D>) -> Self::Output {
|
||||||
|
&self - rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Sub<Transform<D>> for &Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Transform<D>) -> Self::Output {
|
||||||
|
self - &rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Sub<&Transform<D>> for &Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn sub(self, rhs: &Transform<D>) -> Self::Output {
|
||||||
|
let m = self.matrix() - &rhs.matrix();
|
||||||
|
let dm = (self.dmatrix().powi(2) + rhs.matrix().powi(2)).sqrt();
|
||||||
|
Self::Output {
|
||||||
|
parameters: m
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(m.slice(s![..self.ndim, self.ndim]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
dparameters: dm
|
||||||
|
.slice(s![..self.ndim, ..])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(dm.slice(s![..self.ndim, ..]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
center: self.center.clone(),
|
||||||
|
shape: self.shape.clone(),
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: self.dimension,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Mul<Transform<D>> for f64 {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Transform<D>) -> Self::Output {
|
||||||
|
rhs * self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Mul<&Transform<D>> for f64 {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn mul(self, rhs: &Transform<D>) -> Self::Output {
|
||||||
|
rhs * self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Mul<f64> for Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn mul(self, rhs: f64) -> Self::Output {
|
||||||
|
&self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Mul<f64> for &Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn mul(self, rhs: f64) -> Self::Output {
|
||||||
|
let m = self.matrix() * rhs;
|
||||||
|
let dm = self.dmatrix() * rhs;
|
||||||
|
Self::Output {
|
||||||
|
parameters: m
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(m.slice(s![..self.ndim, self.ndim]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
dparameters: dm
|
||||||
|
.slice(s![..self.ndim, ..])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(dm.slice(s![..self.ndim, ..]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
center: self.center.clone(),
|
||||||
|
shape: self.shape.clone(),
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: self.dimension,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Div<f64> for Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn div(self, rhs: f64) -> Self::Output {
|
||||||
|
&self / rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> Div<f64> for &Transform<D> {
|
||||||
|
type Output = Transform<D>;
|
||||||
|
|
||||||
|
fn div(self, rhs: f64) -> Self::Output {
|
||||||
|
let m = self.matrix() / rhs;
|
||||||
|
let dm = self.dmatrix() / rhs;
|
||||||
|
Self::Output {
|
||||||
|
parameters: m
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(m.slice(s![..self.ndim, self.ndim]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
dparameters: dm
|
||||||
|
.slice(s![..self.ndim, ..])
|
||||||
|
.flatten()
|
||||||
|
.iter()
|
||||||
|
.chain(dm.slice(s![..self.ndim, ..]).iter())
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
center: self.center.clone(),
|
||||||
|
shape: self.shape.clone(),
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: self.dimension,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: Dimension> Eq for Transform<D> {}
|
impl<D: Dimension> Eq for Transform<D> {}
|
||||||
|
|
||||||
impl<D: Dimension> Default for Transform<D> {
|
impl<D: Dimension> Default for Transform<D> {
|
||||||
@@ -481,6 +677,44 @@ impl<D: Dimension> Transform<D> {
|
|||||||
matrix
|
matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_matrix(mut self, matrix: ArrayView2<f64>) -> Self {
|
||||||
|
let mut parameters = matrix
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.to_vec();
|
||||||
|
parameters.extend(matrix.slice(s![..self.ndim, self.ndim]).to_vec());
|
||||||
|
self.parameters = parameters;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_matrix(&mut self, matrix: ArrayView2<f64>) {
|
||||||
|
let mut parameters = matrix
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.to_vec();
|
||||||
|
parameters.extend(matrix.slice(s![..self.ndim, self.ndim]).to_vec());
|
||||||
|
self.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_dmatrix(mut self, dmatrix: ArrayView2<f64>) -> Self {
|
||||||
|
let mut dparameters = dmatrix
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.to_vec();
|
||||||
|
dparameters.extend(dmatrix.slice(s![..self.ndim, self.ndim]).to_vec());
|
||||||
|
self.dparameters = dparameters;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_dmatrix(&mut self, dmatrix: ArrayView2<f64>) {
|
||||||
|
let mut dparameters = dmatrix
|
||||||
|
.slice(s![..self.ndim, ..self.ndim])
|
||||||
|
.flatten()
|
||||||
|
.to_vec();
|
||||||
|
dparameters.extend(dmatrix.slice(s![..self.ndim, self.ndim]).to_vec());
|
||||||
|
self.dparameters = dparameters;
|
||||||
|
}
|
||||||
|
|
||||||
/// get the inverse transform
|
/// get the inverse transform
|
||||||
pub fn inverse(&self) -> Result<Self, Error> {
|
pub fn inverse(&self) -> Result<Self, Error> {
|
||||||
let matrix = self.matrix();
|
let matrix = self.matrix();
|
||||||
@@ -540,6 +774,48 @@ impl<D: Dimension> Transform<D> {
|
|||||||
let bspline = BSpline::<B, _>::new(&image);
|
let bspline = BSpline::<B, _>::new(&image);
|
||||||
bspline.interpolate_par(self)
|
bspline.interpolate_par(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// the number of dimensions in the view
|
||||||
|
pub fn ndim(&self) -> usize {
|
||||||
|
if let Some(d) = D::NDIM { d } else { self.ndim }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_dimensionality<D2: Dimension>(self) -> Result<Transform<D2>, Error> {
|
||||||
|
if let Some(d) = D2::NDIM {
|
||||||
|
if d == self.ndim() {
|
||||||
|
Ok(Transform {
|
||||||
|
parameters: self.parameters,
|
||||||
|
dparameters: self.dparameters,
|
||||||
|
center: self.center,
|
||||||
|
shape: self.shape,
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: Default::default(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(Error::DimensionalityMismatch(d, self.ndim()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Transform {
|
||||||
|
parameters: self.parameters,
|
||||||
|
dparameters: self.dparameters,
|
||||||
|
center: self.center,
|
||||||
|
shape: self.shape,
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_dyn(self) -> Transform<IxDyn> {
|
||||||
|
Transform {
|
||||||
|
parameters: self.parameters,
|
||||||
|
dparameters: self.dparameters,
|
||||||
|
center: self.center,
|
||||||
|
shape: self.shape,
|
||||||
|
ndim: self.ndim,
|
||||||
|
dimension: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transform<Ix2> {
|
impl Transform<Ix2> {
|
||||||
|
|||||||
Reference in New Issue
Block a user