use nalgebra::*;
use nalgebra::storage::*;
use std::ops::{Mul, MulAssign, Index, };
use crate::dwt::*;
use std::iter::FromIterator;
use std::cell::RefCell;
use std::fmt::Debug;
pub mod ipp;
pub struct Wavelet2D {
states : Vec<ipp::IppDWT2D>,
basis : Basis,
img_side : usize,
bwd_pyr : RefCell<Pyramid<f32>>
}
impl Wavelet2D {
pub fn new(basis : Basis, img_side : usize, n_levels : usize) -> Self {
assert!(n_levels >= 1 && n_levels <= basis.len());
let (low, high) = basis.coefficients();
let mut states = Vec::new();
for i in 0..n_levels {
let state = unsafe {
ipp::build_dwt2d_state(&low[..], &high[..])
};
states.push(state);
}
let bwd_pyr = RefCell::new(Pyramid::new(basis, img_side, Some(states.len())));
Self { states, basis, img_side, bwd_pyr }
}
pub fn empty_pyramid(&self) -> Pyramid<f32> {
Pyramid::new(self.basis, self.img_side, Some(self.states.len()))
}
pub fn forward_mut(&self, src : &impl AsRef<[f32]>, dst : &mut Pyramid<f32>) {
assert!(self.states.len() == dst.levels.len());
unsafe {
for i in 0..self.states.len() {
if i == 0 {
let curr_lvl = &mut dst.levels[i];
super::verify_dwt2d_dimensions(
src.as_ref(),
&curr_lvl.coarse[..],
&curr_lvl.detail_x[..],
&curr_lvl.detail_y[..],
&curr_lvl.detail_xy[..]
);
ipp::apply_forward(
self.states[i].spec_fwd,
self.states[i].buf_fwd,
src.as_ref(),
self.img_side,
self.basis.len(),
&mut curr_lvl.coarse,
&mut curr_lvl.detail_x,
&mut curr_lvl.detail_y,
&mut curr_lvl.detail_xy
);
} else {
let (prev_lvl, curr_lvl) = dst.level_pair_mut(i);
super::verify_dwt2d_dimensions(
&prev_lvl.coarse[..],
&curr_lvl.coarse[..],
&curr_lvl.detail_x[..],
&curr_lvl.detail_y[..],
&curr_lvl.detail_xy[..]
);
ipp::apply_forward(
self.states[i].spec_fwd,
self.states[i].buf_fwd,
&prev_lvl.coarse[..],
self.img_side,
self.basis.len(),
&mut curr_lvl.coarse,
&mut curr_lvl.detail_x,
&mut curr_lvl.detail_y,
&mut curr_lvl.detail_xy
);
}
}
}
}
pub fn backward_mut(&self, src : &Pyramid<f32>, dst : &mut AsMut<[f32]>) {
assert!(self.states.len() == src.levels.len());
let mut bwd_pyr = self.bwd_pyr.borrow_mut();
unsafe {
for i in (0..self.states.len()).rev().skip(1) {
if i == 0 {
let curr_lvl = &bwd_pyr.levels[0];
ipp::apply_backward(
self.states[i].spec_bwd,
self.states[i].buf_bwd,
dst.as_mut(),
self.img_side,
self.basis.len(),
&curr_lvl.coarse[..],
&curr_lvl.detail_x[..],
&curr_lvl.detail_y[..],
&curr_lvl.detail_xy[..]
);
} else {
let curr_lvl = &mut bwd_pyr.levels[i-1];
let prev_lvl = &src.levels[i];
ipp::apply_backward(
self.states[i].spec_bwd,
self.states[i].buf_bwd,
curr_lvl.coarse.as_mut(),
self.img_side,
self.basis.len(),
&prev_lvl.coarse[..],
&prev_lvl.detail_x[..],
&prev_lvl.detail_y[..],
&prev_lvl.detail_xy[..]
);
}
}
}
}
}
pub struct PyramidLevel<N>
where
N : Scalar + Debug
{
detail_x : Vec<N>,
detail_y : Vec<N>,
detail_xy : Vec<N>,
coarse : Vec<N>,
side_len : usize
}
impl<N> PyramidLevel<N>
where
N : From<f32> + Scalar + Clone
{
pub fn new(side_len : usize, filt_len : usize) -> Self {
let mut coarse = Vec::from_iter((0..side_len.pow(2u32)).map(|_| N::from(0.0) ));
let mut detail_x = coarse.clone();
let mut detail_y = coarse.clone();
let mut detail_xy = coarse.clone();
Self {
detail_x,
detail_y,
detail_xy,
coarse,
side_len
}
}
pub fn coarse(&self) -> &[N] {
&self.coarse[..]
}
pub fn horizontal_detail(&self) -> &[N] {
&self.detail_x[..]
}
pub fn vertical_detail(&self) -> &[N] {
&self.detail_y[..]
}
pub fn diagonal_detail(&self) -> &[N] {
&self.detail_xy[..]
}
}
pub struct Pyramid<N>
where
N : From<f32> + Scalar + Clone
{
levels : Vec<PyramidLevel<N>>
}
impl<N> Pyramid<N>
where
N : From<f32> + Scalar + Clone
{
pub fn new(basis : Basis, side : usize, n_levels : Option<usize>) -> Self {
let n_levels = n_levels.unwrap_or(dwt_max_levels(side));
let filt_len = basis.len();
let levels = (0..n_levels)
.map(|lvl| PyramidLevel::new(side / (2usize).pow(lvl as u32 + 1), filt_len) )
.collect();
Self { levels }
}
pub fn level_pair_mut(&mut self, last : usize) -> (&mut PyramidLevel<N>, &mut PyramidLevel<N>) {
index_and_prev_mut(&mut self.levels[..], last)
}
pub fn horizontal(&self, level : usize) -> &[N] {
&self.levels[level].detail_x[..]
}
pub fn vertical(&self, level : usize) -> &[N] {
&self.levels[level].detail_y[..]
}
pub fn diagonal(&self, level : usize) -> &[N] {
&self.levels[level].detail_xy[..]
}
pub fn coarse(&self, level : usize) -> &[N] {
&self.levels[level].coarse[..]
}
pub fn horizontal_mut(&mut self, level : usize) -> &mut [N] {
&mut self.levels[level].detail_x[..]
}
pub fn vertical_mut(&mut self, level : usize) -> &mut [N] {
&mut self.levels[level].detail_y[..]
}
pub fn diagonal_mut(&mut self, level : usize) -> &mut [N] {
&mut self.levels[level].detail_xy[..]
}
pub fn coarse_mut(&mut self, level : usize) -> &mut [N] {
&mut self.levels[level].coarse[..]
}
fn full_level_mut(&mut self, level : usize) -> (&mut [N], &mut [N], &mut [N], &mut [N]) {
let level = &mut self.levels[level];
(
&mut level.coarse[..],
&mut level.detail_x[..],
&mut level.detail_y[..],
&mut level.detail_xy[..]
)
}
fn full_level(&self, level : usize) -> (&[N], &[N], &[N], &[N]) {
let level = &self.levels[level];
(
&level.coarse[..],
&level.detail_x[..],
&level.detail_y[..],
&level.detail_xy[..]
)
}
}
#[test]
fn image_dwt() {
use crate::dwt::bank;
use crate::signal::gen;
use std::iter::FromIterator;
use super::*;
use crate::display_as_mat;
let img_len = 64;
let filt_len = 4;
let half_len = img_len / 2;
let mut img = gen::step2d(img_len);
let dst_len = (half_len - filt_len / 2) as usize;
let wav = Wavelet::new(Basis::Daubechies(4, false), img_len, 1);
let mut pyr = wav.generate_pyramid();
wav.forward(&img, &mut pyr);
let dst_offset = dst_len as usize;
let dst_ncols = dst_len as usize;
println!("Approx = {}", display_as_mat(pyr.coarse(0), dst_len));
println!("Detail X = {}", display_as_mat(pyr.horizontal(0), dst_len));
println!("Detail Y = {}", display_as_mat(pyr.vertical(0), dst_len));
println!("Detail XY = {}", display_as_mat(pyr.diagonal(0), dst_len));
}
impl Wavelet2D {
}