Besoin aide en programmation python [résolu]


#1

Bonjour tout le monde
je suis nouveau ici et j’ai deja besoin de votre aide.
Pour mon mariage j’ai fait un photobooth qui fonctionne pour ca pas de soucis.
je l’est donc fait avec un raspberry 3 b+ je me suis debrouille à trouver du code pour faire fonctionner le photobooth .
seulement j’aimerais pouvoir enregistrer les photos directement sur un disque dur externe ou une cle usb de 128 go que j’ai .
seulement je ne sais vraiment pas comment faire j’ai cherche sur internet mais rien de probant.
voici mon code :
mon fichier camera-config.yaml

#Photo Booth Config:
“CAMERA_BUTTON_PIN” : 21 # GPIO pin that is connected to ‘take photo’ button
“EXIT_BUTTON_PIN” : 13 # GPIO pin that is connected to ‘exit’ button (optional)
“TOTAL_PICS” : 4 # Number of pics to be taken
“PREP_DELAY” : 4 # Number of seconds as users prepare to have photo taken, before countdown commences
“COUNTDOWN” : 3 # Number of seconds to count down from
#GPIO Debounce Duration

(This may help avoid “phantom presses” caused by electronic interference)

“DEBOUNCE_TIME” : 0.05 # Min duration (seconds) button is required to be “pressed in” for.

Take photos at this resolution:

“PHOTO_W” : 3280
“PHOTO_H” : 2464
#Note:

- The max resolution for PiCamera v2, is: 3280x2464 , assuming you are running the latest firmware.

- To upgrade your firmware, please run:

sudo apt-get dist-upgrade

Resolution of the photo booth display:

“SCREEN_W” : 1050
“SCREEN_H” : 800

Camera setup

“CAMERA_ROTATION” : 0 # Rotation of the camera
“CAMERA_HFLIP” : True # When preparing for photos, the preview will be flipped horizontally.

Primary folder to save images to (required):

“SAVE_RAW_IMAGES_FOLDER” : “photos”

Additional locations where images will be saved to (optional):

“COPY_IMAGES_TO” : [“photos-IN”]

Test purposes only:

“TESTMODE_AUTOPRESS_BUTTON” : False # Should the button be automatically pressed? (only used for testing)

mon fichier camera.py

#!/usr/bin/env python
“”"
Raspberry Pi Photo Booth

This code is intended to be runs on a Raspberry Pi.
Currently both Python 2 and Python 3 are supported.

You can modify the config via [camera-config.yaml].
(The 1st time the code is run [camera-config.yaml] will be created based on [camera-config.example.yaml].
“”"
author = ‘Jibbius (Jack Barker)’
version = ‘2.2’

#Standard imports
from time import sleep
from shutil import copy2
import sys
import datetime
import os

#Need to do this early, in case import below fails:
REAL_PATH = os.path.dirname(os.path.realpath(file))

#Additional Imports
try:
from PIL import Image
from ruamel import yaml
import picamera
import RPi.GPIO as GPIO

except ImportError as missing_module:
print(’--------------------------------------------’)
print(‘ERROR:’)
print(missing_module)
print(’’)
print(’ - Please run the following command(s) to resolve:’)
if sys.version_info < (3,0):
print(’ pip install -r ’ + REAL_PATH + ‘/requirements.txt’)
else:
print(’ python3 -m pip install -r ’ + REAL_PATH + ‘/requirements.txt’)
print(’’)
sys.exit()

#############################

Load config from file

#############################
PATH_TO_CONFIG = REAL_PATH + ‘/camera-config.yaml’
PATH_TO_CONFIG_EXAMPLE = REAL_PATH + ‘/camera-config.example.yaml’

#Check if config file exists
if not os.path.exists(PATH_TO_CONFIG):
#Create a new config file, using the example file
print(‘Config file was not found. Creating:’ + PATH_TO_CONFIG)
copy2(PATH_TO_CONFIG_EXAMPLE, PATH_TO_CONFIG)

#Read config file using YAML interpreter
with open(PATH_TO_CONFIG, ‘r’) as stream:
CONFIG = {}
try:
CONFIG = yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)

