Median filter with Redis
27 May 2014
Recently I had to implement a median filter algorithm, I found Redis very powerful to accomplish this! A very simple solution and scalable.
As described in Wikipedia, Median filter works in this way: given a signal, output sample is the median of last N input samples, where N can be any positive integer number. Higher is N, more aggressive will be your filter.
We need a store for last samples, in a FIFO way, pushing a new one will drop an older one. Redis provides lists, which are perfect for this scope. Also we need to sort these samples in numerical order, to get every time we want the median value. Redis provides a SORT command, which does this job.
I implemented these two primitives:
add_sample(value)
- called every time to add a new sampleget_median()
- to get the median value
For the former we need to call two Redis commands:
MULTI
LPUSH <yourkey> <value>
LTRIM 0 <N>-1
EXEC
LPUSH
will simply add a new sample to the list, LTRIM
ensures that at least
N elements will be stored, no more.
To get median value we need to call SORT
and then calculate median. SORT returns
all values on that list, sorted by numerical order. I have preferred
to use a script, so Redis avoids returning non useful data to clients:
local list_key = KEYS[1] -- Key of samples list
-- Sort values
local sorted_values = redis.call("SORT", list_key)
local size = #sorted_values
local median = 0.0
-- Calculate median
if size % 2 == 0 then
median = (sorted_values[size/2]+sorted_values[size/2+1]) / 2
else
median = sorted_values[(size+1)/2]
end
-- Use tostring because median value may be floating point
return tostring(median)
Calling this script it’s easy:
EVAL <script> 1 <yourkey>
Done!