Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/regexident/median
An implementation of an efficient O(n) median filter in Rust.
https://github.com/regexident/median
dsp embedded filter median rust
Last synced: about 2 months ago
JSON representation
An implementation of an efficient O(n) median filter in Rust.
- Host: GitHub
- URL: https://github.com/regexident/median
- Owner: regexident
- License: mpl-2.0
- Created: 2018-03-13T16:07:28.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2022-05-12T14:39:54.000Z (over 2 years ago)
- Last Synced: 2024-07-28T17:43:58.833Z (about 2 months ago)
- Topics: dsp, embedded, filter, median, rust
- Language: Rust
- Size: 133 KB
- Stars: 21
- Watchers: 4
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
# median
[![Build Status](http://img.shields.io/travis/regexident/median.svg?style=flat-square)](https://travis-ci.org/regexident/median)
[![Downloads](https://img.shields.io/crates/d/median.svg?style=flat-square)](https://crates.io/crates/median/)
[![Version](https://img.shields.io/crates/v/median.svg?style=flat-square)](https://crates.io/crates/median/)
[![License](https://img.shields.io/crates/l/median.svg?style=flat-square)](https://crates.io/crates/median/)## Synopsis
An implementation of an efficient `O(n)` [median filter](https://en.wikipedia.org/wiki/Median_filter) in Rust.
## Motivation
> The median filter is a **nonlinear digital filtering technique**, often **used to remove noise from an image or signal**. Such noise reduction is a typical pre-processing step to **improve the results of later processing** […]. Median filtering is very widely used […] because, **under certain conditions, it preserves edges while removing noise**, also having **applications in signal processing**. ([Wikipedia](https://en.wikipedia.org/wiki/Median_filter))
### Median vs. Mean
![signal](signal.png)
## Usage
```rust
extern crate rand;
use rand::{Rng, XorShiftRng};extern crate median;
use median::Filter;let mut rng = XorShiftRng::new_unseeded();
let mut filter = Filter::new(FILTER_WIDTH);
for i in 0..INPUT_LENGTH {
let signal = (i as f32).sin();
let noise = rng.gen::();
let value = signal + (noise * 0.2);
let filtered = filter.consume(value);
// use filtered
}
```## Implementation
The algorithm makes use of a **ring buffer** of the same size as its filter window.
Inserting values into the ring buffer appends them to a **linked list** that is embedded
inside said ring buffer.### Performance
The classical implementation of a median filter uses an internal buffer that is re-sorted for each input to find the median, leading to inferior performance compared to the use of a linked list embedded in a ring buffer, as used in this crate.
![performance](performance.png)
(lower is better)### Example
Given a sequence of values `[3, 2, 4, 6, 5, 1]` and a buffer of size 5,
the buffer would be filled like this:```plain
new(5) consume(3) consume(2) consume(4) consume(6) consume(5) consume(1)
▶︎[ ] ▷[3] ┌→[3] ┌→[3]─┐ ┌→[3]─┐ ▶︎┌→[3]─┐ ▷[1]─┐
[ ] ▶︎[ ] ▷└─[2] ▷└─[2] │ ▷└─[2] │ ▷└─[2] │ ▶︎┌─[2]←┘
[ ] [ ] ▶︎[ ] [4]←┘ ┌─[4]←┘ ┌─[4]←┘ └→[4]─┐
[ ] [ ] [ ] ▶︎[ ] └→[6] │ [6]←┐ ┌→[6] │
[ ] [ ] [ ] [ ] ▶︎[ ] └→[5]─┘ └─[5]←┘
```### Algorithm
1. **Remove node** at current cursor (`▶︎`) from linked list, if it exists.
(by re-wiring its predecessor to its successor).
2. **Initialize** `current` and `median` index to first node of linked list (`▷`).
3. **Walk through** linked list, **searching** for insertion point.
4. **Shift median index** on every other hop (thus ending up in the list's median).
5. **Insert value** into ring buffer and linked list respectively.
6. **Update index** to linked list's first node, if necessary.
7. **Update ring buffer**'s cursor.
8. **Return median value**.## Contributing
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our [code of conduct](https://www.rust-lang.org/conduct.html),
and the process for submitting pull requests to us.## License
This project is licensed under the [**MPL-2.0**](https://www.tldrlegal.com/l/mpl-2.0) – see the [LICENSE.md](LICENSE.md) file for details.