Changeset - 17da56a3c8df
[Not reviewed]
default
0 4 0
Drew Perttula - 8 years ago 2017-05-30 08:37:25
drewp@bigasterisk.com
group device captures into sessions, limit solver to specific ones
Ignore-this: b91d858ebb435973b9742bed00567ffd
4 files changed with 32 insertions and 19 deletions:
0 comments (0 inline, 0 general)
bin/captureDevice
Show inline comments
 
@@ -12,31 +12,31 @@ import treq
 
import cyclone.web, cyclone.websocket, cyclone.httpclient
 
from greplin import scales
 

	
 
from run_local import log
 
from lib.cycloneerr import PrettyErrorHandler
 

	
 
from light9.namespaces import L9
 
from light9.namespaces import L9, RDF
 
from light9 import networking, showconfig
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from light9.paint.capture import writeCaptureDescription
 
from light9.greplin_cyclone import StatsForCyclone
 
from light9.effect.settings import DeviceSettings
 
from light9.effect.sequencer import sendToCollector
 
from light9.rdfdb.patch import Patch
 

	
 
stats = scales.collection('/webServer', scales.PmfStat('setAttr'))
 

	
 

	
 
class Camera(object):
 
    def __init__(self, imageUrl):
 
        self.imageUrl = imageUrl
 
    
 
    def takePic(self, uri, writePath):
 
        log.info('takePic %s', uri)
 
        return treq.get(self.imageUrl).addCallbacks(lambda r: self._done(writePath, r),
 
                                                    log.error)
 
        return treq.get(self.imageUrl).addCallbacks(
 
            lambda r: self._done(writePath, r), log.error)
 
        
 
    @inlineCallbacks
 
    def _done(self, writePath, response):
 
        jpg = yield response.content()
 
        try:
 
            os.makedirs(os.path.dirname(writePath))
 
@@ -53,12 +53,13 @@ def deferSleep(sec):
 
    
 
class Capture(object):
 
    firstMoveTime = 3
 
    settleTime = .5
 
    def __init__(self, graph, dev):
 
        self.graph = graph
 
        self.dev = dev
 
        
 
        def steps(a, b, n):
 
            return [round(a + (b - a) * i / n, 5) for i in range(n)]
 

	
 
        startTime = time.time()
 
        self.captureId = 'cap%s' % (int(startTime) - 1495170000)
 
