first commit
15
.pip/pip.log
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
------------------------------------------------------------
|
||||||
|
/usr/bin/pip run on Sat Nov 8 14:03:54 2014
|
||||||
|
Cannot uninstall requirement pil, not installed
|
||||||
|
|
||||||
|
Exception information:
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", line 104, in main
|
||||||
|
status = self.run(options, args)
|
||||||
|
File "/usr/lib/python2.7/dist-packages/pip/commands/uninstall.py", line 41, in run
|
||||||
|
requirement_set.uninstall(auto_confirm=options.yes)
|
||||||
|
File "/usr/lib/python2.7/dist-packages/pip/req.py", line 862, in uninstall
|
||||||
|
req.uninstall(auto_confirm=auto_confirm)
|
||||||
|
File "/usr/lib/python2.7/dist-packages/pip/req.py", line 410, in uninstall
|
||||||
|
raise UninstallationError("Cannot uninstall requirement %s, not installed" % (self.name,))
|
||||||
|
UninstallationError: Cannot uninstall requirement pil, not installed
|
22
.profile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# ~/.profile: executed by the command interpreter for login shells.
|
||||||
|
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
|
||||||
|
# exists.
|
||||||
|
# see /usr/share/doc/bash/examples/startup-files for examples.
|
||||||
|
# the files are located in the bash-doc package.
|
||||||
|
|
||||||
|
# the default umask is set in /etc/profile; for setting the umask
|
||||||
|
# for ssh logins, install and configure the libpam-umask package.
|
||||||
|
#umask 022
|
||||||
|
|
||||||
|
# if running bash
|
||||||
|
if [ -n "$BASH_VERSION" ]; then
|
||||||
|
# include .bashrc if it exists
|
||||||
|
if [ -f "$HOME/.bashrc" ]; then
|
||||||
|
. "$HOME/.bashrc"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set PATH so it includes user's private bin if it exists
|
||||||
|
if [ -d "$HOME/bin" ] ; then
|
||||||
|
PATH="$HOME/bin:$PATH"
|
||||||
|
fi
|
BIN
OrignalImages/1415458989/combined.jpg
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
OrignalImages/1415458989/image1.jpg
Normal file
After Width: | Height: | Size: 194 KiB |
BIN
OrignalImages/1415458989/image2.jpg
Normal file
After Width: | Height: | Size: 194 KiB |
BIN
OrignalImages/1415458989/image3.jpg
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
OrignalImages/1415458989/image4.jpg
Normal file
After Width: | Height: | Size: 194 KiB |
341
Photobooth.py
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
# Raspberry Pi - Photo Booth
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, John Croucher - www.jcroucher.com
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
# materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# 3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software without specific
|
||||||
|
# prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
# THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
|
GPIO.setmode(GPIO.BOARD)
|
||||||
|
import tweepy
|
||||||
|
import time
|
||||||
|
from threading import Thread
|
||||||
|
from subprocess import call
|
||||||
|
from datetime import datetime
|
||||||
|
import picamera
|
||||||
|
import PIL
|
||||||
|
from PIL import Image
|
||||||
|
#import cups
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import pygame
|
||||||
|
import random
|
||||||
|
import requests
|
||||||
|
import urllib
|
||||||
|
buttonled = 7
|
||||||
|
flashled = 22
|
||||||
|
button = 18
|
||||||
|
|
||||||
|
slideshowRunning = True
|
||||||
|
basewidth = 177 # Used for merging the photos onto one
|
||||||
|
printPhoto = False
|
||||||
|
TweetPhoto = True
|
||||||
|
Combine = True
|
||||||
|
imgPath = '/home/pi/.images/tmp'
|
||||||
|
|
||||||
|
# Light big light
|
||||||
|
GPIO.setup(buttonled, GPIO.OUT) ## Setup GPIO Pin 7 to OUT
|
||||||
|
GPIO.output(buttonled, 1) ## Turn on GPIO pin 7
|
||||||
|
|
||||||
|
# Push button for starting the photo sequence
|
||||||
|
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||||
|
|
||||||
|
# Display surface
|
||||||
|
pygame.init()
|
||||||
|
|
||||||
|
pygame.mouse.set_visible(0)
|
||||||
|
|
||||||
|
w = pygame.display.Info().current_w
|
||||||
|
h = pygame.display.Info().current_h
|
||||||
|
|
||||||
|
screenSize = (w, h)
|
||||||
|
|
||||||
|
screen = pygame.display.set_mode(screenSize, pygame.FULLSCREEN) # Full screen the display with no window
|
||||||
|
|
||||||
|
|
||||||
|
# Used for loading a random photo for the slideshow
|
||||||
|
def random_file(dir):
|
||||||
|
files = [os.path.join(path, filename)
|
||||||
|
for path, dirs, files in os.walk(dir)
|
||||||
|
for filename in files]
|
||||||
|
|
||||||
|
return random.choice(files)
|
||||||
|
|
||||||
|
|
||||||
|
def displayImage(file):
|
||||||
|
screen.fill((0,0,0))
|
||||||
|
|
||||||
|
img = pygame.image.load(file)
|
||||||
|
img = pygame.transform.scale(img,(w,h)) # Make the image full screen
|
||||||
|
screen.blit(img,(0,0))
|
||||||
|
pygame.display.flip() # update the display
|
||||||
|
|
||||||
|
|
||||||
|
# Display a random image
|
||||||
|
def slideshow():
|
||||||
|
while True:
|
||||||
|
|
||||||
|
if slideshowRunning == True:
|
||||||
|
|
||||||
|
checkEvents()
|
||||||
|
|
||||||
|
randomFile = random_file('/home/pi/.images')
|
||||||
|
|
||||||
|
displayImage(randomFile)
|
||||||
|
|
||||||
|
time.sleep(10) # pause
|
||||||
|
|
||||||
|
# Handle events like keypress
|
||||||
|
def checkEvents():
|
||||||
|
for event in pygame.event.get():
|
||||||
|
# Shutdown the application if quit event or escape key is pressed
|
||||||
|
if event.type == pygame.QUIT or ( event.type is pygame.KEYDOWN and event.key == pygame.K_ESCAPE ):
|
||||||
|
slideshowRunning = False
|
||||||
|
pygame.quit()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
if event.type is pygame.KEYDOWN and event.key == pygame.K_f: # Switch the display mode between full screen and windowed
|
||||||
|
if screen.get_flags() & pygame.FULLSCREEN:
|
||||||
|
pygame.display.set_mode(screenSize)
|
||||||
|
else:
|
||||||
|
pygame.display.set_mode(screenSize,pygame.FULLSCREEN)
|
||||||
|
|
||||||
|
# On screen text message
|
||||||
|
def displayStatus(status):
|
||||||
|
screen.fill((0,0,0))
|
||||||
|
|
||||||
|
font = pygame.font.SysFont("monospace",92)
|
||||||
|
text = font.render(status,True,(255,255,255))
|
||||||
|
|
||||||
|
# Display in the center of the screen
|
||||||
|
textrect = text.get_rect()
|
||||||
|
textrect.centerx = screen.get_rect().centerx
|
||||||
|
textrect.centery = screen.get_rect().centery
|
||||||
|
|
||||||
|
screen.blit(text,textrect)
|
||||||
|
|
||||||
|
pygame.display.flip() # update the display
|
||||||
|
|
||||||
|
|
||||||
|
# Merge all photos onto one ready for printing
|
||||||
|
def combineImages():
|
||||||
|
if Combine == True:
|
||||||
|
displayStatus('Saving')
|
||||||
|
|
||||||
|
# Do the merging
|
||||||
|
blankImage = Image.open('blank.jpg')
|
||||||
|
|
||||||
|
image1 = Image.open(imgPath + '/image1.jpg')
|
||||||
|
image1 = image1.resize((640,480))
|
||||||
|
blankImage.paste(image1, (0,0))
|
||||||
|
displayStatus('25%')
|
||||||
|
|
||||||
|
image2 = Image.open(imgPath + '/image2.jpg')
|
||||||
|
image2 = image2.resize((640,480))
|
||||||
|
blankImage.paste(image2, (0,480))
|
||||||
|
displayStatus('50%')
|
||||||
|
|
||||||
|
image3 = Image.open(imgPath + '/image3.jpg')
|
||||||
|
image3 = image3.resize((640,480))
|
||||||
|
blankImage.paste(image3, (640,0))
|
||||||
|
displayStatus('75%')
|
||||||
|
|
||||||
|
image4 = Image.open(imgPath + '/image4.jpg')
|
||||||
|
image4 = image4.resize((640,600))
|
||||||
|
blankImage.paste(image4, (640,480))
|
||||||
|
displayStatus('100%')
|
||||||
|
|
||||||
|
blankImage.save(imgPath + '/combined.jpg', 'JPEG', quality=80)
|
||||||
|
displayStatus('Saved')
|
||||||
|
|
||||||
|
# Check net
|
||||||
|
def CheckNet():
|
||||||
|
try :
|
||||||
|
stri = "https://www.google.com"
|
||||||
|
data = urllib.urlopen(stri)
|
||||||
|
Tweet()
|
||||||
|
except:
|
||||||
|
displayStatus('Offline')
|
||||||
|
time.sleep(3) # pause
|
||||||
|
|
||||||
|
|
||||||
|
# Upload to Twitter
|
||||||
|
def Tweet():
|
||||||
|
if Combine == True:
|
||||||
|
if TweetPhoto == True:
|
||||||
|
displayStatus('Tweeting')
|
||||||
|
|
||||||
|
# Consumer keys and access tokens, used for OAuth
|
||||||
|
consumer_key = 'DVW3lqng3wY6hE77L7HV3Pq6o'
|
||||||
|
consumer_secret = 'o8hOsaAGuDkoHyH8CjBrhhAYidf8KsyubAVhad6bAZDlP0nQ6U'
|
||||||
|
access_token = '2867471873-HPqS3vtqHUOJHnWskkZK4ofZNWM7laef6L1LTWa'
|
||||||
|
access_token_secret = 'rZbxlDLqlgGuHZRXSH2V2rMRzWJLAIXWSbxorpZrFgVDX'
|
||||||
|
|
||||||
|
# OAuth process, using the keys and tokens
|
||||||
|
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
|
||||||
|
auth.set_access_token(access_token, access_token_secret)
|
||||||
|
|
||||||
|
# Creation of the actual interface, using authentication
|
||||||
|
api = tweepy.API(auth)
|
||||||
|
|
||||||
|
# Send the tweet with photo
|
||||||
|
photo_path = imgPath + '/combined.jpg'
|
||||||
|
status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')
|
||||||
|
api.update_with_media(photo_path, status=status)
|
||||||
|
displayStatus('Complete')
|
||||||
|
|
||||||
|
if Combine == False:
|
||||||
|
if TweetPhoto == True:
|
||||||
|
displayStatus('Tweeting')
|
||||||
|
|
||||||
|
# Consumer keys and access tokens, used for OAuth
|
||||||
|
consumer_key = 'DVW3lqng3wY6hE77L7HV3Pq6o'
|
||||||
|
consumer_secret = 'o8hOsaAGuDkoHyH8CjBrhhAYidf8KsyubAVhad6bAZDlP0nQ6U'
|
||||||
|
access_token = '2867471873-HPqS3vtqHUOJHnWskkZK4ofZNWM7laef6L1LTWa'
|
||||||
|
access_token_secret = 'rZbxlDLqlgGuHZRXSH2V2rMRzWJLAIXWSbxorpZrFgVDX'
|
||||||
|
|
||||||
|
# OAuth process, using the keys and tokens
|
||||||
|
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
|
||||||
|
auth.set_access_token(access_token, access_token_secret)
|
||||||
|
|
||||||
|
# Creation of the actual interface, using authentication
|
||||||
|
api = tweepy.API(auth)
|
||||||
|
|
||||||
|
# Send the tweet with photo 1
|
||||||
|
displayStatus('25%')
|
||||||
|
photo_path = imgPath + '/image1.jpg'
|
||||||
|
status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')
|
||||||
|
api.update_with_media(photo_path, status=status)
|
||||||
|
|
||||||
|
# Send the tweet with photo 2
|
||||||
|
displayStatus('50%')
|
||||||
|
photo_path = imgPath + '/image2.jpg'
|
||||||
|
status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')
|
||||||
|
api.update_with_media(photo_path, status=status)
|
||||||
|
|
||||||
|
# Send the tweet with photo 3
|
||||||
|
displayStatus('75%')
|
||||||
|
photo_path = imgPath + '/image3.jpg'
|
||||||
|
status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')
|
||||||
|
api.update_with_media(photo_path, status=status)
|
||||||
|
|
||||||
|
# Send the tweet with photo 4
|
||||||
|
displayStatus('100%')
|
||||||
|
photo_path = imgPath + '/image4.jpg'
|
||||||
|
status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')
|
||||||
|
api.update_with_media(photo_path, status=status)
|
||||||
|
displayStatus('Complete')
|
||||||
|
|
||||||
|
# Print the photo
|
||||||
|
def printPhoto():
|
||||||
|
if printPhoto == True:
|
||||||
|
displayStatus('Printing')
|
||||||
|
|
||||||
|
conn = cups.Connection()
|
||||||
|
printers = conn.getPrinters()
|
||||||
|
printer_name = printers.keys()[0]
|
||||||
|
conn.printFile(printer_name, imgPath + '/combined.jpg',"TITLE",{})
|
||||||
|
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Combine Preview
|
||||||
|
def combinePre():
|
||||||
|
if Combine == True:
|
||||||
|
displayImage( imgPath + '/combined.jpg' ) # Display a preview of the combined image
|
||||||
|
|
||||||
|
|
||||||
|
# Thread for the slideshow
|
||||||
|
t = Thread(target=slideshow)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
with picamera.PiCamera() as camera:
|
||||||
|
|
||||||
|
while True:
|
||||||
|
checkEvents() # Needed to check for keypresses and close signals
|
||||||
|
|
||||||
|
# Putton press to start the photo sequence
|
||||||
|
input_state = GPIO.input(button)
|
||||||
|
if input_state == False:
|
||||||
|
|
||||||
|
GPIO.output(buttonled, 0) ## Turn off GPIO pin 7
|
||||||
|
|
||||||
|
# Stop the slideshow
|
||||||
|
slideshowRunning = False
|
||||||
|
displayStatus('')
|
||||||
|
|
||||||
|
# Start the camera preview
|
||||||
|
camera.hflip = True
|
||||||
|
camera.start_preview()
|
||||||
|
|
||||||
|
# Make the destination path for the photos
|
||||||
|
if not os.path.exists(imgPath):
|
||||||
|
os.mkdir(imgPath)
|
||||||
|
|
||||||
|
# Loop through the 4 photo taking sequences
|
||||||
|
GPIO.setup(flashled, GPIO.OUT) ## Setup GPIO Pin 22 to OUT
|
||||||
|
GPIO.output(flashled, 1) ## Turn on GPIO pin 22
|
||||||
|
i = datetime.now() #take time and date for filename
|
||||||
|
now = i.strftime('%Y%m%d-%H%M%S')
|
||||||
|
|
||||||
|
for pNum in range (1,5):
|
||||||
|
camera.annotate_text = 'Photo ' + str(pNum) + ' of 4'
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
for countDown in range (3,0,-1):
|
||||||
|
camera.annotate_text = str(countDown)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
camera.annotate_text = ''
|
||||||
|
#camera.resolution = (2560, 1920)
|
||||||
|
camera.resolution = (1280, 960)
|
||||||
|
os.system('mpg321 CSC.mp3 &')
|
||||||
|
camera.capture ( imgPath + '/image' + str(pNum) + '.jpg')
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# Stop the camera preview so we can return to the pygame surface
|
||||||
|
GPIO.output(flashled, 0) ## Turn on GPIO pin 7
|
||||||
|
camera.stop_preview()
|
||||||
|
|
||||||
|
combineImages()
|
||||||
|
|
||||||
|
CheckNet()
|
||||||
|
|
||||||
|
printPhoto()
|
||||||
|
|
||||||
|
combinePre()
|
||||||
|
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
# Move the temp files to a new dir based on the current timestamp so they can be retrieved later
|
||||||
|
os.rename(imgPath, '/home/pi/.images/' + str(int(time.time())))
|
||||||
|
|
||||||
|
GPIO.output(buttonled, 1) ## Turn on GPIO pin 7
|
||||||
|
|
||||||
|
# Restart the slideshow
|
||||||
|
slideshowRunning = True
|
||||||
|
|
8
autostart.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# launcher.sh
|
||||||
|
# navigate to home directory, then to this directory, then execute python script, then back home
|
||||||
|
|
||||||
|
cd /
|
||||||
|
cd home/pi
|
||||||
|
sudo python Photobooth.py
|
||||||
|
cd /
|
BIN
blank_boarder.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
blank_noboard.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
ocr_pi.png
Normal file
After Width: | Height: | Size: 5.6 KiB |