Mercurial > code > home > repos > light9
changeset 1570:0480fc790527
paint now looks for best match
Ignore-this: 5604a2a2181624a0612dddf1afa32985
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Sat, 27 May 2017 12:22:28 +0000 |
parents | 654c41ccf265 |
children | 9bfd2303f011 |
files | bin/effecteval bin/paintserver light9/paint/solve.py light9/web/paint/paint-elements.coffee light9/web/paint/paint-elements.html light9/web/paint/paint-report-elements.html |
diffstat | 6 files changed, 93 insertions(+), 178 deletions(-) [+] |
line wrap: on
line diff
--- a/bin/effecteval Thu May 25 07:01:42 2017 +0000 +++ b/bin/effecteval Sat May 27 12:22:28 2017 +0000 @@ -69,7 +69,6 @@ note = URIRef(note) log.info("adding to %s", song) - note, p = yield songNotePatch(self.settings.graph, dropped, song, event, ctx=song, note=note) self.settings.graph.patch(p)
--- a/bin/paintserver Thu May 25 07:01:42 2017 +0000 +++ b/bin/paintserver Sat May 27 12:22:28 2017 +0000 @@ -14,6 +14,7 @@ from light9.rdfdb import clientsession import light9.paint.solve from lib.cycloneerr import PrettyErrorHandler +from light9.namespaces import RDF, L9, DEV class Solve(PrettyErrorHandler, cyclone.web.RequestHandler): @@ -23,9 +24,18 @@ solver = light9.paint.solve.Solver(self.settings.graph) solver.loadSamples() with self.settings.stats.solve.time(): - out = solver.solve(painting) - layers = solver.simulationLayers(out) - self.write(json.dumps({'layers': layers, 'out': out})) + img = solver.draw(painting) + sample = solver.bestMatch(img) + with self.settings.graph.currentState() as g: + bestPath = 'show/dance2017/cam/test/%s' % g.value(sample, L9['path']) + #out = solver.solve(painting) + #layers = solver.simulationLayers(out) + + self.write(json.dumps({ + 'bestMatch': {'uri': sample, 'path': bestPath}, + # 'layers': layers, + # 'out': out, + })) class App(object): def __init__(self, show, session):
--- a/light9/paint/solve.py Thu May 25 07:01:42 2017 +0000 +++ b/light9/paint/solve.py Sat May 27 12:22:28 2017 +0000 @@ -64,33 +64,51 @@ def _blur(self, img): return scipy.ndimage.gaussian_filter(img, 10, 0, mode='nearest') - - def draw(self, painting, w, h): + + def draw(self, painting): + return self._draw(painting, 100, 48) + + def _draw(self, painting, w, h): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) ctx = cairo.Context(surface) ctx.rectangle(0, 0, w, h) ctx.fill() ctx.set_line_cap(cairo.LINE_CAP_ROUND) - ctx.set_line_width(20) + ctx.set_line_width(20) # ? for stroke in painting['strokes']: for pt in stroke['pts']: op = ctx.move_to if pt is stroke['pts'][0] else ctx.line_to - op(pt[0] / 4, pt[1] / 4) # todo scale + op(pt[0] * w, pt[1] * h) r,g,b = parseHex(stroke['color']) 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): + 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] def solve(self, painting): """ given strokes of colors on a photo of the stage, figure out the best light DeviceSettings to match the image """ - pic0 = self.draw(painting, 100, 48).astype(numpy.float) + pic0 = self.draw(painting).astype(numpy.float) pic0Blur = self._blur(pic0) saveNumpy('/tmp/sample_paint_%s.png' % len(painting['strokes']), pic0Blur) @@ -98,7 +116,7 @@ for sample, picSample in sorted(self.blurredSamples.items()): #saveNumpy('/tmp/sample_%s.png' % sample.split('/')[-1], # f(picSample)) - dist = numpy.sum(numpy.absolute(pic0Blur - picSample), axis=None) + dist = self._imgDist(pic0Blur, picSample) sampleDist[sample] = dist results = [(d, uri) for uri, d in sampleDist.items()] results.sort() @@ -119,7 +137,7 @@ return s def solveBrute(self, painting): - pic0 = self.draw(painting, 100, 48).astype(numpy.float) + pic0 = self.draw(painting).astype(numpy.float) colorSteps = 3 colorStep = 1. / colorSteps
--- a/light9/web/paint/paint-elements.coffee Thu May 25 07:01:42 2017 +0000 +++ b/light9/web/paint/paint-elements.coffee Sat May 27 12:22:28 2017 +0000 @@ -9,9 +9,9 @@ {strokes: @strokes} class Stroke - constructor: (pos, @color) -> + constructor: (pos, @color, @size) -> @path = document.createElementNS('http://www.w3.org/2000/svg', 'path') - @path.setAttributeNS(null, 'd', "M #{pos[0]} #{pos[1]}") + @path.setAttributeNS(null, 'd', "M #{pos[0]*@size[0]} #{pos[1]*@size[1]}") @pts = [pos] @lastPos = pos @@ -19,20 +19,22 @@ parent.appendChild(@path) move: (pos) -> - if Math.hypot(pos[0] - @lastPos[0], pos[1] - @lastPos[1]) < 30 + if Math.hypot(pos[0] - @lastPos[0], pos[1] - @lastPos[1]) < .02 return - @path.attributes.d.value += " L #{pos[0]} #{pos[1]}" + @path.attributes.d.value += " L #{pos[0]*@size[0]} #{pos[1]*@size[1]}" @pts.push(pos) @lastPos = pos - + Polymer - is: "light9-paint" + is: "light9-paint-canvas" behaviors: [ Polymer.IronResizableBehavior ] listeners: 'iron-resize': 'onResize' properties: { - layers: { type: Object } + bg: { type: String }, + painting: { type: Object } # output } ready: -> + @onResize() @painting = new Painting() @$.paint.addEventListener('mousedown', @onDown.bind(@)) @$.paint.addEventListener('mousemove', @onMove.bind(@)) @@ -42,12 +44,13 @@ @$.paint.addEventListener('touchend', @onUp.bind(@)) evPos: (ev) -> - return (if ev.touches?.length? then [Math.round(ev.touches[0].clientX), - Math.round(ev.touches[0].clientY)] else [ev.x, ev.y]) + px = (if ev.touches?.length? then [Math.round(ev.touches[0].clientX), + Math.round(ev.touches[0].clientY)] else [ev.x, ev.y]) + return [px[0] / @size[0], px[1] / @size[1]] onDown: (ev) -> # if it's on an existing one, do selection - @stroke = new Stroke(@evPos(ev), '#aaaaaa') + @stroke = new Stroke(@evPos(ev), '#aaaaaa', @size) @stroke.appendElem(@$.paint) @scopeSubtree(@$.paint) @@ -57,19 +60,23 @@ @stroke.move(@evPos(ev)) onUp: (ev) -> + return unless @stroke @painting.addStroke(@stroke.pts, @stroke.color) - @$.solve.body = JSON.stringify(@painting.getDoc()) - @$.solve.generateRequest() @stroke = null + + @notifyPath('painting.strokes.length') # not working + @fire('paintingChanged', @painting) onResize: (ev) -> - @$.paint.attributes.viewBox.value = "0 0 #{ev.target.offsetWidth} 500" + @size = [@$.parent.offsetWidth, @$.parent.offsetHeight] + @$.paint.attributes.viewBox.value = "0 0 #{@size[0]} #{@size[1]}" Polymer is: "light9-simulation" properties: { layers: { type: Object } + solution: { type: Object } } listeners: [ "onLayers(layers)" @@ -77,4 +84,24 @@ ready: -> null onLayers: (layers) -> - log('upd', layers) \ No newline at end of file + log('upd', layers) + + +Polymer + is: "light9-paint" + properties: { + painting: { type: Object } + } + + ready: () -> + # couldn't make it work to bind to painting's notifyPath events + @$.canvas.addEventListener('paintingChanged', @paintingChanged.bind(@)) + @$.solve.addEventListener('response', @onSolve.bind(@)) + + paintingChanged: (ev) -> + @painting = ev.detail + @$.solve.body = JSON.stringify(@painting.getDoc()) + @$.solve.generateRequest() + + onSolve: (response) -> + console.log(response) \ No newline at end of file
--- a/light9/web/paint/paint-elements.html Thu May 25 07:01:42 2017 +0000 +++ b/light9/web/paint/paint-elements.html Sat May 27 12:22:28 2017 +0000 @@ -1,10 +1,14 @@ <link rel="import" href="/lib/polymer/polymer.html"> <link rel="import" href="/lib/iron-resizable-behavior/iron-resizable-behavior.html"> <link rel="import" href="/lib/iron-ajax/iron-ajax.html"> +<link rel="import" href="paint-report-elements.html"> -<dom-module id="light9-paint"> +<dom-module id="light9-paint-canvas"> <template> <style> + :host { + display: block; + } #parent { position: relative; height: 500px; @@ -34,9 +38,8 @@ - erase </div> - <iron-ajax id="solve" method="POST" url="../paintServer/solve"></iron-ajax> <div id="parent"> - <img src="bg2.jpg"> + <img src="{{bg}}"> <svg id="paint" viewBox="0 0 500 221"> <defs id="defs12751"> <filter @@ -76,159 +79,17 @@ </defs> </svg> </div> - - - - <light9-simulation layers="{{layers}}"></light9-simulation> </template> -</dom-module> - -<!-- merge more with light9-collector-device --> -<dom-module id="light9-device-settings"> - <template> - <style> - :host { - display: block; - break-inside: avoid-column; - border: 2px solid gray; - padding: 8px; - } - td.nonzero { - background: #310202; - color: #e25757; - } - td.full { - background: #2b0000; - color: red; - font-weight: bold; - } - </style> - <h3>{{label}}</h3> - <table class="borders"> - <tr> - <th>device attr</th> - <th>value</th> - </tr> - <template is="dom-repeat" items="{{attrs}}"> - <tr> - <td>{{item.attr}}</td> - <td class$="{{item.valClass}}">{{item.val}}</td> - </tr> - </template> - - </template> - <script> - HTMLImports.whenReady(function () { - Polymer({ - is: "light9-device-settings", - properties: { - label: {type: String, notify: true}, - attrs: {type: Array, notify: true}, - - }, - ready: function() { - - this.label = "aura2"; - this.attrs = [ - {attr: 'rx', val: .03}, - {attr: 'color', val: '#ffe897'}, - ]; - - } - }); - }); - </script> + </dom-module> -<dom-module id="light9-capture-image"> +<dom-module id="light9-paint"> <template> - <style> - :host { display: block; } - </style> - <div>{{name}}</div> - <div><img width="100" src="../{{path}}"></div> - </template> - <script> - HTMLImports.whenReady(function () { - Polymer({ - is: "light9-capture-image", - properties: { - name: { type: String }, - path: { type: String }, - } - }); - }); - </script> -</dom-module> - -<dom-module id="light9-simulation"> - <template> - <style> - #solutions { display: flex; margin: 20px; } - #single-light { margin-right: 70px; } - #multi-light {} - #breakdown { position: relative; } - #sources { display: flex; } - #solution { display: flex; margin-top: 80px; } - #connectors { position: absolute; width: 100%; height: 100%; } - #connectors path { stroke: #615c54; stroke-width: 3px; } - </style> - - <div id="solutions"> - <div id="single-light"> - <div>Single pic best match:</div> - - <light9-capture-image name="mac2" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image> + <light9-paint-canvas id="canvas" bg="bg2.jpg" painting="{{painting}}"></light9-paint-canvas> - <div>Error: 280844</div> - - <div>DeviceSettings</div> - <light9-device-settings></light9-device-settings> - </div> - - <!-- existing effect best match? --> - - <div id="multi-light"> - Created from multiple lights: - - <div id="breakdown"> - <svg id="connectors"> - <g> - <path d="M 112,241 L 150,280"></path> - <path d="M 332,241 L 150,280"></path> - <path d="M 532,241 L 150,280"></path> - <path d="M 732,241 L 150,280"></path> - </g> - - </svg> - <div id="sources"> - <div> - <light9-capture-image name="aura1" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image> - <light9-device-settings></light9-device-settings> - </div> - <div> - <light9-capture-image name="aura2" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image> - <light9-device-settings></light9-device-settings> - </div> - <div> - <light9-capture-image name="aura3" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image> - <light9-device-settings></light9-device-settings> - </div> - <div> - <light9-capture-image name="aura4" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image> - <light9-device-settings></light9-device-settings> - </div> - </div> - - <div id="solution"> - <div> <div>combined</div><div><img width="150" src="../show/dance2017/capture/moving1/cap258592/pic1.jpg"></div><div>error 9980</div></div> - <div> <div>residual</div><div><img width="150" src="../show/dance2017/capture/moving1/cap258592/pic1.jpg"></div></div> - </div> - </div> - - Save as effect named <input> <button>Save</button> - </div> - + <iron-ajax id="solve" method="POST" url="../paintServer/solve" last-response="{{solve}}"></iron-ajax> + + <light9-simulation solution="{{solve}}" layers="{{layers}}"></light9-simulation> </template> </dom-module>
--- a/light9/web/paint/paint-report-elements.html Thu May 25 07:01:42 2017 +0000 +++ b/light9/web/paint/paint-report-elements.html Sat May 27 12:22:28 2017 +0000 @@ -20,7 +20,7 @@ <div>Single pic best match:</div> <!-- drag this img to make an effect out of just it --> - <light9-capture-image name="mac2" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image> + <light9-capture-image name="mac2" path="{{solution.bestMatch.path}}"></light9-capture-image> <div>Error: 280844</div>