Skip to content

Commit

Permalink
Row noise removal node
Browse files Browse the repository at this point in the history
  • Loading branch information
rroohhh committed Apr 16, 2024
1 parent 59d94b6 commit bc3f942
Show file tree
Hide file tree
Showing 17 changed files with 1,312 additions and 44 deletions.
39 changes: 14 additions & 25 deletions capture_calibrated.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
input:
type: WebcamInput
device: {{ webcam-device }}

decode:
type: DualFrameRawDecoder
input: <input

calibrate:
input: <decode
type: Calibrate
darkframe: {{ darkframe }}
type: RawDirectoryReader
file-pattern: test/Darkbox-Timelapse-Clock-Sequence/*.raw12
width: 4096
height: 2160

calib_cache:
type: Cache
input: <calibrate
height: 3072
bit-depth: 12
internal-loop: true
cache-frames: true

bitdepth_conv:
type: BitDepthConverter
input: <calib_cache
type: GpuBitDepthConverter
input: <input

debayer:
type: Debayer
type: DebayerResolutionLoss
input: <bitdepth_conv

display:
# out:
# type: BenchmarkSink
# input: <debayer

Display:
type: Display
input: <debayer

save:
type: RawBlobWriter
path: {{ out-file }}
input: <calib_cache
31 changes: 31 additions & 0 deletions row_noise_mean_model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# #[derive(serde::Deserialize)]
# pub struct PerHalfWeights {
# dark_col_mean_weights: Option<[f32; 2 * NUM_DARKCOLS]>,
# #[serde(default)]
# green_diff_weights: Vec<[f32; 2]>,

# // index -> lags
# // 0, 1, 2, 3, 4 -> 0, -1, 1, -2, 2
# #[serde(default)]
# dark_col_row_weights: Vec<[[f32; 2 * NUM_DARKCOLS]; 2]>,
# #[serde(default)]
# offset: f32,
# }

# #[derive(serde::Deserialize)]
# pub struct RowNoiseRemovalModel {
# weights_odd: PerHalfWeights,
# weights_even: PerHalfWeights,
# }



weights_even:
dark_col_row_weights:
- - [0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

weights_odd:
dark_col_row_weights:
- - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, 0.0375]
6 changes: 4 additions & 2 deletions src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ use crate::{
bitdepth_convert::BitDepthConverter,
dual_frame_raw_decoder::{DualFrameRawDecoder, ReverseDualFrameRawDecoder},
fp_to_uint::Fp32ToUInt16,
row_noise_removal::RowNoiseRemoval,
sz3::SZ3Compress,
zstd::ZstdBlobReader,
},
nodes_gpu::{
bitdepth_convert::GpuBitDepthConverter,
calibrate::Calibrate,
color_voodoo::ColorVoodoo,
darkframe_subtract::DarkframeSubtract,
debayer::Debayer,
debayer_resolution_loss::DebayerResolutionLoss,
histogram::Histogram,
Expand Down Expand Up @@ -91,7 +92,8 @@ generate_dynamic_node_creation_functions![
Split,
SZ3Compress,
ZstdBlobReader,
Calibrate,
DarkframeSubtract,
RowNoiseRemoval,
Histogram,
#[cfg(target_os = "linux")]
Plot,
Expand Down
38 changes: 33 additions & 5 deletions src/nodes_cpu/bitdepth_convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,26 @@ use async_trait::async_trait;

pub struct BitDepthConverter {
input: InputProcessingNode,
target_bitdepth: u64,
context: ProcessingContext,
}
impl Parameterizable for BitDepthConverter {
fn describe_parameters() -> ParametersDescriptor {
ParametersDescriptor::new().with("input", Mandatory(NodeInputParameter))
ParametersDescriptor::new()
.with("input", Mandatory(NodeInputParameter))
.with("to", WithDefault(U8(), IntRangeValue(8)))
}

fn from_parameters(
mut parameters: Parameters,
_is_input_to: &[NodeID],
context: &ProcessingContext,
) -> Result<Self> {
Ok(Self { input: parameters.take("input")?, context: context.clone() })
Ok(Self {
input: parameters.take("input")?,
context: context.clone(),
target_bitdepth: parameters.take("to")?,
})
}
}

Expand All @@ -40,12 +47,12 @@ impl ProcessingNode for BitDepthConverter {
.context
.ensure_cpu_buffer::<Raw>(&input)
.context("Wrong input format for BitDepthConverter")?;
let interp = Raw { bit_depth: 8, ..frame.interp };
let interp = Raw { bit_depth: self.target_bitdepth, ..frame.interp };
let mut new_buffer = unsafe { self.context.get_uninit_cpu_buffer(interp.required_bytes()) };

if frame.interp.bit_depth == 8 {
if frame.interp.bit_depth == self.target_bitdepth {
return Ok(input);
} else if frame.interp.bit_depth == 12 {
} else if (frame.interp.bit_depth == 12) && (self.target_bitdepth == 8) {
new_buffer.as_mut_slice(|new_buffer| {
frame.storage.as_slice(|frame_storage| {
for (input, output) in
Expand All @@ -56,7 +63,28 @@ impl ProcessingNode for BitDepthConverter {
}
})
});
} else if (frame.interp.bit_depth == 12) && (self.target_bitdepth == 16) {
new_buffer.as_mut_slice(|new_buffer| {
frame.storage.as_slice(|frame_storage| {
let new_buffer: &mut [u16] = bytemuck::cast_slice_mut(new_buffer);
for (input, output) in
frame_storage.chunks_exact(3).zip(new_buffer.chunks_exact_mut(2))
{
let a: u16 = ((input[0] as u16) << 4) | ((input[1] >> 4) as u16);
let b: u16 = (((input[1] & 0xf) as u16) << 8) | input[2] as u16;

output[0] = a;
output[1] = b;
}
})
});
} else {
println!(
"using unoptimized bitdepth conversion path from {} to {}",
frame.interp.bit_depth, self.target_bitdepth
);
assert_eq!(self.target_bitdepth, 8);

let mut rest_value: u32 = 0;
let mut rest_bits: u32 = 0;
let mut pos = 0;
Expand Down
1 change: 1 addition & 0 deletions src/nodes_cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ pub mod benchmark_sink;
pub mod bitdepth_convert;
pub mod dual_frame_raw_decoder;
pub mod fp_to_uint;
pub mod row_noise_removal;
pub mod sz3;
pub mod zstd;
108 changes: 108 additions & 0 deletions src/nodes_cpu/rgb_to_rgba.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use crate::pipeline_processing::{
node::InputProcessingNode,
parametrizable::{Parameterizable, Parameters, ParametersDescriptor},
payload::Payload,
};
use anyhow::{Context, Result};


use crate::pipeline_processing::{
frame::{Frame, FrameInterpretation, Raw},
node::{Caps, NodeID, ProcessingNode, Request},
parametrizable::prelude::*,
processing_context::ProcessingContext,
};
use async_trait::async_trait;

pub struct RgbToRgbaToFlutter {
input: InputProcessingNode,
context: ProcessingContext,
sink: Stream
}
impl Parameterizable for BitDepthConverter {
fn describe_parameters() -> ParametersDescriptor {
ParametersDescriptor::new().with("input", Mandatory(NodeInputParameter))
}

fn from_parameters(
mut parameters: Parameters,
_is_input_to: &[NodeID],
context: &ProcessingContext,
) -> Result<Self> {
Ok(Self { input: parameters.take("input")?, context: context.clone() })
}
}

#[async_trait]
impl ProcessingNode for BitDepthConverter {
async fn pull(&self, request: Request) -> Result<Payload> {
let frame = self.input.pull(request).await?;
let frame = processing_context.ensure_cpu_buffer::<Rgb>(&frame).unwrap();
let mut rgba_buffer = vec![0u8; (frame.interp.width * frame.interp.height * 4) as usize];

let interp = Rgba { width: frame.interp.width, height: frame.interp.height, fps: frame.interp.fps };
let mut new_buffer = unsafe { self.context.get_uninit_cpu_buffer(interp.required_bytes()) };

frame.storage.as_slice(|frame| {
new_buffer.storage.as_slice_mut(|frame| {
for (src, dest) in frame.chunks_exact(3).zip(rgba_buffer.chunks_exact_mut(4)) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = 255;

}
});


if frame.interp.bit_depth == 8 {
return Ok(input);
} else if frame.interp.bit_depth == 12 {
new_buffer.as_mut_slice(|new_buffer| {
frame.storage.as_slice(|frame_storage| {
for (input, output) in
frame_storage.chunks_exact(3).zip(new_buffer.chunks_exact_mut(2))
{
output[0] = input[0];
output[1] = (input[1] << 4) | (input[2] >> 4);
}
})
});
} else {
let mut rest_value: u32 = 0;
let mut rest_bits: u32 = 0;
let mut pos = 0;
new_buffer.as_mut_slice(|new_buffer| {
frame.storage.as_slice(|frame_storage| {
for value in frame_storage.iter() {
let bits_more_than_bit_depth =
(rest_bits as i32 + 8) - frame.interp.bit_depth as i32;
if bits_more_than_bit_depth >= 0 {
let new_n_bit_value: u32 = rest_value
.wrapping_shl(frame.interp.bit_depth as u32 - rest_bits)
| value.wrapping_shr(8 - bits_more_than_bit_depth as u32) as u32;
new_buffer[pos] = (if frame.interp.bit_depth > 8 {
new_n_bit_value.wrapping_shr(frame.interp.bit_depth as u32 - 8)
} else {
new_n_bit_value
} as u8);
pos += 1;

rest_bits = bits_more_than_bit_depth as u32;
rest_value = (value & (2u32.pow(rest_bits as u32) - 1) as u8) as u32
} else {
rest_bits += 8;
rest_value = (rest_value << 8) | *value as u32;
};
}
})
});
}

let new_frame = Frame { storage: new_buffer, interp };

Ok(Payload::from(new_frame))
}

fn get_caps(&self) -> Caps { self.input.get_caps() }
}
Loading

0 comments on commit bc3f942

Please sign in to comment.