changeset 1571:9bfd2303f011

fix bestMatch solve method Ignore-this: 2e7f5af86e2e54b36dfb27a6b52e26a5
author Drew Perttula <drewp@bigasterisk.com>
date Sun, 28 May 2017 07:48:04 +0000
parents 0480fc790527
children 9be85c08a69f
files light9/effect/settings.py light9/effect/settings_test.py light9/paint/solve.py light9/paint/solve_test.py show/dance2017/cam/test/lightConfig.n3 show/dance2017/deviceClass.n3
diffstat 5 files changed, 47 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/light9/effect/settings.py	Sat May 27 12:22:28 2017 +0000
+++ b/light9/effect/settings.py	Sun May 28 07:48:04 2017 +0000
@@ -9,7 +9,8 @@
 from rdflib import URIRef, Literal
 from light9.namespaces import RDF, L9, DEV
 from light9.rdfdb.patch import Patch
-
+import logging
+log = logging.getLogger('settings')
 
 def parseHex(h):
     if h[0] != '#': raise ValueError(h)
@@ -96,7 +97,9 @@
     def __ne__(self, other):
         return not self == other
 
-
+    def __nonzero__(self):
+        return bool(self._compiled)
+        
     def __repr__(self):
         words = []
         def accum():
@@ -151,6 +154,7 @@
     def distanceTo(self, other):
         diff = numpy.array(self.toVector()) - other.toVector()
         d = numpy.linalg.norm(diff, ord=None)
+        log.info('distanceTo %r - %r = %g', self, other, d)
         return d
 
     def statements(self, subj, ctx, settingRoot, settingsSubgraphCache):
--- a/light9/effect/settings_test.py	Sat May 27 12:22:28 2017 +0000
+++ b/light9/effect/settings_test.py	Sun May 28 07:48:04 2017 +0000
@@ -30,6 +30,10 @@
         self.assertEqual(
             DeviceSettings(self.graph, [(L9['aura1'], L9['rx'], 0),]),
             DeviceSettings(self.graph, []))
+
+    def testFalseIfZero(self):
+        self.assertTrue(DeviceSettings(self.graph, [(L9['aura1'], L9['rx'], 0.1)]))
+        self.assertFalse(DeviceSettings(self.graph, []))
         
     def testFromResource(self):
         ctx = L9['']
--- a/light9/paint/solve.py	Sat May 27 12:22:28 2017 +0000
+++ b/light9/paint/solve.py	Sun May 28 07:48:04 2017 +0000
@@ -4,9 +4,12 @@
 import numpy
 import scipy.misc, scipy.ndimage, scipy.optimize
 import cairo
+import logging
 
 from light9.effect.settings import DeviceSettings, parseHex, toHex
 
+log = logging.getLogger('solve')
+
 # numpy images in this file are (x, y, c) layout.
 
 def numpyFromCairo(surface):
@@ -25,6 +28,7 @@
     return numpyFromPil(img)
 
 def saveNumpy(path, img):
+    # maybe this should only run if log level is debug?
     scipy.misc.imsave(path, img.transpose((1, 0, 2)))
 
 def scaledHex(h, scale):
@@ -35,7 +39,11 @@
 def colorRatio(col1, col2):
     rgb1 = parseHex(col1)
     rgb2 = parseHex(col2)
-    return tuple([round(a / b, 3) for a, b in zip(rgb1, rgb2)])
+    def div(x, y):
+        if y == 0:
+            return 0
+        return round(x / y, 3)
+    return tuple([div(a, b) for a, b in zip(rgb1, rgb2)])
 
 def brightest(img):
     return numpy.amax(img, axis=(0, 1))
@@ -75,7 +83,7 @@
         ctx.fill()
         
         ctx.set_line_cap(cairo.LINE_CAP_ROUND)
-        ctx.set_line_width(20) # ?
+        ctx.set_line_width(w / 5) # ?
         for stroke in painting['strokes']:
             for pt in stroke['pts']:
                 op = ctx.move_to if pt is stroke['pts'][0] else ctx.line_to
@@ -93,15 +101,16 @@
         return numpy.sum(numpy.absolute(a - b), axis=None)
         
     def bestMatch(self, img):
+        """the one sample that best matches this image"""
         results = []
         for uri, img2 in self.samples.iteritems():
             results.append((self._imgDist(img, img2), uri, img2))
         results.sort()
-        print 'results:'
-        for r in results:
-            print r
-        saveNumpy('/tmp/bestsamp.png', results[-1][2])
-        return results[-1][1]
+        log.info('results:')
+        for d,u,i in results:
+            log.info('%s %g', u, d)
+        saveNumpy('/tmp/bestsamp.png', results[0][2])
+        return results[0][1]
         
     def solve(self, painting):
         """
@@ -192,13 +201,18 @@
             requestedColor = devSettings.getValue(dev, L9['color'])
             candidatePics = [] # (distance, path, picColor)
             for (sample, path), s in self.sampleSettings.items():
-                dist = devSettings.distanceTo(s.ofDevice(dev))
+                otherDevSettings = s.ofDevice(dev)
+                if not otherDevSettings:
+                    continue
+                dist = devSettings.distanceTo(otherDevSettings)
+                log.info('  candidate pic %s %s dist=%s', sample, path, dist)
                 candidatePics.append((dist, path, s.getValue(dev, L9['color'])))
             candidatePics.sort()
             # we could even blend multiple top candidates, or omit all
             # of them if they're too far
             bestDist, bestPath, bestPicColor = candidatePics[0]
-
+            log.info('  device best d=%g path=%s color=%s', bestDist, bestPath, bestPicColor)
+            
             layers.append({'path': bestPath,
                            'color': colorRatio(requestedColor, bestPicColor)})
         
--- a/light9/paint/solve_test.py	Sat May 27 12:22:28 2017 +0000
+++ b/light9/paint/solve_test.py	Sun May 28 07:48:04 2017 +0000
@@ -87,3 +87,16 @@
         golden = solve.loadNumpy('show/dance2017/cam/test/layers_out1.png')
         numpy.testing.assert_array_equal(golden, out)
 
+class TestBestMatch(unittest.TestCase):
+    def setUp(self):
+        graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
+                                        'show/dance2017/cam/test/bg.n3'])
+        self.solver = solve.Solver(graph)
+        self.solver.loadSamples()
+        
+    def testRightSide(self):
+        drawingOnRight = {"strokes":[{"pts":[[0.875,0.64],[0.854,0.644]],
+                                      "color":"#aaaaaa"}]}
+        drawImg = self.solver.draw(drawingOnRight)
+        match = self.solver.bestMatch(drawImg)
+        self.assertEqual(L9['sample5'], match)
--- a/show/dance2017/deviceClass.n3	Sat May 27 12:22:28 2017 +0000
+++ b/show/dance2017/deviceClass.n3	Sun May 28 07:48:04 2017 +0000
@@ -18,6 +18,7 @@
 :quantumGoboChoice  a :DeviceAttr; :dataType :choice;
   :choice :open, :spider, :windmill, :limbo, :brush, :whirlpool, :stars .
 
+
 :SimpleDimmer a :DeviceClass;
   :deviceAttr :brightness;
   :attr