Skip to content

Commit

Permalink
Merge pull request #99 from Aharoni-Lab/black_out_method
Browse files Browse the repository at this point in the history
Combined detector / black area detector / bugfix process frame index
  • Loading branch information
t-sasatani authored Feb 12, 2025
2 parents bf7ee75 + b23571f commit 00542e3
Show file tree
Hide file tree
Showing 14 changed files with 574 additions and 280 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# preprocessing video files
# Preprocessing videos


## Filtering of frames with broken buffers (blocks of a frame)
Expand Down
7 changes: 7 additions & 0 deletions docs/api/process/frame_helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Frame helpers

```{eval-rst}
.. automodule:: mio.process.frame_helper
:members:
:private-members:
```
9 changes: 9 additions & 0 deletions docs/api/process/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# preprocess

```{toctree}
:caption: Preprocess
video
frame_helper
zstack_helper
```
7 changes: 7 additions & 0 deletions docs/api/process/video.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Video preprocessor

```{eval-rst}
.. automodule:: mio.process.video
:members:
:private-members:
```
7 changes: 7 additions & 0 deletions docs/api/process/zstack_helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# z-stack helpers

```{eval-rst}
.. automodule:: mio.process.zstack_helper
:members:
:private-members:
```
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Generic I/O interfaces for miniscopes :)
guide/installation
guide/config
cli/index
api/preprocessing_guide
```

```{toctree}
Expand All @@ -31,9 +32,9 @@ api/exceptions
api/plots/index
api/utils
api/stream_daq
api/preprocessing
api/bit_operation
api/vendor/index
api/process/index
```

```{toctree}
Expand Down
17 changes: 12 additions & 5 deletions mio/data/config/process/denoise_example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ mio_model: mio.models.process.DenoiseConfig
mio_version: 0.6.1
noise_patch:
enable: true
method: gradient # gradient or mean_error
threshold: 20
device_config_id: wireless-200px
comparison_unit: 1000
diff_multiply: 1
method: [gradient, black_area]
mean_error_config:
threshold: 40
device_config_id: wireless-200px
buffer_split: 8
comparison_unit: 1000
diff_multiply: 1
gradient_config:
threshold: 20
black_area_config:
consecutive_threshold: 5
value_threshold: 16
output_result: true
output_noise_patch: true
output_diff: true
Expand Down
19 changes: 13 additions & 6 deletions mio/data/config/process/denoise_example_mean_error.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ mio_model: mio.models.process.DenoiseConfig
mio_version: 0.6.1
noise_patch:
enable: true
method: mean_error
threshold: 40
device_config_id: wireless-200px
comparison_unit: 1000
diff_multiply: 1
method: [mean_error]
mean_error_config:
threshold: 40
device_config_id: wireless-200px
buffer_split: 8
comparison_unit: 1000
diff_multiply: 1
gradient_config:
threshold: 20
black_area_config:
consecutive_threshold: 5
value_threshold: 16
output_result: true
output_noise_patch: true
output_diff: true
Expand All @@ -32,4 +39,4 @@ interactive_display:
display_freq_mask: true
end_frame: -1 #-1 means all frames
output_result: true
output_dir: user_data/output
output_dir: user_data/output
110 changes: 79 additions & 31 deletions mio/models/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Module for preprocessing data.
"""

from typing import Literal, Optional
from typing import List, Literal, Optional

from pydantic import BaseModel, Field

Expand Down Expand Up @@ -38,35 +38,26 @@ class MinimumProjectionConfig(BaseModel):
)


class NoisePatchConfig(BaseModel):
class MSEDetectorConfig(BaseModel):
"""
Configuration for patch based noise handling.
This is used to detect noisy areas in each frame and drop the frame if it is noisy.
Configraiton for detecting invalid frames based on mean squared error.
"""

enable: bool = Field(
default=True,
description="Enable patch based noise handling.",
)
method: Literal["mean_error", "gradient"] = Field(
default="gradient",
description="Method for detecting noise."
"The gradient method is the current recommended method."
"gradient: Detection based on the gradient of the frame row."
"mean_error: Detection based on the mean error with the same row of the previous frame.",
)
threshold: float = Field(
default=20,
description="Threshold for detecting noise."
"This is used together with the method to determine whether a frame is noisy."
"Currently, the value needs to be empirically determined.",
...,
description="Threshold for detecting invalid frames based on mean squared error.",
)
device_config_id: Optional[str] = Field(
default=None,
description="ID of the stream device configuration used for aquiring the video."
"This is used in the mean_error method to compare frames"
" in the units of data transfer buffers.",
)
buffer_size: int = Field(
default=5032,
description="Size of the buffers composing the image."
"This premises that the noisy area will appear in units of buffer_size.",
)
buffer_split: int = Field(
default=1,
description="Number of splits to make in the buffer when detecting noisy areas."
Expand All @@ -77,6 +68,75 @@ class NoisePatchConfig(BaseModel):
default=1,
description="Multiplier for visualizing the diff between the current and previous frame.",
)

_device_config: Optional[StreamDevConfig] = None

@property
def device_config(self) -> StreamDevConfig:
"""
Get the device configuration based on the device_config_id.
This is used in the mean_error method to compare frames in the units of data buffers.
"""
if self._device_config is None:
self._device_config = StreamDevConfig.from_any(self.device_config_id)
return self._device_config


class GradientDetectorConfig(BaseModel):
"""
Configraiton for detecting invalid frames based on gradient.
"""

threshold: float = Field(
...,
description="Threshold for detecting invalid frames based on gradient.",
)


class BlackAreaDetectorConfig(BaseModel):
"""
Configraiton for detecting invalid frames based on black area.
"""

consecutive_threshold: int = Field(
default=5,
description="Number of consecutive black pixels required to classify a row as noisy.",
)
value_threshold: int = Field(
default=0,
description="Pixel intensity value below which a pixel is considered 'black'.",
)


class NoisePatchConfig(BaseModel):
"""
Configuration for patch based noise handling.
This is used to detect noisy areas in each frame and drop the frame if it is noisy.
"""

enable: bool = Field(
default=True,
description="Enable patch based noise handling.",
)
method: List[Literal["mean_error", "gradient", "black_area"]] = Field(
default="gradient",
description="Method for detecting noise."
"gradient: Detection based on the gradient of the frame row."
"mean_error: Detection based on the mean error with the same row of the previous frame."
"black_area: Detection based on the number of consecutive black pixels in a row.",
)
mean_error_config: Optional[MSEDetectorConfig] = Field(
default=None,
description="Configuration for detecting invalid frames based on mean squared error.",
)
gradient_config: Optional[GradientDetectorConfig] = Field(
default=None,
description="Configuration for detecting invalid frames based on gradient.",
)
black_area_config: Optional[BlackAreaDetectorConfig] = Field(
default=None,
description="Configuration for detecting invalid frames based on black area.",
)
output_result: bool = Field(
default=False,
description="Output the output video stream.",
Expand All @@ -97,18 +157,6 @@ class NoisePatchConfig(BaseModel):
description="Output the stack of noisy frames as an independent video stream.",
)

_device_config: Optional[StreamDevConfig] = None

@property
def device_config(self) -> StreamDevConfig:
"""
Get the device configuration based on the device_config_id.
This is used in the mean_error method to compare frames in the units of data buffers.
"""
if self._device_config is None:
self._device_config = StreamDevConfig.from_any(self.device_config_id)
return self._device_config


class FreqencyMaskingConfig(BaseModel):
"""
Expand Down
Loading

0 comments on commit 00542e3

Please sign in to comment.