Changeset - 0d2247ec8f49
[Not reviewed]
default
0 7 0
Drew Perttula - 8 years ago 2017-05-29 07:59:59
drewp@bigasterisk.com
bestMatch works in paintserver
Ignore-this: c237f9f9a3dafe3ccfa3087423a5259a
7 files changed with 72 insertions and 34 deletions:
0 comments (0 inline, 0 general)
.boring
Show inline comments
 
@@ -153,3 +153,4 @@
 

	
 
# temporary!
 
rgbled/build-nano328/
 
^show/dance..../capture
bin/paintserver
Show inline comments
 
@@ -20,23 +20,26 @@ from light9.namespaces import RDF, L9, D
 
class Solve(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def post(self):
 
        painting = json.loads(self.request.body)
 
        reload(light9.paint.solve)
 
        solver = light9.paint.solve.Solver(self.settings.graph)
 
        solver.loadSamples()
 
        with self.settings.stats.solve.time():
 
            img = solver.draw(painting)
 
            sample = solver.bestMatch(img)
 
            img = self.settings.solver.draw(painting)
 
            sample, sampleDist = self.settings.solver.bestMatch(img)
 
            with self.settings.graph.currentState() as g:
 
                bestPath = 'show/dance2017/cam/test/%s' % g.value(sample, L9['path'])
 
                bestPath = g.value(sample, L9['imagePath']).replace(L9[''], '')
 
            #out = solver.solve(painting)
 
            #layers = solver.simulationLayers(out)
 
            
 
        self.write(json.dumps({
 
            'bestMatch': {'uri': sample, 'path': bestPath},
 
            'bestMatch': {'uri': sample, 'path': bestPath, 'dist': sampleDist},
 
        #    'layers': layers,
 
        #    'out': out,
 
        }))
 

	
 
    def reloadSolver(self):
 
        reload(light9.paint.solve)
 
        self.settings.solver = light9.paint.solve.Solver(self.settings.graph)
 
        self.settings.solver.loadSamples()
 

	
 
        
 
class App(object):
 
    def __init__(self, show, session):
 
        self.show = show
 
@@ -44,17 +47,22 @@ class App(object):
 

	
 
        self.graph = SyncedGraph(networking.rdfdb.url, "paintServer")
 
        self.graph.initiallySynced.addCallback(self.launch)
 
        
 
        self.stats = scales.collection('/', scales.PmfStat('solve'),
 
                                       )
 
       
 
    def launch(self, *args):
 

	
 
        self.stats = scales.collection('/',
 
                                       scales.PmfStat('solve'),
 
                                       )
 
    def launch(self, *args):
 
        self.solver = light9.paint.solve.Solver(self.graph)
 
        self.solver.loadSamples()
 
        
 
        self.cycloneApp = cyclone.web.Application(handlers=[
 
            (r'/stats', StatsForCyclone),
 
            (r'/solve', Solve),
 
        ],
 
                                                  debug=True,
 
                                                  graph=self.graph,
 
                                                  solver=self.solver,
 
                                                  stats=self.stats)
 
        reactor.listenTCP(networking.paintServer.port, self.cycloneApp)
 
        log.info("listening on %s" % networking.paintServer.port)
light9/paint/capture.py
Show inline comments
 
@@ -15,6 +15,7 @@ def writeCaptureDescription(graph, ctx, 
 
        (uri, RDF.type, L9['LightSample'], ctx),
 
        (uri, L9['imagePath'], URIRef('/'.join([showconfig.showUri(), relOutPath])), ctx),
 
        ]))
 
    graph.suggestPrefixes('cap', URIRef(uri.rsplit('/', 1)[0] + '/'))
 
    
 
class CaptureLoader(object):
 
    def __init__(self, graph):
light9/paint/solve.py
Show inline comments
 
@@ -47,12 +47,30 @@ def colorRatio(col1, col2):
 

	
 
def brightest(img):
 
    return numpy.amax(img, axis=(0, 1))
 
    
 
class ImageDist(object):
 
    def __init__(self, img1):
 
        self.a = img1.reshape((-1,))
 
        self.d = 255 * 255 * self.a.shape[0]
 

	
 
    def distanceTo(self, img2):
 
        b = img2.reshape((-1,))
 
        return 1 - numpy.dot(self.a, b) / self.d
 

	
 
class ImageDistAbs(object):
 
    def __init__(self, img1):
 
        self.a = img1
 
        self.maxDist = img1.shape[0] * img1.shape[1] * img1.shape[2] * 255
 

	
 
    def distanceTo(self, img2):
 
        return numpy.sum(numpy.absolute(self.a - img2), axis=None) / self.maxDist
 

	
 
        
 
class Solver(object):
 
    def __init__(self, graph):
 
    def __init__(self, graph, imgSize=(100, 75)):
 
        self.graph = graph
 
        self.samples = {} # uri: Image array
 
        self.imgSize = imgSize
 
        self.samples = {} # uri: Image array (float 0-255)
 
        self.fromPath = {} # imagePath: image array
 
        self.blurredSamples = {}
 
        self.sampleSettings = {} # (uri, path): DeviceSettings
 