#Required config
try:
# Each of the following varibles, is now configured within [camera-config.yaml]:
CAMERA_BUTTON_PIN = CONFIG[‘CAMERA_BUTTON_PIN’]
EXIT_BUTTON_PIN = CONFIG[‘EXIT_BUTTON_PIN’]
TOTAL_PICS = CONFIG[‘TOTAL_PICS’]
PREP_DELAY = CONFIG[‘PREP_DELAY’]
COUNTDOWN = CONFIG[‘COUNTDOWN’]
PHOTO_W = CONFIG[‘PHOTO_W’]
PHOTO_H = CONFIG[‘PHOTO_H’]
SCREEN_W = CONFIG[‘SCREEN_W’]
SCREEN_H = CONFIG[‘SCREEN_H’]
CAMERA_ROTATION = CONFIG[‘CAMERA_ROTATION’]
CAMERA_HFLIP = CONFIG[‘CAMERA_HFLIP’]
DEBOUNCE_TIME = CONFIG[‘DEBOUNCE_TIME’]
TESTMODE_AUTOPRESS_BUTTON = CONFIG[‘TESTMODE_AUTOPRESS_BUTTON’]
SAVE_RAW_IMAGES_FOLDER = CONFIG[‘SAVE_RAW_IMAGES_FOLDER’]

except KeyError as exc:
print(’’)
print(‘ERROR:’)
print(’ - Problems exist within configuration file: [’ + PATH_TO_CONFIG + ‘].’)
print(’ - The expected configuration item ’ + str(exc) + ’ was not found.’)
print(’ - Please refer to the example file [’ + PATH_TO_CONFIG_EXAMPLE + ‘], for reference.’)
print(’’)
sys.exit()

#Optional config
COPY_IMAGES_TO = []
try:
if isinstance(CONFIG[“COPY_IMAGES_TO”], list):
COPY_IMAGES_TO.extend( CONFIG[“COPY_IMAGES_TO”] )
else:
COPY_IMAGES_TO.append( CONFIG[“COPY_IMAGES_TO”] )

except KeyError as exc:
pass

##############################

Setup Objects and Pins

##############################
#Setup GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(CAMERA_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(EXIT_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

CAMERA = picamera.PiCamera()
CAMERA.rotation = CAMERA_ROTATION
CAMERA.annotate_text_size = 80
CAMERA.resolution = (PHOTO_W, PHOTO_H)
CAMERA.hflip = CAMERA_HFLIP

########################

Helper Functions

########################
def health_test_required_folders():
folders_list=[SAVE_RAW_IMAGES_FOLDER]
folders_list.extend(COPY_IMAGES_TO)
folders_checked=[]

for folder in folders_list:
    if folder not in folders_checked:
        folders_checked.append(folder)
    else:
        print('ERROR: Cannot use same folder path ('+folder+') twice. Refer config file.')

    #Create folder if doesn't exist
    if not os.path.exists(folder):
        print('Creating folder: ' + folder)
        os.makedirs(folder)

def print_overlay(string_to_print):
“”"
Writes a string to both [i] the console, and [ii] CAMERA.annotate_text
“”"
print(string_to_print)
CAMERA.annotate_text = string_to_print

def get_base_filename_for_images():
“”"
For each photo-capture cycle, a common base filename shall be used,
based on the current timestamp.

Example:
${ProjectRoot}/photos/2017-12-31_23-59-59

