Rhe asked if I could come up with a way to make time lapse videos of her building a model on the desk. We could do that with a real camera on a tripod taking timed exposures, but the lack of immediate feedback kinda sucks. I've got a Raspberry Pi free and a camera module for it that I haven't played with yet, so I'm building that out.
I have an 8gb sd card, looking at it on the win7 machine, there's old
pi image on it I don't care about, so
win32 disk imager and the
raspibian-stretch-full.img that's to hand go onto it. Fresh
stock install of a year old distro.
I had to look up how to setup SSH:
For headless setup, SSH can be enabled by placing a file named ssh, without any extension, onto the boot partition of the SD card from another computer. When the Pi boots, it looks for the ssh file. If it is found, SSH is enabled and the file is deleted. The content of the file does not matter; it could contain text, or nothing at all.
Then once its booted and logged in, configure ssh to stay on via
sudo systemctl enable ssh sudo systemctl start ssh
Got that all set up and now: the goal was doing time lapse and the awesome RasPi foundation folks have provided a timelapse howto even
raspistill -o test.jpg It works!
Reading docs, it says it will be a H264 (or MJPEG!) video camera to lan if you ask it to be. with all the lovely hardware options exposed by their nice little CLI apps. awesome. 15 years ago I spent considerable time and effort to achieve something similar, so let's see just how hard it is today.
Looking at a picamera docs example, not hard at all.
([6 second exposure] the maximum the Pi V1 camera module is capable of; the V2 camera module can manage 10 second exposures)
interesting fact. There's all sorts of interesting things i can see to do already, without even looking intot he tools I know exist with OpenCV etc. Later.
picamera API reference for docs on attributes like hflip etc.
In a couple hours, I've got a LAN ready webstreaming camera on a 2ft goose-neck mount fully ready for further customization depending on just what exactly she wants to do. I'm thinking a live feedback monitor she can see and high quality frames every second or so we can further decimate as needed for making the real videos. We shall see.
My python web streaming script, thus far:
import io import picamera import logging import socketserver from threading import Condition from http import server HEIGHT = 1024 WIDTH = 768 FPS = 10 PORT= 8000 PAGE="""\ <html> <head> <title>picamera MJPEG streaming demo</title> </head> <body> <h1>PiCamera MJPEG Streaming Demo</h1> <img src="stream.mjpg" width="%s" height="%s" /> </body> </html> """ PAGE = PAGE % (HEIGHT,WIDTH) class StreamingOutput(object): def __init__(self): self.frame = None self.buffer = io.BytesIO() self.condition = Condition() def write(self, buf): if buf.startswith(b'\xff\xd8'): # New frame, copy the existing buffer's content and notify all # clients it's available self.buffer.truncate() with self.condition: self.frame = self.buffer.getvalue() self.condition.notify_all() self.buffer.seek(0) return self.buffer.write(buf) class StreamingHandler(server.BaseHTTPRequestHandler): def do_GET(self): if self.path == '/': self.send_response(301) self.send_header('Location', '/index.html') self.end_headers() elif self.path == '/index.html': content = PAGE.encode('utf-8') self.send_response(200) self.send_header('Content-Type', 'text/html') self.send_header('Content-Length', len(content)) self.end_headers() self.wfile.write(content) elif self.path == '/stream.mjpg': self.send_response(200) self.send_header('Age', 0) self.send_header('Cache-Control', 'no-cache, private') self.send_header('Pragma', 'no-cache') self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME') self.end_headers() try: while True: with output.condition: output.condition.wait() frame = output.frame self.wfile.write(b'--FRAME\r\n') self.send_header('Content-Type', 'image/jpeg') self.send_header('Content-Length', len(frame)) self.end_headers() self.wfile.write(frame) self.wfile.write(b'\r\n') except Exception as e: logging.warning( 'Removed streaming client %s: %s', self.client_address, str(e)) else: self.send_error(404) self.end_headers() class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer): allow_reuse_address = True daemon_threads = True with picamera.PiCamera(resolution=(HEIGHT,WIDTH), framerate=FPS) as camera: output = StreamingOutput() camera.hflip=True camera.vflip=True camera.exposure_mode='backlight' camera.meter_mode='backlit' camera.start_recording(output, format='mjpeg') try: address = ('', PORT) server = StreamingServer(address, StreamingHandler) server.serve_forever() finally: camera.stop_recording()