Source code for munin.distance.moodbar

#!/usr/bin/env python
# encoding: utf-8


"""
Overview
--------

The Distance Function in this Module works with the following providers:

    * :class:`munin.provider.moodbar.MoodbarProvider`
    * :class:`munin.provider.moodbar.MoodbarMoodFileProvider`
    * :class:`munin.provider.moodbar.MoodbarAudioFileProvider`

**Technical Details:**

The individual attributes are weighted and computes as following:

+-------------------+---------+---------------------------------------------------------------+
|  Name             | Weight  | Formula                                                       |
+===================+=========+===============================================================+
| *diffsum*         |   0.135 | ``abs(v1 - v2) / 50``                                         |
+-------------------+---------+---------------------------------------------------------------+
| *histogram*       |   0.135 | ``1.0 - sum(a - b for a, b in lefts, rights) / 5 * 255``      |
+-------------------+---------+---------------------------------------------------------------+
| *dominant colors* |   0.63  | ``len(common) / max(len(lefts), len(rights))``                |
+-------------------+---------+---------------------------------------------------------------+
| *blackness*       |   0.05  | ``abs(v1 - v2) / 50``                                         |
+-------------------+---------+---------------------------------------------------------------+
| *average min/max* |   0.05  | ``abs(v1 - v2) / 255``                                        |
+-------------------+---------+---------------------------------------------------------------+
|                   |   1.0   |                                                               |
+-------------------+---------+---------------------------------------------------------------+

Reference
---------
"""

from munin.distance import DistanceFunction
from math import sqrt


[docs]class MoodbarDistance(DistanceFunction): """Distance Function that compares two MoodbarDescriptions."""
[docs] def do_compute(self, lefts, rights): """Compute the distance between two moodbar desc Only the first element in the individual lists is used. :param lefts: Packed left moodbar description. :param rights: Packed right moodbar description. """ if not (lefts and rights): return 1.0 distance = 1.0 ld, rd = lefts[0], rights[0] distf = lambda v1, v2, m: 1.0 - sqrt(min(1.0, abs(v1 - v2) / m)) for left_chan, right_chan in zip(ld.channels, rd.channels): hist_diff = sum(abs(a - b) for a, b in zip(left_chan.histogram, right_chan.histogram)) distance -= 0.045 * (1.0 - hist_diff / (5 * 255)) distance -= 0.045 * distf(left_chan.diffsum, right_chan.diffsum, 50) distance -= 0.025 * distf(ld.average_max, rd.average_max, 255) distance -= 0.025 * distf(ld.average_min, rd.average_min, 255) distance -= 0.050 * distf(ld.blackness, rd.blackness, 50) lkeys, rkeys = ld.dominant_colors.keys(), rd.dominant_colors.keys() if lkeys and rkeys: distance -= 0.63 * (len(lkeys & rkeys) / max(len(lkeys), len(rkeys))) # Good distances are in the range 0.3 - 0.5 usually # Therefore we handle lower values better. # http://www.arndt-bruenner.de/mathe/scripts/regr.htm # was used to calculate a polynom that scales these values. # This function goes through the following points: # 0 0 # 0,25 0,125 # 0,5 0,5 # 0,75 0,875 # 1 1 # # The function is not 100% correct, so we clamp possible precision # errors into [0, 1] d2 = distance * distance d3 = d2 * distance return min(1.0, max(0, -2.666 * d3 + 4 * d2 - 0.3333 * distance))
if __name__ == '__main__': import sys import unittest from munin.provider.moodbar import MoodbarDescription, MoodbarChannel class TestMoodbarDistance(unittest.TestCase): def test_equality(self): func = MoodbarDistance() description = MoodbarDescription( [ MoodbarChannel([0, 0, 0, 0, 0], 0), MoodbarChannel([0, 0, 0, 0, 0], 0), MoodbarChannel([0, 0, 0, 0, 0], 0) ], 0, 0, { (0, 0, 0): 20, (1, 1, 1): 19, (2, 2, 2): 18, (256, 256, 256): 0 }, 100 ) self.assertAlmostEqual( func.do_compute([description], [description]), 0.0 ) anti = MoodbarDescription( [ MoodbarChannel([0xff, 0xff, 0xff, 0xff, 0xff], 20), MoodbarChannel([0xff, 0xff, 0xff, 0xff, 0xff], 20), MoodbarChannel([0xff, 0xff, 0xff, 0xff, 0xff], 20) ], 0xff, 0xff, { (12, 12, 12): 20, (250, 250, 250): 19, (3, 3, 3): 18, (255, 255, 255): 0 }, 0 ) self.assertAlmostEqual(func.do_compute([description], [anti]), 1.0) if '--cli' in sys.argv: from munin.provider.moodbar import MoodbarMoodFileProvider prov = MoodbarMoodFileProvider() one = prov.do_process(sys.argv[2]) two = prov.do_process(sys.argv[3]) func = MoodbarDistance() print(one) print(two) print(func.do_compute(one, two)) else: unittest.main()

Related Topics

Useful links:

Package:

Github: