Mercurial > code > home > repos > light9
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