@@ -74,12 +75,21 @@ class Capture(object):
 
                self.toGather.append(DeviceSettings(graph, [
 
                    (dev, L9['rx'], rx),
 
                    (dev, L9['ry'], ry),
 
                    (dev, L9['color'], '#ffffff'),
 
                ]))
 

	
 
        self.devTail = dev.rsplit('/')[-1]
 
        self.session = URIRef('/'.join([showconfig.showUri(),
 
                                   'capture', self.devTail, self.captureId]))
 
        self.ctx = URIRef(self.session + '/index')
 
                
 
        self.graph.patch(Patch(addQuads=[
 
            (self.session, RDF.type, L9['CaptureSession'], self.ctx),
 
        ]))
 
                
 
        self.numPics = 0
 
        self.settingsCache = set()
 
        self.step().addErrback(log.error)
 

	
 
    def off(self):
 
        return sendToCollector(client='captureDevice', session='main',
 
@@ -98,26 +108,23 @@ class Capture(object):
 
        yield sendToCollector(client='captureDevice', session='main',
 
                              settings=settings)
 
        
 
        yield deferSleep(self.firstMoveTime if self.numPics == 0 else
 
                         self.settleTime)
 
        
 
        dev = settings.devices()[0]
 
        devTail = dev.rsplit('/')[-1]
 
        picId = 'pic%s' % self.numPics
 
        path = '/'.join(['capture', devTail, self.captureId, picId]) + '.jpg'
 
        ctx = URIRef('/'.join([showconfig.showUri(),
 
                               'capture', devTail, self.captureId, 'index']))
 
        uri = URIRef('/'.join([showconfig.showUri(),
 
                               'capture', devTail, self.captureId, picId]))
 
        path = '/'.join([
 
            'capture', self.devTail, self.captureId, picId]) + '.jpg'
 
        uri = URIRef(self.session + '/' + picId)
 
        
 
        yield camera.takePic(uri, os.path.join(showconfig.root(), path))
 
        self.numPics += 1
 

	
 
        writeCaptureDescription(self.graph, ctx, uri, dev, path,
 
                                self.settingsCache, settings)
 
        writeCaptureDescription(self.graph, self.ctx, self.session, uri,
 
                                self.dev,
 
                                path, self.settingsCache, settings)
 
        
 
        reactor.callLater(0, self.step)
 

	
 
        
 

	
 
camera = Camera('http://dash:8200/picamserve/pic?res=480&resize=480&rotation=180&iso=800&redgain=1.6&bluegain=2&shutter=60000')
bin/paintserver
Show inline comments
 
@@ -50,13 +50,13 @@ class App(object):
 
        
 
        self.stats = scales.collection('/', scales.PmfStat('solve'),
 
                                       )
 
       
 
    def launch(self, *args):
 

	
 
        self.solver = light9.paint.solve.Solver(self.graph)
 
        self.solver = light9.paint.solve.Solver(self.graph, sessions=[L9['show/dance2017/capture/moving1/cap961804']])
 
        self.solver.loadSamples()
 
        
 
        self.cycloneApp = cyclone.web.Application(handlers=[
 
            (r'/stats', StatsForCyclone),
 
            (r'/solve', Solve),
 
        ],
light9/paint/capture.py
Show inline comments
 
@@ -2,21 +2,22 @@ import os
 
from rdflib import URIRef
 
from light9 import showconfig
 
from light9.rdfdb.patch import Patch
 
from light9.namespaces import L9, RDF
 
from light9.paint.solve import loadNumpy
 

	
 
def writeCaptureDescription(graph, ctx, uri, dev, outPath, settingsSubgraphCache,
 
                            settings):
 
def writeCaptureDescription(graph, ctx, session, uri, dev, outPath,
 
                            settingsSubgraphCache, settings):
 
    graph.patch(Patch(addQuads=settings.statements(
 
        uri, ctx=ctx,
 
        settingRoot=URIRef('/'.join([
 
            showconfig.showUri(), 'capture', dev.rsplit('/')[1]])),
 
        settingsSubgraphCache=settingsSubgraphCache)))
 
    graph.patch(Patch(addQuads=[
 
        (dev, L9['capture'], uri, ctx),
 
        (session, L9['capture'], uri, ctx),
 
        (uri, RDF.type, L9['LightSample'], ctx),
 
        (uri, L9['imagePath'], URIRef('/'.join([
 
            showconfig.showUri(), outPath])), ctx),
 
        ]))
 
    graph.suggestPrefixes(ctx, {'cap': uri.rsplit('/', 1)[0] + '/',
 
                                'showcap': showconfig.showUri() + '/capture/'})
light9/paint/solve.py
Show inline comments
 
@@ -64,32 +64,37 @@ class ImageDistAbs(object):
 

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

	
 
        
 
class Solver(object):
 
    def __init__(self, graph, imgSize=(100, 75)):
 
    def __init__(self, graph, sessions=None, imgSize=(100, 75)):
 
        self.graph = graph
 
        self.sessions = sessions
 
        self.imgSize = imgSize
 
        self.samples = {} # uri: Image array (float 0-255)
 
        self.fromPath = {} # imagePath: image array
 
        self.blurredSamples = {}
 
        self.sampleSettings = {} # (uri, path): DeviceSettings
 
        
 
    def loadSamples(self):
 
        """learn what lights do from images"""
 

	
 
        with self.graph.currentState() as g:
 
            for samp in g.subjects(RDF.type, L9['LightSample']):
 
            for sess in self.sessions:
 
                for cap in g.objects(sess, L9['capture']):
 
                    self._loadSample(g, cap)
 
        log.info('loaded %s samples', len(self.samples))
 

	
 
    def _loadSample(self, g, samp):
 
                pathUri = g.value(samp, L9['imagePath'])
 
                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, self.imgSize[0], self.imgSize[1])
0 comments (0 inline, 0 general)