Mercurial > code > home > repos > light9
changeset 1087:1f877950ad28
new picamserve for raspberry pi camera -> http, especially with crop control
Ignore-this: 38fc34a6eff577c05129df87d6133a95
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Wed, 04 Jun 2014 08:30:45 +0000 |
parents | c42b32853560 |
children | bb92c50438ed |
files | bin/picamserve bin/run_local.py light9/vidref/gui.js light9/vidref/index.html makefile |
diffstat | 5 files changed, 133 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/picamserve Wed Jun 04 08:30:45 2014 +0000 @@ -0,0 +1,71 @@ +#!env_pi/bin/python +from __future__ import division +from run_local import log +import sys;sys.path.append('/usr/lib/python2.7/dist-packages/') +import io, logging, traceback +import cyclone.web +from twisted.internet import reactor +from light9 import prof + +try: + import picamera + cameraCls = picamera.PiCamera +except ImportError: + class cameraCls(object): + def __enter__(self): return self + def __exit__(self): pass + def capture(self, out, *a, **kw): + out.write(open('yuv.demo').read()) + +@prof.logTime +def getFrame(c, arg): + res = int(arg('res', 480)) + c.resolution = { + 480: (640, 480), + 1080: (1920, 1080), + 1944: (2592, 1944), + }[res] + c.shutter_speed = int(arg('shutter', 50000)) + c.exposure_mode = arg('exposure_mode', 'fixedfps') + c.awb_mode = arg('awb_mode', 'off') + c.brightness = int(arg('brightness', 50)) + + c.awb_gains = (float(arg('redgain', 1)), float(arg('bluegain', 1))) + c.crop = (float(arg('x', 0)), float(arg('y', 0)), + float(arg('w', 1)), float(arg('h', 1))) + rw = rh = int(arg('resize', 100)) + # width 1920, showing w=.3 of image, resize=100 -> scale is 100/.3*1920 + # scl is [ output px / camera px ] + scl1 = rw / (c.crop[2] * c.resolution[0]) + scl2 = rh / (c.crop[3] * c.resolution[1]) + if scl1 < scl2: + # width is the constraint; reduce height to the same scale + rh = int(scl1 * c.crop[3] * c.resolution[1]) + else: + # height is the constraint + rw = int(scl2 * c.crop[2] * c.resolution[0]) + c.ISO = int(arg('iso', 250)) + out = io.BytesIO('w') + prof.logTime(c.capture)(out, 'jpeg', use_video_port=True, resize=(rw, rh)) + return out.getvalue() + +class Pic(cyclone.web.RequestHandler): + def get(self): + try: + self.set_header('Content-Type', 'image/jpeg') + self.write(getFrame(self.settings.camera, self.get_argument)) + except Exception: + traceback.print_exc() + +log.setLevel(logging.INFO) + +with cameraCls() as camera: + port = 8001 + reactor.listenTCP(port, cyclone.web.Application(handlers=[ + (r'/pic', Pic), + (r'/static/(.*)', cyclone.web.StaticFileHandler, {'path': 'static/'}), + (r'/(|gui.js)', cyclone.web.StaticFileHandler, {'path': 'light9/vidref/', + 'default_filename': 'index.html'}), + ], debug=True, camera=camera)) + log.info("serving on %s" % port) + reactor.run()
--- a/bin/run_local.py Wed Jun 04 08:27:34 2014 +0000 +++ b/bin/run_local.py Wed Jun 04 08:30:45 2014 +0000 @@ -16,8 +16,12 @@ Failure(val, exc, tb).printDetailedTraceback() Tkinter.Tk.report_callback_exception = rce -import coloredlogs, logging, time, faulthandler -faulthandler.enable() +import coloredlogs, logging, time +try: + import faulthandler + faulthandler.enable() +except ImportError: + pass log = logging.getLogger() class CSH(coloredlogs.ColoredStreamHandler):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/light9/vidref/gui.js Wed Jun 04 08:30:45 2014 +0000 @@ -0,0 +1,11 @@ +var model = { + shutters: [], +}; +for (var s=0; s < 1; s+=.04) { + var micro = Math.floor(Math.pow(s, 3) * 100000) + if (micro == 0) { + continue; + } + model.shutters.push(micro); +} +ko.applyBindings(model)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/light9/vidref/index.html Wed Jun 04 08:30:45 2014 +0000 @@ -0,0 +1,37 @@ +<!doctype html> +<html> + <head> + <title>picamserve</title> + <meta charset="utf-8" /> + <style> + .tile { + display: inline-block; + border: 1px solid gray; + margin: 3px; + padding: 2px; + } + .tile img { + } + + </style> + </head> + <body> + <section> + Whole view + <div class="tile"> + <img src="pic?resize=500&awb_mode=auto&exposure_mode=auto&shutter=100000"> + </div> + </section> + <section> + Shutters + <div data-bind="foreach: shutters"> + <div class="tile"> + <div><img data-bind="attr: {src: 'pic?res=480&resize=200&x=.5&y=.3&w=.5&h=.2&awb_mode=auto&exposure_mode=auto&shutter='+$data}"></div> + <span data-bind="text: ($data / 1000) + ' ms'"></span> + </div> + </div> + </section> + <script src="static/knockout-3.1.0.js"></script> + <script src="gui.js"></script> + </body> +</html>
--- a/makefile Wed Jun 04 08:27:34 2014 +0000 +++ b/makefile Wed Jun 04 08:30:45 2014 +0000 @@ -51,3 +51,11 @@ packages: sudo aptitude install coffeescript freemind normalize-audio audacity python-pygoocanvas python-pygame + +raspberry_pi_virtualenv: + mkdir -p env_pi + virtualenv --system-site-packages env_pi + +raspberry_pi_packages: + sudo apt-get install python-picamera python-twisted + env_pi/bin/pip install cyclone coloredlogs