The example above, will later result in:
${ProjectRoot}/photos/2017-12-31_23-59-59_1of4.png, being used as a filename.
"""

base_filename = str(datetime.datetime.now()).split('.')[0]
base_filename = base_filename.replace(' ', '_')
base_filename = base_filename.replace(':', '-')

base_filepath = REAL_PATH + '/' + SAVE_RAW_IMAGES_FOLDER + '/' + base_filename

return base_filepath

def remove_overlay(overlay_id):
“”"
If there is an overlay, remove it
“”"
if overlay_id != -1:
CAMERA.remove_overlay(overlay_id)

overlay one image on screen

def overlay_image(image_path, duration=0, layer=3, mode=‘RGB’):
“”"
Add an overlay (and sleep for an optional duration).
If sleep duration is not supplied, then overlay will need to be removed later.
This function returns an overlay id, which can be used to remove_overlay(id).
“”"

# Load the (arbitrarily sized) image
img = Image.open(image_path)

if( img.size[0] > SCREEN_W):
    # To avoid memory issues associated with large images, we are going to resize image to match our screen's size:
    basewidth = SCREEN_W
    wpercent = (basewidth/float(img.size[0]))
    hsize = int((float(img.size[1])*float(wpercent)))
    img = img.resize((basewidth,hsize), Image.ANTIALIAS)

# "
#   The camera`s block size is 32x16 so any image data
#   provided to a renderer must have a width which is a
#   multiple of 32, and a height which is a multiple of
#   16.
# "
# Refer:
# http://picamera.readthedocs.io/en/release-1.10/recipes1.html#overlaying-images-on-the-preview

# Create an image padded to the required size with mode 'RGB' / 'RGBA'
pad = Image.new(mode, (
    ((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))

#Get the padded image data
try:
    padded_img_data = pad.tobytes()
except AttributeError:
    padded_img_data = pad.tostring() # Note: tostring() is deprecated in PIL v3.x

# Add the overlay with the padded image as the source,
# but the original image's dimensions
o_id = CAMERA.add_overlay(padded_img_data, size=img.size)
o_id.layer = layer

if duration > 0:
    sleep(duration)
    CAMERA.remove_overlay(o_id)
    o_id = -1 # '-1' indicates there is no overlay

return o_id # if we have an overlay (o_id > 0), we will need to remove it later

###############

Screens

###############
def prep_for_photo_screen(photo_number):
“”"
Prompt the user to get ready for the next photo
“”"

#Get ready for the next photo
get_ready_image = REAL_PATH + '/assets/get_ready_' + str(photo_number) + '.png'
overlay_image(get_ready_image, PREP_DELAY, 3, 'RGBA')

def taking_photo(photo_number, filename_prefix):
“”"
This function captures the photo
“”"

#get filename to use
filename = filename_prefix + '_' + str(photo_number) + 'of'+ str(TOTAL_PICS)+'.jpg'

#countdown from 3, and display countdown on screen
for counter in range(COUNTDOWN, 0, -1):
    print_overlay("             ..." + str(counter))
    sleep(1)

#Take still
CAMERA.annotate_text = ''
CAMERA.capture(filename)
print('Photo (' + str(photo_number) + ') saved: ' + filename)
return filename

def playback_screen(filename_prefix):
“”"
Final screen before main loop restarts
“”"

#Processing
print('Processing...')
processing_image = REAL_PATH + '/assets/processing.png'
overlay_image(processing_image, 2)

#Playback
prev_overlay = False
for photo_number in range(1, TOTAL_PICS + 1):
    filename = filename_prefix + '_' + str(photo_number) + 'of'+ str(TOTAL_PICS)+'.jpg'
    this_overlay = overlay_image(filename, False, (3 + TOTAL_PICS))
    # The idea here, is only remove the previous overlay after a new overlay is added.
    if prev_overlay:
        remove_overlay(prev_overlay)
    sleep(2)
    prev_overlay = this_overlay

remove_overlay(prev_overlay)

#All done
print('All done!')
finished_image = REAL_PATH + '/assets/all_done_delayed_upload.png'
overlay_image(finished_image, 5)

def main():
“”"
Main program loop
“”"

#Start Program
print('Welcome to the photo booth!')
print('(version ' + __version__ + ')')
print('')
print('Press the \'Take photo\' button to take a photo')
print('Use [Ctrl] + [\\] to exit')
print('')

#Setup any required folders (if missing)
health_test_required_folders()

#Start camera preview
CAMERA.start_preview(resolution=(SCREEN_W, SCREEN_H))

#Display intro screen
intro_image_1 = REAL_PATH + '/assets/intro_1.png'
intro_image_2 = REAL_PATH + '/assets/intro_2.png'
overlay_1 = overlay_image(intro_image_1, 0, 3)
overlay_2 = overlay_image(intro_image_2, 0, 4)

#Wait for someone to push the button
i = 0
blink_speed = 10

#Use falling edge detection to see if button is being pushed in
GPIO.add_event_detect(CAMERA_BUTTON_PIN, GPIO.FALLING)
GPIO.add_event_detect(EXIT_BUTTON_PIN, GPIO.FALLING)

while True:
    photo_button_is_pressed = None
    exit_button_is_pressed = None

    if GPIO.event_detected(CAMERA_BUTTON_PIN):
        sleep(DEBOUNCE_TIME)
        if GPIO.input(CAMERA_BUTTON_PIN) == 0:
            photo_button_is_pressed = True

    if GPIO.event_detected(EXIT_BUTTON_PIN):
        sleep(DEBOUNCE_TIME)
        if GPIO.input(EXIT_BUTTON_PIN) == 0:
            exit_button_is_pressed = True

    if exit_button_is_pressed is not None:
        return #Exit the photo booth

    if TESTMODE_AUTOPRESS_BUTTON:
        photo_button_is_pressed = True

    #Stay inside loop, until button is pressed
    if photo_button_is_pressed is None:

        #After every 10 cycles, alternate the overlay
        i = i+1
        if i == blink_speed:
            overlay_2.alpha = 255
        elif i == (2 * blink_speed):
            overlay_2.alpha = 0
            i = 0

        #Regardless, restart loop
        sleep(0.1)
        continue

    #Button has been pressed!
    print('Button pressed! You folks are in for a treat.')

    #Silence GPIO detection
    GPIO.remove_event_detect(CAMERA_BUTTON_PIN)
    GPIO.remove_event_detect(EXIT_BUTTON_PIN)

    #Get filenames for images
    filename_prefix = get_base_filename_for_images()
    remove_overlay(overlay_2)
    remove_overlay(overlay_1)

    photo_filenames = []
    for photo_number in range(1, TOTAL_PICS + 1):
        prep_for_photo_screen(photo_number)
        fname = taking_photo(photo_number, filename_prefix)
        photo_filenames.append(fname)

    #thanks for playing
    playback_screen(filename_prefix)

    #Save photos into additional folders (for post-processing/backup... etc.)
    for dest in COPY_IMAGES_TO:
        for src in photo_filenames:
            print(src + ' -> ' + dest)
            copy2(src, dest)

    # If we were doing a test run, exit here.
    if TESTMODE_AUTOPRESS_BUTTON:
        break

    # Otherwise, display intro screen again
    overlay_1 = overlay_image(intro_image_1, 0, 3)
    overlay_2 = overlay_image(intro_image_2, 0, 4)
    GPIO.add_event_detect(CAMERA_BUTTON_PIN, GPIO.FALLING)
    GPIO.add_event_detect(EXIT_BUTTON_PIN, GPIO.FALLING)
    print('Press the button to take a photo')

if name == “main”:
try:
main()

except KeyboardInterrupt:
    print('Goodbye')

finally:
    CAMERA.stop_preview()
    CAMERA.close()
    GPIO.cleanup()
    sys.exit()

si vous pouvez m’aidez ca serait cool
merci d’avance


#2

Bonjour,

As-tu essayé de changer ses 2 paramètre vers le chemin du disque externe ?

A+


#3

salut et merci d’avoir prit le temps.
j’ai essaye mais je pense que j’ai du mal m’y prendre.
je met juste le chemin ou alors y a une facon precise de le mettre?


#4

Salut,

Hyper long ce code :-o
Faut avoir un chemin vers le lieu de stockage.
Ce lieu pourrait être du type /media/pi/ (de mémoire en passant et sans être sur un Rpi)

Perso mon code est bcp plus court et le chemin et clairement noté avec
chemin_photo = '/home/pi/Desktop/photos/'+nom_image+'.jpeg'

Là, tes images sont stockées dans le dossier “photos” ; tu confirmes ?

++


#5

alors merci Nabla tu ma mis la puce à l’oreille.
en fait le code enregistre les photos sur le support sur lequel il est exécuté.
si je l’execute depuis ma carte sd systeme il enregistre les photos sur la carte sd.
par contre je viens d’essaye de l’executer de ma cle usb et il enregistre sur la cle usb.
je suppose donc que si je l’execute sur un disque dur externe cela sera pareil.
en gros mon soucis est regle d’une drole de facon. j’avais essaye tout les chemin ca marche jamais .
merci a vous en tout cas j’y aurai pas pense sans vos messages


#6

Re,

Certaines personnes disent que je ne vois pas le monde de la même façon que tout le monde.
Faut croire que parfois, ça aide :slight_smile:

Si ton souci est réglé, tu peux éditer ton premier message afin d’insérer [Résolu] dans le titre ?
Merci,

Et Merci @jelopo qui a pris le temps (lui) de lire ton code afin d’en tirer la zone où il était question du lieu de sauvegarde.

@+