@@ -63,17 +81,18 @@ class Solver(object):
 
        with self.graph.currentState() as g:
 
            for samp in g.subjects(RDF.type, L9['LightSample']):
 
                pathUri = g.value(samp, L9['imagePath'])
 
                self.samples[samp] = self.fromPath[pathUri] = loadNumpy(pathUri.replace(L9[''], ''))
 
                self.samples[samp] = self.fromPath[pathUri] = loadNumpy(pathUri.replace(L9[''], '')).astype(float)
 
                self.blurredSamples[samp] = self._blur(self.samples[samp])
 
                
 
                key = (samp, pathUri)
 
                self.sampleSettings[key] = DeviceSettings.fromResource(self.graph, samp)
 

	
 
        log.info('loaded %s samples', len(self.samples))
 
                
 
    def _blur(self, img):
 
        return scipy.ndimage.gaussian_filter(img, 10, 0, mode='nearest')
 

	
 
    def draw(self, painting):
 
        return self._draw(painting, 100, 48)
 
        return self._draw(painting, self.imgSize[0], self.imgSize[1])
 
        
 
    def _draw(self, painting, w, h):
 
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
 
@@ -92,24 +111,25 @@ class Solver(object):
 
            ctx.set_source_rgb(r / 255, g / 255, b / 255)
 
            ctx.stroke()
 
        
 
        surface.write_to_png('/tmp/surf.png')
 
        #surface.write_to_png('/tmp/surf.png')
 
        return numpyFromCairo(surface)
 

	
 

	
 
    def _imgDist(self, a, b):
 
        return numpy.sum(numpy.absolute(a - b), axis=None)
 
        
 
    def bestMatch(self, img):
 
        """the one sample that best matches this image"""
 
        #img = self._blur(img)
 
        results = []
 
        for uri, img2 in self.samples.iteritems():
 
            results.append((self._imgDist(img, img2), uri, img2))
 
        dist = ImageDist(img)
 
        for uri, img2 in sorted(self.samples.items()):
 
            if img.shape != img2.shape:
 
                continue
 
            results.append((dist.distanceTo(img2), uri, img2))
 
        results.sort()
 
        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]
 
        topDist, topUri, topImg = results[0]
 
       
 
        #saveNumpy('/tmp/best_in.png', img)
 
        #saveNumpy('/tmp/best_out.png', topImg)
 
        #saveNumpy('/tmp/mult.png', topImg / 255 * img)
 
        return topUri, topDist
 
        
 
    def solve(self, painting):
 
        """
light9/paint/solve_test.py
Show inline comments
 
@@ -10,7 +10,7 @@ class TestSolve(unittest.TestCase):
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                             'show/dance2017/cam/test/bg.n3'])
 
        self.solver = solve.Solver(self.graph)
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48))
 
        self.solver.loadSamples()
 
        self.solveMethod = self.solver.solve
 

	
 
@@ -39,7 +39,7 @@ class TestSimulationLayers(unittest.Test
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                             'show/dance2017/cam/test/bg.n3'])
 
        self.solver = solve.Solver(self.graph)
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48))
 
        self.solver.loadSamples()
 
        
 
    def testBlack(self):
 
@@ -79,7 +79,7 @@ class TestCombineImages(unittest.TestCas
 
    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 = solve.Solver(graph, imgSize=(100, 48))
 
        self.solver.loadSamples()
 
    def test(self):
 
        out = self.solver.combineImages(layers=[
 
@@ -94,12 +94,13 @@ 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 = solve.Solver(graph, imgSize=(100, 48))
 
        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)
 
        match, dist = self.solver.bestMatch(drawImg)
 
        self.assertEqual(L9['sample5'], match)
 
        self.assertAlmostEqual(0.06678758, dist)
light9/rdfdb/currentstategraphapi.py
Show inline comments
 
@@ -14,6 +14,9 @@ class ReadOnlyConjunctiveGraph(object):
 
            return getattr(self.graph, attr)
 
        raise TypeError("can't access %r of read-only graph" % attr)
 

	
 
    def __len__(self):
 
        return len(self.graph)
 

	
 

	
 
class CurrentStateGraphApi(object):
 
    """
light9/web/paint/paint-report-elements.html
Show inline comments
 
@@ -22,7 +22,7 @@
 
        <!-- drag this img to make an effect out of just it -->
 
        <light9-capture-image name="mac2" path="{{solution.bestMatch.path}}"></light9-capture-image>
 

	
 
        <div>Error: 280844</div>
 
        <div>Error: {{solution.bestMatch.dist}}</div>
 
        
 
        <light9-device-settings></light9-device-settings>
 
      </div>
 
@@ -140,6 +140,10 @@
 
  <template>
 
    <style>
 
     :host { display: block; }
 
       img {
 
         outline: 1px solid #232323;
 
         margin: 5px;
 
     }
 
    </style>
 
    <div>{{name}}</div>
 
    <div><img width="100" src="../{{path}}"></div>
0 comments (0 inline, 0 general)