Created
September 21, 2016 15:48
-
-
Save emm-ess/dcd0831f97f302e4740591a9efd990c0 to your computer and use it in GitHub Desktop.
Basic script for listening to button presses and taking photos on a Raspberry Pi. It's work in progress so...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import os | |
import sys | |
import getopt | |
import io | |
import picamera | |
import RPi.GPIO as GPIO | |
import datetime | |
from PIL import Image | |
import threading | |
config = {} | |
config['dir'] = 'photos/' | |
config['numberOfPhotos'] = 4 | |
config['imgSize'] = 2464 | |
config['inputPin'] = 23 | |
config['outputPin'] = 15 | |
config['lightPin'] = 14 | |
config['indicator1Pin'] = 24 | |
config['indicator2Pin'] = 25 | |
# 0 -> Display only | |
# 1 -> LEDs only | |
config['countdownMode'] = 1 | |
cam = None | |
stream = None | |
hotSince = None | |
class countdownThread (threading.Thread): | |
def __init__(self, threadID, name, method, led): | |
threading.Thread.__init__(self) | |
self.threadID = threadID | |
self.name = name | |
self.method = method | |
self.led = led | |
self.time = 10.0 | |
def run(self): | |
sleep = 0.1 | |
for i in range(0, 10): | |
GPIO.output(self.led, GPIO.HIGH) | |
time.sleep(sleep) | |
GPIO.output(self.led, GPIO.LOW) | |
time.sleep(1 - sleep) | |
sleep += 0.1 | |
def createFolderStructure(): | |
if not os.path.exists(config['dir']): | |
os.makedirs(config['dir']) | |
def countdown(): | |
if config['countdownMode'] == 0: | |
countdownDisplay() | |
elif config['countdownMode'] == 1: | |
countdownLED() | |
def countdownDisplay(): | |
# o = None | |
for i in reversed(range(0, 10)): | |
num = i + 1 | |
cam.annotate_text = '%s' % num | |
# print(i) | |
# proc = subprocess.Popen(["./pngview", "-l", "4", "./overlays/countdown-3.png"]) # ./pngview -l 3 ./overlays/countdown-3.png | |
# img = config['overlays']['countdown'][i] | |
# # img.convert('RGB') | |
# pad = Image.new('RGB', ( | |
# ((img.size[0] + 31) // 32) * 32, | |
# ((img.size[1] + 15) // 16) * 16, | |
# )) | |
# # Paste the original image into the padded one | |
# pad.paste(img, (0, 0)) | |
# if not o: | |
# o = cam.add_overlay(pad.tobytes(), layer=3, size=img.size, alpha=128) | |
# else: | |
# o.update(img.tostring()) | |
time.sleep(1) | |
# os.kill(proc.pid, signal.SIGTERM) | |
# proc.communicate() | |
# cam.remove_overlay(o) | |
cam.annotate_text = '' | |
def countdownLED(): | |
threads = [] | |
thread1 = countdownThread(1, "Thread-1", "lin", config['indicator1Pin']) | |
thread2 = countdownThread(2, "Thread-2", "log", config['indicator2Pin']) | |
thread1.start() | |
thread2.start() | |
threads.append(thread1) | |
threads.append(thread2) | |
for t in threads: | |
t.join(10) | |
def handleButtonPress(channel): | |
now = datetime.datetime.now() | |
if (now - hotSince).total_seconds() > 0.5: | |
unsetButtonDetection() | |
takePhotos() | |
setButtonDetection() | |
def unsetButtonDetection(): | |
# GPIO.remove_event_detect(config['inputPin']) | |
GPIO.output(config['outputPin'], GPIO.LOW) | |
def setButtonDetection(): | |
GPIO.output(config['outputPin'], GPIO.HIGH) | |
# tell the GPIO library to look out for an | |
# event on pin 23 and deal with it by calling | |
# the buttonEventHandler function | |
global hotSince | |
hotSince = datetime.datetime.now() | |
def takePhotos(): | |
global stream | |
imgs = [] | |
timeStamp = '{:%Y%m%d_%H%M%S}'.format(datetime.datetime.now()) | |
print('take pictures: ' + timeStamp) | |
# proc = subprocess.Popen(["./pngview", "-l", "4", "./overlays/image-0.png"]) | |
countdown() | |
# Now fix the values | |
# camera.shutter_speed = camera.exposure_speed | |
# camera.exposure_mode = 'off' | |
# g = camera.awb_gains | |
# camera.awb_mode = 'off' | |
# camera.awb_gains = g | |
for i, filename in enumerate(cam.capture_continuous(stream, 'jpeg')): | |
print('Captured image %s' % i) | |
stream.seek(0) | |
img = Image.open(stream) | |
imgs.append(img.copy()) | |
stream.seek(0) | |
if i == config['numberOfPhotos'] - 1: | |
# os.kill(proc.pid, signal.SIGTERM) | |
break | |
else: | |
# os.kill(proc.pid, signal.SIGTERM) | |
# proc = subprocess.Popen(["./pngview", "-l", "4", "./overlays/image-%s.png" % i]) | |
countdown() | |
# Turn automation back on | |
# camera.exposure_mode = 'auto' | |
# camera.awb_mode = 'auto' | |
combineImages(timeStamp, imgs) | |
def combineImages(timeStamp, imgs): | |
try: | |
print("copying") | |
img = Image.new('RGB', (config['imgSize'] * 2, config['imgSize'] * 2)) | |
img.paste(imgs[0], (0, 0)) | |
img.paste(imgs[1], (config['imgSize'], 0)) | |
img.paste(imgs[2], (0, config['imgSize'])) | |
img.paste(imgs[3], (config['imgSize'], config['imgSize'])) | |
print("saving") | |
img.save(config['dir'] + timeStamp + '.jpg', 'JPEG') | |
print("saved") | |
except IOError: | |
print("IOError") | |
def usage(): | |
print("Usage: python3 fotomat.py --dir photos --photos 4 --size 2464") | |
def getOptions(argv): | |
global config | |
try: | |
opts, args = getopt.getopt(argv, "d:p:s:", ["dir=", "photos=", "size="]) | |
except getopt.GetoptError: | |
usage() | |
sys.exit(2) | |
for opt, arg in opts: | |
if opt in ("-d", "--dir"): | |
config['dir'] = arg.strip() | |
elif opt in ("-p", "--photos"): | |
# TODO | |
# config['numberOfPhotos'] = arg | |
pass | |
elif opt in ("-s", "--size"): | |
config['size'] = arg | |
def pushOverlaysIntoArray(arr, prefix, max): | |
for i in range(0, max): | |
img = Image.open(prefix + '-%s.png' % i) | |
arr.append(img.copy()) | |
def loadOverlays(): | |
global config | |
config['overlays'] = {} | |
config['overlays']['image'] = [] | |
pushOverlaysIntoArray(config['overlays']['image'], './overlays/image', 4) | |
config['overlays']['countdown'] = [] | |
pushOverlaysIntoArray( config['overlays']['countdown'], './overlays/countdown', 10) | |
def main(argv): | |
getOptions(argv) | |
# loadOverlays() | |
# tell the GPIO module that we want to use | |
# the chip's pin numbering scheme | |
GPIO.setmode(GPIO.BCM) | |
GPIO.setup(config['outputPin'], GPIO.OUT) | |
GPIO.setup(config['lightPin'], GPIO.OUT) | |
GPIO.setup(config['indicator1Pin'], GPIO.OUT) | |
GPIO.setup(config['indicator2Pin'], GPIO.OUT) | |
# setup pin 23 as an input | |
GPIO.setup(config['inputPin'], GPIO.IN, pull_up_down=GPIO.PUD_UP) | |
setButtonDetection() | |
GPIO.add_event_detect(config['inputPin'], GPIO.FALLING, handleButtonPress, 200) | |
createFolderStructure() | |
with picamera.PiCamera() as camera: | |
global cam | |
global stream | |
stream = io.BytesIO() | |
cam = camera | |
camera.annotate_text_size = 128 | |
camera.resolution = (config['imgSize'], config['imgSize']) | |
camera.flash_mode = 'on' | |
camera.rotation = 90 | |
camera.start_preview() | |
# camera.exif_tags['IFD0.Artist'] = 'Me!' | |
# camera.exif_tags['IFD0.Copyright'] = 'Copyright (c) 2013 Me!' | |
try: | |
while True: | |
pass | |
except KeyboardInterrupt: | |
pass | |
camera.stop_preview() | |
GPIO.cleanup() | |
stream.close() | |
if __name__ == "__main__": | |
main(sys.argv[1:]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment